]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- remove from HEAD
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
dece6358
AM
1diff -urN linux-2.6.30.org/Documentation/ABI/testing/debugfs-aufs linux-2.6.30/Documentation/ABI/testing/debugfs-aufs
2--- linux-2.6.30.org/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
3+++ linux-2.6.30/Documentation/ABI/testing/debugfs-aufs 2009-07-21 08:54:18.000000000 +0200
1facf9fc 4@@ -0,0 +1,40 @@
5+What: /debug/aufs/si_<id>/
6+Date: March 2009
7+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
8+Description:
9+ Under /debug/aufs, a directory named si_<id> is created
10+ per aufs mount, where <id> is a unique id generated
11+ internally.
12+
13+What: /debug/aufs/si_<id>/xib
14+Date: March 2009
15+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
16+Description:
17+ It shows the consumed blocks by xib (External Inode Number
18+ Bitmap), its block size and file size.
19+ When the aufs mount option 'noxino' is specified, it
20+ will be empty. About XINO files, see
21+ Documentation/filesystems/aufs/aufs.5 in detail.
22+
23+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
24+Date: March 2009
25+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
26+Description:
27+ It shows the consumed blocks by xino (External Inode Number
28+ Translation Table), its link count, block size and file
29+ size.
30+ When the aufs mount option 'noxino' is specified, it
31+ will be empty. About XINO files, see
32+ Documentation/filesystems/aufs/aufs.5 in detail.
33+
34+What: /debug/aufs/si_<id>/xigen
35+Date: March 2009
36+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
37+Description:
38+ It shows the consumed blocks by xigen (External Inode
39+ Generation Table), its block size and file size.
40+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
41+ be created.
42+ When the aufs mount option 'noxino' is specified, it
43+ will be empty. About XINO files, see
44+ Documentation/filesystems/aufs/aufs.5 in detail.
dece6358
AM
45diff -urN linux-2.6.30.org/Documentation/ABI/testing/sysfs-aufs linux-2.6.30/Documentation/ABI/testing/sysfs-aufs
46--- linux-2.6.30.org/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
47+++ linux-2.6.30/Documentation/ABI/testing/sysfs-aufs 2009-07-21 08:54:18.000000000 +0200
1facf9fc 48@@ -0,0 +1,25 @@
49+What: /sys/fs/aufs/si_<id>/
50+Date: March 2009
51+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
52+Description:
53+ Under /sys/fs/aufs, a directory named si_<id> is created
54+ per aufs mount, where <id> is a unique id generated
55+ internally.
56+
57+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
58+Date: March 2009
59+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
60+Description:
61+ It shows the abolute path of a member directory (which
62+ is called branch) in aufs, and its permission.
63+
64+What: /sys/fs/aufs/si_<id>/xi_path
65+Date: March 2009
66+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
67+Description:
68+ It shows the abolute path of XINO (External Inode Number
69+ Bitmap, Translation Table and Generation Table) file
70+ even if it is the default path.
71+ When the aufs mount option 'noxino' is specified, it
72+ will be empty. About XINO files, see
73+ Documentation/filesystems/aufs/aufs.5 in detail.
dece6358
AM
74diff -urN linux-2.6.30.org/fs/aufs/aufs.h linux-2.6.30/fs/aufs/aufs.h
75--- linux-2.6.30.org/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
76+++ linux-2.6.30/fs/aufs/aufs.h 2009-07-21 08:54:18.000000000 +0200
1facf9fc 77@@ -0,0 +1,51 @@
1facf9fc 78+/*
79+ * Copyright (C) 2005-2009 Junjiro R. Okajima
80+ *
81+ * This program, aufs is free software; you can redistribute it and/or modify
82+ * it under the terms of the GNU General Public License as published by
83+ * the Free Software Foundation; either version 2 of the License, or
84+ * (at your option) any later version.
dece6358
AM
85+ *
86+ * This program is distributed in the hope that it will be useful,
87+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89+ * GNU General Public License for more details.
90+ *
91+ * You should have received a copy of the GNU General Public License
92+ * along with this program; if not, write to the Free Software
93+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 94+ */
95+
96+/*
97+ * all header files
98+ */
99+
100+#ifndef __AUFS_H__
101+#define __AUFS_H__
102+
103+#ifdef __KERNEL__
104+
1facf9fc 105+#include "debug.h"
106+
107+#include "branch.h"
108+#include "cpup.h"
109+#include "dcsub.h"
110+#include "dbgaufs.h"
111+#include "dentry.h"
112+#include "dir.h"
113+#include "file.h"
114+#include "fstype.h"
115+#include "inode.h"
116+#include "loop.h"
117+#include "module.h"
118+#include "opts.h"
119+#include "rwsem.h"
120+#include "spl.h"
121+#include "super.h"
122+#include "sysaufs.h"
123+#include "vfsub.h"
124+#include "whout.h"
125+#include "wkq.h"
126+
127+#endif /* __KERNEL__ */
128+#endif /* __AUFS_H__ */
dece6358
AM
129diff -urN linux-2.6.30.org/fs/aufs/branch.c linux-2.6.30/fs/aufs/branch.c
130--- linux-2.6.30.org/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
131+++ linux-2.6.30/fs/aufs/branch.c 2009-07-21 08:54:18.000000000 +0200
132@@ -0,0 +1,973 @@
1facf9fc 133+/*
134+ * Copyright (C) 2005-2009 Junjiro R. Okajima
135+ *
136+ * This program, aufs is free software; you can redistribute it and/or modify
137+ * it under the terms of the GNU General Public License as published by
138+ * the Free Software Foundation; either version 2 of the License, or
139+ * (at your option) any later version.
dece6358
AM
140+ *
141+ * This program is distributed in the hope that it will be useful,
142+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
143+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144+ * GNU General Public License for more details.
145+ *
146+ * You should have received a copy of the GNU General Public License
147+ * along with this program; if not, write to the Free Software
148+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 149+ */
150+
151+/*
152+ * branch management
153+ */
154+
dece6358 155+#include <linux/file.h>
1facf9fc 156+#include "aufs.h"
157+
158+/*
159+ * free a single branch
160+ */
161+static void au_br_do_free(struct au_branch *br)
162+{
163+ int i;
164+ struct au_wbr *wbr;
165+
166+ if (br->br_xino.xi_file)
167+ fput(br->br_xino.xi_file);
168+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
169+
170+ AuDebugOn(atomic_read(&br->br_count));
171+
172+ wbr = br->br_wbr;
173+ if (wbr) {
174+ for (i = 0; i < AuBrWh_Last; i++)
175+ dput(wbr->wbr_wh[i]);
176+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 177+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 178+ }
179+
180+ /* some filesystems acquire extra lock */
181+ lockdep_off();
182+ mntput(br->br_mnt);
183+ lockdep_on();
184+
185+ kfree(wbr);
186+ kfree(br);
187+}
188+
189+/*
190+ * frees all branches
191+ */
192+void au_br_free(struct au_sbinfo *sbinfo)
193+{
194+ aufs_bindex_t bmax;
195+ struct au_branch **br;
196+
dece6358
AM
197+ AuRwMustWriteLock(&sbinfo->si_rwsem);
198+
1facf9fc 199+ bmax = sbinfo->si_bend + 1;
200+ br = sbinfo->si_branch;
201+ while (bmax--)
202+ au_br_do_free(*br++);
203+}
204+
205+/*
206+ * find the index of a branch which is specified by @br_id.
207+ */
208+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
209+{
210+ aufs_bindex_t bindex, bend;
211+
212+ bend = au_sbend(sb);
213+ for (bindex = 0; bindex <= bend; bindex++)
214+ if (au_sbr_id(sb, bindex) == br_id)
215+ return bindex;
216+ return -1;
217+}
218+
219+/* ---------------------------------------------------------------------- */
220+
221+/*
222+ * add a branch
223+ */
224+
225+static int test_overlap(struct super_block *sb, struct dentry *h_d1,
226+ struct dentry *h_d2)
227+{
228+ if (unlikely(h_d1 == h_d2))
229+ return 1;
230+ return !!au_test_subdir(h_d1, h_d2)
231+ || !!au_test_subdir(h_d2, h_d1)
232+ || au_test_loopback_overlap(sb, h_d1, h_d2)
233+ || au_test_loopback_overlap(sb, h_d2, h_d1);
234+}
235+
236+/*
237+ * returns a newly allocated branch. @new_nbranch is a number of branches
238+ * after adding a branch.
239+ */
240+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
241+ int perm)
242+{
243+ struct au_branch *add_branch;
244+ struct dentry *root;
245+
246+ root = sb->s_root;
247+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
248+ if (unlikely(!add_branch))
249+ goto out;
250+
251+ add_branch->br_wbr = NULL;
252+ if (au_br_writable(perm)) {
253+ /* may be freed separately at changing the branch permission */
254+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
255+ GFP_NOFS);
256+ if (unlikely(!add_branch->br_wbr))
257+ goto out_br;
258+ }
259+
260+ if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch)
261+ || au_di_realloc(au_di(root), new_nbranch)
262+ || au_ii_realloc(au_ii(root->d_inode), new_nbranch)))
263+ goto out_wbr;
264+ return add_branch; /* success */
265+
266+ out_wbr:
267+ kfree(add_branch->br_wbr);
268+ out_br:
269+ kfree(add_branch);
270+ out:
271+ return ERR_PTR(-ENOMEM);
272+}
273+
274+/*
275+ * test if the branch permission is legal or not.
276+ */
277+static int test_br(struct inode *inode, int brperm, char *path)
278+{
279+ int err;
280+
281+ err = 0;
282+ if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
283+ AuErr("write permission for readonly mount or inode, %s\n",
284+ path);
285+ err = -EINVAL;
286+ }
287+
288+ return err;
289+}
290+
291+/*
292+ * returns:
293+ * 0: success, the caller will add it
294+ * plus: success, it is already unified, the caller should ignore it
295+ * minus: error
296+ */
297+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
298+{
299+ int err;
300+ aufs_bindex_t bend, bindex;
301+ struct dentry *root;
302+ struct inode *inode, *h_inode;
303+
304+ root = sb->s_root;
305+ bend = au_sbend(sb);
306+ if (unlikely(bend >= 0
307+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
308+ err = 1;
309+ if (!remount) {
310+ err = -EINVAL;
311+ AuErr("%s duplicated\n", add->pathname);
312+ }
313+ goto out;
314+ }
315+
316+ err = -ENOSPC; /* -E2BIG; */
317+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
318+ || AUFS_BRANCH_MAX - 1 <= bend)) {
319+ AuErr("number of branches exceeded %s\n", add->pathname);
320+ goto out;
321+ }
322+
323+ err = -EDOM;
324+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
325+ AuErr("bad index %d\n", add->bindex);
326+ goto out;
327+ }
328+
329+ inode = add->path.dentry->d_inode;
330+ err = -ENOENT;
331+ if (unlikely(!inode->i_nlink)) {
332+ AuErr("no existence %s\n", add->pathname);
333+ goto out;
334+ }
335+
336+ err = -EINVAL;
337+ if (unlikely(inode->i_sb == sb)) {
338+ AuErr("%s must be outside\n", add->pathname);
339+ goto out;
340+ }
341+
342+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
343+ AuErr("unsupported filesystem, %s (%s)\n",
344+ add->pathname, au_sbtype(inode->i_sb));
345+ goto out;
346+ }
347+
348+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
349+ if (unlikely(err))
350+ goto out;
351+
352+ if (bend < 0)
353+ return 0; /* success */
354+
355+ err = -EINVAL;
356+ for (bindex = 0; bindex <= bend; bindex++)
357+ if (unlikely(test_overlap(sb, add->path.dentry,
358+ au_h_dptr(root, bindex)))) {
359+ AuErr("%s is overlapped\n", add->pathname);
360+ goto out;
361+ }
362+
363+ err = 0;
364+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
365+ h_inode = au_h_dptr(root, 0)->d_inode;
366+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
367+ || h_inode->i_uid != inode->i_uid
368+ || h_inode->i_gid != inode->i_gid)
369+ AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
370+ add->pathname,
371+ inode->i_uid, inode->i_gid,
372+ (inode->i_mode & S_IALLUGO),
373+ h_inode->i_uid, h_inode->i_gid,
374+ (h_inode->i_mode & S_IALLUGO));
375+ }
376+
377+ out:
378+ return err;
379+}
380+
381+/*
382+ * initialize or clean the whiteouts for an adding branch
383+ */
384+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
385+ int new_perm, struct dentry *h_root)
386+{
387+ int err, old_perm;
388+ aufs_bindex_t bindex;
389+ struct mutex *h_mtx;
390+ struct au_wbr *wbr;
391+ struct au_hinode *hdir;
392+
393+ wbr = br->br_wbr;
394+ old_perm = br->br_perm;
395+ br->br_perm = new_perm;
396+ hdir = NULL;
397+ h_mtx = NULL;
398+ bindex = au_br_index(sb, br->br_id);
399+ if (0 <= bindex) {
400+ hdir = au_hi(sb->s_root->d_inode, bindex);
401+ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
402+ } else {
403+ h_mtx = &h_root->d_inode->i_mutex;
404+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
405+ }
406+ if (!wbr)
407+ err = au_wh_init(h_root, br, sb);
408+ else {
409+ wbr_wh_write_lock(wbr);
410+ err = au_wh_init(h_root, br, sb);
411+ wbr_wh_write_unlock(wbr);
412+ }
413+ if (hdir)
414+ au_hin_imtx_unlock(hdir);
415+ else
416+ mutex_unlock(h_mtx);
417+ br->br_perm = old_perm;
418+
419+ if (!err && wbr && !au_br_writable(new_perm)) {
420+ kfree(wbr);
421+ br->br_wbr = NULL;
422+ }
423+
424+ return err;
425+}
426+
427+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
428+ int perm, struct path *path)
429+{
430+ int err;
431+ struct au_wbr *wbr;
432+
433+ wbr = br->br_wbr;
dece6358 434+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 435+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
436+ atomic_set(&wbr->wbr_wh_running, 0);
437+ wbr->wbr_bytes = 0;
438+
439+ err = au_br_init_wh(sb, br, perm, path->dentry);
440+
441+ return err;
442+}
443+
444+/* intialize a new branch */
445+static int au_br_init(struct au_branch *br, struct super_block *sb,
446+ struct au_opt_add *add)
447+{
448+ int err;
449+
450+ err = 0;
451+ memset(&br->br_xino, 0, sizeof(br->br_xino));
452+ mutex_init(&br->br_xino.xi_nondir_mtx);
453+ br->br_perm = add->perm;
454+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
455+ atomic_set(&br->br_count, 0);
456+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
457+ atomic_set(&br->br_xino_running, 0);
458+ br->br_id = au_new_br_id(sb);
459+
460+ if (au_br_writable(add->perm)) {
461+ err = au_wbr_init(br, sb, add->perm, &add->path);
462+ if (unlikely(err))
463+ goto out;
464+ }
465+
466+ if (au_opt_test(au_mntflags(sb), XINO)) {
467+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
468+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
469+ if (unlikely(err)) {
470+ AuDebugOn(br->br_xino.xi_file);
471+ goto out;
472+ }
473+ }
474+
475+ sysaufs_br_init(br);
476+ mntget(add->path.mnt);
477+
478+ out:
479+ return err;
480+}
481+
482+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
483+ struct au_branch *br, aufs_bindex_t bend,
484+ aufs_bindex_t amount)
485+{
486+ struct au_branch **brp;
487+
dece6358
AM
488+ AuRwMustWriteLock(&sbinfo->si_rwsem);
489+
1facf9fc 490+ brp = sbinfo->si_branch + bindex;
491+ memmove(brp + 1, brp, sizeof(*brp) * amount);
492+ *brp = br;
493+ sbinfo->si_bend++;
494+ if (unlikely(bend < 0))
495+ sbinfo->si_bend = 0;
496+}
497+
498+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
499+ aufs_bindex_t bend, aufs_bindex_t amount)
500+{
501+ struct au_hdentry *hdp;
502+
503+ hdp = dinfo->di_hdentry + bindex;
504+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
505+ au_h_dentry_init(hdp);
506+ dinfo->di_bend++;
507+ if (unlikely(bend < 0))
508+ dinfo->di_bstart = 0;
509+}
510+
511+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
512+ aufs_bindex_t bend, aufs_bindex_t amount)
513+{
514+ struct au_hinode *hip;
515+
516+ hip = iinfo->ii_hinode + bindex;
517+ memmove(hip + 1, hip, sizeof(*hip) * amount);
518+ hip->hi_inode = NULL;
519+ au_hin_init(hip, NULL);
520+ iinfo->ii_bend++;
521+ if (unlikely(bend < 0))
522+ iinfo->ii_bstart = 0;
523+}
524+
525+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
526+ struct au_branch *br, aufs_bindex_t bindex)
527+{
528+ struct dentry *root;
529+ struct inode *root_inode;
530+ aufs_bindex_t bend, amount;
531+
532+ root = sb->s_root;
533+ root_inode = root->d_inode;
534+ au_plink_block_maintain(sb);
535+ bend = au_sbend(sb);
536+ amount = bend + 1 - bindex;
537+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
538+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
539+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
540+ au_set_h_dptr(root, bindex, dget(h_dentry));
541+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
542+ /*flags*/0);
543+}
544+
545+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
546+{
547+ int err;
548+ unsigned long long maxb;
549+ aufs_bindex_t bend, add_bindex;
550+ struct dentry *root, *h_dentry;
551+ struct inode *root_inode;
552+ struct au_branch *add_branch;
553+
554+ root = sb->s_root;
555+ root_inode = root->d_inode;
556+ IMustLock(root_inode);
557+ err = test_add(sb, add, remount);
558+ if (unlikely(err < 0))
559+ goto out;
560+ if (err) {
561+ err = 0;
562+ goto out; /* success */
563+ }
564+
565+ bend = au_sbend(sb);
566+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
567+ err = PTR_ERR(add_branch);
568+ if (IS_ERR(add_branch))
569+ goto out;
570+
571+ err = au_br_init(add_branch, sb, add);
572+ if (unlikely(err)) {
573+ au_br_do_free(add_branch);
574+ goto out;
575+ }
576+
577+ add_bindex = add->bindex;
578+ h_dentry = add->path.dentry;
579+ if (!remount)
580+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
581+ else {
582+ sysaufs_brs_del(sb, add_bindex);
583+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
584+ sysaufs_brs_add(sb, add_bindex);
585+ }
586+
587+ if (!add_bindex)
588+ au_cpup_attr_all(root_inode, /*force*/1);
589+ else
590+ au_add_nlink(root_inode, h_dentry->d_inode);
591+ maxb = h_dentry->d_sb->s_maxbytes;
592+ if (sb->s_maxbytes < maxb)
593+ sb->s_maxbytes = maxb;
594+
595+ /*
596+ * this test/set prevents aufs from handling unnecesary inotify events
597+ * of xino files, in a case of re-adding a writable branch which was
598+ * once detached from aufs.
599+ */
600+ if (au_xino_brid(sb) < 0
601+ && au_br_writable(add_branch->br_perm)
602+ && !au_test_fs_bad_xino(h_dentry->d_sb)
603+ && add_branch->br_xino.xi_file
604+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
605+ au_xino_brid_set(sb, add_branch->br_id);
606+
607+ out:
608+ return err;
609+}
610+
611+/* ---------------------------------------------------------------------- */
612+
613+/*
614+ * delete a branch
615+ */
616+
617+/* to show the line number, do not make it inlined function */
618+#define AuVerbose(do_info, fmt, args...) do { \
619+ if (do_info) \
620+ AuInfo(fmt, ##args); \
621+} while (0)
622+
623+/*
624+ * test if the branch is deletable or not.
625+ */
626+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
627+ unsigned int sigen)
628+{
629+ int err, i, j, ndentry;
630+ aufs_bindex_t bstart, bend;
631+ unsigned char verbose;
632+ struct au_dcsub_pages dpages;
633+ struct au_dpage *dpage;
634+ struct dentry *d;
635+ struct inode *inode;
636+
637+ err = au_dpages_init(&dpages, GFP_NOFS);
638+ if (unlikely(err))
639+ goto out;
640+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
641+ if (unlikely(err))
642+ goto out_dpages;
643+
644+ verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
645+ for (i = 0; !err && i < dpages.ndpage; i++) {
646+ dpage = dpages.dpages + i;
647+ ndentry = dpage->ndentry;
648+ for (j = 0; !err && j < ndentry; j++) {
649+ d = dpage->dentries[j];
650+ AuDebugOn(!atomic_read(&d->d_count));
651+ inode = d->d_inode;
652+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
653+ di_read_lock_child(d, AuLock_IR);
654+ else {
655+ di_write_lock_child(d);
656+ err = au_reval_dpath(d, sigen);
657+ if (!err)
658+ di_downgrade_lock(d, AuLock_IR);
659+ else {
660+ di_write_unlock(d);
661+ break;
662+ }
663+ }
664+
665+ bstart = au_dbstart(d);
666+ bend = au_dbend(d);
667+ if (bstart <= bindex
668+ && bindex <= bend
669+ && au_h_dptr(d, bindex)
670+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
671+ err = -EBUSY;
672+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
673+ }
674+ di_read_unlock(d, AuLock_IR);
675+ }
676+ }
677+
678+ out_dpages:
679+ au_dpages_free(&dpages);
680+ out:
681+ return err;
682+}
683+
684+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
685+ unsigned int sigen)
686+{
687+ int err;
688+ struct inode *i;
689+ aufs_bindex_t bstart, bend;
690+ unsigned char verbose;
691+
692+ err = 0;
693+ verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
694+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
695+ AuDebugOn(!atomic_read(&i->i_count));
696+ if (!list_empty(&i->i_dentry))
697+ continue;
698+
699+ if (au_iigen(i) == sigen)
700+ ii_read_lock_child(i);
701+ else {
702+ ii_write_lock_child(i);
703+ err = au_refresh_hinode_self(i, /*do_attr*/1);
704+ if (!err)
705+ ii_downgrade_lock(i);
706+ else {
707+ ii_write_unlock(i);
708+ break;
709+ }
710+ }
711+
712+ bstart = au_ibstart(i);
713+ bend = au_ibend(i);
714+ if (bstart <= bindex
715+ && bindex <= bend
716+ && au_h_iptr(i, bindex)
717+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
718+ err = -EBUSY;
719+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
720+ ii_read_unlock(i);
721+ break;
722+ }
723+ ii_read_unlock(i);
724+ }
725+
726+ return err;
727+}
728+
729+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
730+{
731+ int err;
732+ unsigned int sigen;
733+
734+ sigen = au_sigen(root->d_sb);
735+ DiMustNoWaiters(root);
736+ IiMustNoWaiters(root->d_inode);
737+ di_write_unlock(root);
738+ err = test_dentry_busy(root, bindex, sigen);
739+ if (!err)
740+ err = test_inode_busy(root->d_sb, bindex, sigen);
741+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
742+
743+ return err;
744+}
745+
746+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
747+ const aufs_bindex_t bindex,
748+ const aufs_bindex_t bend)
749+{
750+ struct au_branch **brp, **p;
751+
dece6358
AM
752+ AuRwMustWriteLock(&sbinfo->si_rwsem);
753+
1facf9fc 754+ brp = sbinfo->si_branch + bindex;
755+ if (bindex < bend)
756+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
757+ sbinfo->si_branch[0 + bend] = NULL;
758+ sbinfo->si_bend--;
759+
760+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
761+ if (p)
762+ sbinfo->si_branch = p;
763+}
764+
765+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
766+ const aufs_bindex_t bend)
767+{
768+ struct au_hdentry *hdp, *p;
769+
770+ hdp = dinfo->di_hdentry + bindex;
771+ if (bindex < bend)
772+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bend - bindex));
773+ dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
774+ dinfo->di_bend--;
775+
776+ p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
777+ if (p)
778+ dinfo->di_hdentry = p;
779+}
780+
781+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
782+ const aufs_bindex_t bend)
783+{
784+ struct au_hinode *hip, *p;
785+
786+ hip = iinfo->ii_hinode + bindex;
787+ if (bindex < bend)
788+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
789+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
790+ au_hin_init(iinfo->ii_hinode + bend, NULL);
791+ iinfo->ii_bend--;
792+
793+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
794+ if (p)
795+ iinfo->ii_hinode = p;
796+}
797+
798+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
799+ struct au_branch *br)
800+{
801+ aufs_bindex_t bend;
802+ struct au_sbinfo *sbinfo;
803+ struct dentry *root;
804+ struct inode *inode;
805+
dece6358
AM
806+ SiMustWriteLock(sb);
807+
1facf9fc 808+ root = sb->s_root;
809+ inode = root->d_inode;
810+ au_plink_block_maintain(sb);
811+ sbinfo = au_sbi(sb);
812+ bend = sbinfo->si_bend;
813+
814+ dput(au_h_dptr(root, bindex));
815+ au_hiput(au_hi(inode, bindex));
816+ au_br_do_free(br);
817+
818+ au_br_do_del_brp(sbinfo, bindex, bend);
819+ au_br_do_del_hdp(au_di(root), bindex, bend);
820+ au_br_do_del_hip(au_ii(inode), bindex, bend);
821+}
822+
823+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
824+{
825+ int err, rerr, i;
826+ unsigned int mnt_flags;
827+ aufs_bindex_t bindex, bend, br_id;
828+ unsigned char do_wh, verbose;
829+ struct au_branch *br;
830+ struct au_wbr *wbr;
831+
832+ err = 0;
833+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
834+ if (bindex < 0) {
835+ if (remount)
836+ goto out; /* success */
837+ err = -ENOENT;
838+ AuErr("%s no such branch\n", del->pathname);
839+ goto out;
840+ }
841+ AuDbg("bindex b%d\n", bindex);
842+
843+ err = -EBUSY;
844+ mnt_flags = au_mntflags(sb);
845+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
846+ bend = au_sbend(sb);
847+ if (unlikely(!bend)) {
848+ AuVerbose(verbose, "no more branches left\n");
849+ goto out;
850+ }
851+ br = au_sbr(sb, bindex);
852+ i = atomic_read(&br->br_count);
853+ if (unlikely(i)) {
854+ AuVerbose(verbose, "%d file(s) opened\n", i);
855+ goto out;
856+ }
857+
858+ wbr = br->br_wbr;
859+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
860+ if (do_wh) {
861+ for (i = 0; i < AuBrWh_Last; i++) {
862+ dput(wbr->wbr_wh[i]);
863+ wbr->wbr_wh[i] = NULL;
864+ }
865+ }
866+
867+ err = test_children_busy(sb->s_root, bindex);
868+ if (unlikely(err)) {
869+ if (do_wh)
870+ goto out_wh;
871+ goto out;
872+ }
873+
874+ err = 0;
875+ br_id = br->br_id;
876+ if (!remount)
877+ au_br_do_del(sb, bindex, br);
878+ else {
879+ sysaufs_brs_del(sb, bindex);
880+ au_br_do_del(sb, bindex, br);
881+ sysaufs_brs_add(sb, bindex);
882+ }
883+
884+ if (!bindex)
885+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
886+ else
887+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
888+ if (au_opt_test(mnt_flags, PLINK))
889+ au_plink_half_refresh(sb, br_id);
890+
891+ if (sb->s_maxbytes == del->h_path.dentry->d_sb->s_maxbytes) {
892+ bend--;
893+ sb->s_maxbytes = 0;
894+ for (bindex = 0; bindex <= bend; bindex++) {
895+ unsigned long long maxb;
896+
897+ maxb = au_sbr_sb(sb, bindex)->s_maxbytes;
898+ if (sb->s_maxbytes < maxb)
899+ sb->s_maxbytes = maxb;
900+ }
901+ }
902+
903+ if (au_xino_brid(sb) == br->br_id)
904+ au_xino_brid_set(sb, -1);
905+ goto out; /* success */
906+
907+ out_wh:
908+ /* revert */
909+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
910+ if (rerr)
911+ AuWarn("failed re-creating base whiteout, %s. (%d)\n",
912+ del->pathname, rerr);
913+ out:
914+ return err;
915+}
916+
917+/* ---------------------------------------------------------------------- */
918+
919+/*
920+ * change a branch permission
921+ */
922+
dece6358
AM
923+static void au_warn_ima(void)
924+{
925+#ifdef CONFIG_IMA
926+ AuWarn("RW -> RO makes IMA to produce wrong message");
927+#endif
928+}
929+
1facf9fc 930+static int do_need_sigen_inc(int a, int b)
931+{
932+ return au_br_whable(a) && !au_br_whable(b);
933+}
934+
935+static int need_sigen_inc(int old, int new)
936+{
937+ return do_need_sigen_inc(old, new)
938+ || do_need_sigen_inc(new, old);
939+}
940+
941+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
942+{
943+ int err;
944+ unsigned long n, ul, bytes, files;
945+ aufs_bindex_t bstart;
946+ struct file *file, *hf, **a;
947+ const int step_bytes = 1024, /* memory allocation unit */
948+ step_files = step_bytes / sizeof(*a);
949+
950+ err = -ENOMEM;
951+ n = 0;
952+ bytes = step_bytes;
953+ files = step_files;
954+ a = kmalloc(bytes, GFP_NOFS);
955+ if (unlikely(!a))
956+ goto out;
957+
958+ /* no need file_list_lock() since sbinfo is locked? defered? */
959+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
960+ if (special_file(file->f_dentry->d_inode->i_mode))
961+ continue;
962+
963+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
964+ fi_read_lock(file);
965+ if (unlikely(au_test_mmapped(file))) {
966+ err = -EBUSY;
967+ FiMustNoWaiters(file);
968+ fi_read_unlock(file);
969+ goto out_free;
970+ }
971+
972+ bstart = au_fbstart(file);
973+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
974+ || !(file->f_mode & FMODE_WRITE)
975+ || bstart != bindex) {
976+ FiMustNoWaiters(file);
977+ fi_read_unlock(file);
978+ continue;
979+ }
980+
981+ hf = au_h_fptr(file, bstart);
982+ FiMustNoWaiters(file);
983+ fi_read_unlock(file);
984+
985+ if (n < files)
986+ a[n++] = hf;
987+ else {
988+ void *p;
989+
990+ err = -ENOMEM;
991+ bytes += step_bytes;
992+ files += step_files;
993+ p = krealloc(a, bytes, GFP_NOFS);
994+ if (p) {
995+ a = p;
996+ a[n++] = hf;
997+ } else
998+ goto out_free;
999+ }
1000+ }
1001+
1002+ err = 0;
dece6358
AM
1003+ if (n)
1004+ au_warn_ima();
1facf9fc 1005+ for (ul = 0; ul < n; ul++) {
1006+ /* todo: already flushed? */
1007+ /* cf. fs/super.c:mark_files_ro() */
1008+ hf = a[ul];
1009+ hf->f_mode &= ~FMODE_WRITE;
1010+ if (!file_check_writeable(hf)) {
1011+ file_release_write(hf);
1012+ mnt_drop_write(hf->f_vfsmnt);
1013+ }
1014+ }
1015+
1016+ out_free:
1017+ kfree(a);
1018+ out:
1019+ return err;
1020+}
1021+
1022+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1023+ int *do_update)
1024+{
1025+ int err, rerr;
1026+ aufs_bindex_t bindex;
1027+ struct dentry *root;
1028+ struct au_branch *br;
1029+
1030+ root = sb->s_root;
1031+ au_plink_block_maintain(sb);
1032+ bindex = au_find_dbindex(root, mod->h_root);
1033+ if (bindex < 0) {
1034+ if (remount)
1035+ return 0; /* success */
1036+ err = -ENOENT;
1037+ AuErr("%s no such branch\n", mod->path);
1038+ goto out;
1039+ }
1040+ AuDbg("bindex b%d\n", bindex);
1041+
1042+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1043+ if (unlikely(err))
1044+ goto out;
1045+
1046+ br = au_sbr(sb, bindex);
1047+ if (br->br_perm == mod->perm)
1048+ return 0; /* success */
1049+
1050+ if (au_br_writable(br->br_perm)) {
1051+ /* remove whiteout base */
1052+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1053+ if (unlikely(err))
1054+ goto out;
1055+
1056+ if (!au_br_writable(mod->perm)) {
1057+ /* rw --> ro, file might be mmapped */
1058+ DiMustNoWaiters(root);
1059+ IiMustNoWaiters(root->d_inode);
1060+ di_write_unlock(root);
1061+ err = au_br_mod_files_ro(sb, bindex);
1062+ /* aufs_write_lock() calls ..._child() */
1063+ di_write_lock_child(root);
1064+
1065+ if (unlikely(err)) {
1066+ rerr = -ENOMEM;
1067+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1068+ GFP_NOFS);
1069+ if (br->br_wbr)
1070+ rerr = au_br_init_wh
1071+ (sb, br, br->br_perm,
1072+ mod->h_root);
1073+ if (unlikely(rerr)) {
1074+ AuIOErr("nested error %d (%d)\n",
1075+ rerr, err);
1076+ br->br_perm = mod->perm;
1077+ }
1078+ }
1079+ }
1080+ } else if (au_br_writable(mod->perm)) {
1081+ /* ro --> rw */
1082+ err = -ENOMEM;
1083+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1084+ if (br->br_wbr) {
1085+ struct path path = {
1086+ .mnt = br->br_mnt,
1087+ .dentry = mod->h_root
1088+ };
1089+
1090+ err = au_wbr_init(br, sb, mod->perm, &path);
1091+ if (unlikely(err)) {
1092+ kfree(br->br_wbr);
1093+ br->br_wbr = NULL;
1094+ }
1095+ }
1096+ }
1097+
1098+ if (!err) {
1099+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1100+ br->br_perm = mod->perm;
1101+ }
1102+
1103+ out:
1104+ return err;
1105+}
dece6358
AM
1106diff -urN linux-2.6.30.org/fs/aufs/branch.h linux-2.6.30/fs/aufs/branch.h
1107--- linux-2.6.30.org/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
1108+++ linux-2.6.30/fs/aufs/branch.h 2009-07-21 08:54:18.000000000 +0200
1109@@ -0,0 +1,219 @@
1facf9fc 1110+/*
1111+ * Copyright (C) 2005-2009 Junjiro R. Okajima
1112+ *
1113+ * This program, aufs is free software; you can redistribute it and/or modify
1114+ * it under the terms of the GNU General Public License as published by
1115+ * the Free Software Foundation; either version 2 of the License, or
1116+ * (at your option) any later version.
dece6358
AM
1117+ *
1118+ * This program is distributed in the hope that it will be useful,
1119+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1120+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1121+ * GNU General Public License for more details.
1122+ *
1123+ * You should have received a copy of the GNU General Public License
1124+ * along with this program; if not, write to the Free Software
1125+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1126+ */
1127+
1128+/*
1129+ * branch filesystems and xino for them
1130+ */
1131+
1132+#ifndef __AUFS_BRANCH_H__
1133+#define __AUFS_BRANCH_H__
1134+
1135+#ifdef __KERNEL__
1136+
1137+#include <linux/fs.h>
1138+#include <linux/mount.h>
1facf9fc 1139+#include <linux/aufs_type.h>
1140+#include "rwsem.h"
1141+#include "super.h"
1142+
1143+/* ---------------------------------------------------------------------- */
1144+
1145+/* a xino file */
1146+struct au_xino_file {
1147+ struct file *xi_file;
1148+ struct mutex xi_nondir_mtx;
1149+
1150+ /* todo: make xino files an array to support huge inode number */
1151+
1152+#ifdef CONFIG_DEBUG_FS
1153+ struct dentry *xi_dbgaufs;
1154+#endif
1155+};
1156+
1157+/* members for writable branch only */
1158+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1159+struct au_wbr {
dece6358 1160+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1161+ struct dentry *wbr_wh[AuBrWh_Last];
1162+ atomic_t wbr_wh_running;
1163+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1164+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1165+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1166+
1167+ /* mfs mode */
1168+ unsigned long long wbr_bytes;
1169+};
1170+
1171+/* protected by superblock rwsem */
1172+struct au_branch {
1173+ struct au_xino_file br_xino;
1174+
1175+ aufs_bindex_t br_id;
1176+
1177+ int br_perm;
1178+ struct vfsmount *br_mnt;
1179+ atomic_t br_count;
1180+
1181+ struct au_wbr *br_wbr;
1182+
1183+ /* xino truncation */
1184+ blkcnt_t br_xino_upper; /* watermark in blocks */
1185+ atomic_t br_xino_running;
1186+
1187+#ifdef CONFIG_SYSFS
1188+ /* an entry under sysfs per mount-point */
1189+ char br_name[8];
1190+ struct attribute br_attr;
1191+#endif
1192+};
1193+
1194+/* ---------------------------------------------------------------------- */
1195+
1196+/* branch permission and attribute */
1197+enum {
1198+ AuBrPerm_RW, /* writable, linkable wh */
1199+ AuBrPerm_RO, /* readonly, no wh */
1200+ AuBrPerm_RR, /* natively readonly, no wh */
1201+
1202+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1203+
1204+ AuBrPerm_ROWH, /* whiteout-able */
1205+ AuBrPerm_RRWH, /* whiteout-able */
1206+
1207+ AuBrPerm_Last
1208+};
1209+
1210+static inline int au_br_writable(int brperm)
1211+{
1212+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1213+}
1214+
1215+static inline int au_br_whable(int brperm)
1216+{
1217+ return brperm == AuBrPerm_RW
1218+ || brperm == AuBrPerm_ROWH
1219+ || brperm == AuBrPerm_RRWH;
1220+}
1221+
1222+static inline int au_br_rdonly(struct au_branch *br)
1223+{
1224+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1225+ || !au_br_writable(br->br_perm))
1226+ ? -EROFS : 0;
1227+}
1228+
1229+static inline int au_br_hinotifyable(int brperm __maybe_unused)
1230+{
1231+#ifdef CONFIG_AUFS_HINOTIFY
1232+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1233+#else
1234+ return 0;
1235+#endif
1236+}
1237+
1238+/* ---------------------------------------------------------------------- */
1239+
1240+/* branch.c */
1241+struct au_sbinfo;
1242+void au_br_free(struct au_sbinfo *sinfo);
1243+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1244+struct au_opt_add;
1245+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1246+struct au_opt_del;
1247+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1248+struct au_opt_mod;
1249+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1250+ int *do_update);
1251+
1252+/* xino.c */
1253+static const loff_t au_loff_max = LLONG_MAX;
1254+
1255+int au_xib_trunc(struct super_block *sb);
1256+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1257+ loff_t *pos);
1258+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1259+ loff_t *pos);
1260+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1261+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1262+ino_t au_xino_new_ino(struct super_block *sb);
1263+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1264+ ino_t ino);
1265+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1266+ ino_t ino);
1267+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1268+ ino_t *ino);
1269+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1270+ struct file *base_file, int do_test);
1271+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1272+
1273+struct au_opt_xino;
1274+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1275+void au_xino_clr(struct super_block *sb);
1276+struct file *au_xino_def(struct super_block *sb);
1277+int au_xino_path(struct seq_file *seq, struct file *file);
1278+
1279+/* ---------------------------------------------------------------------- */
1280+
1281+/* Superblock to branch */
1282+static inline
1283+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1284+{
1285+ return au_sbr(sb, bindex)->br_id;
1286+}
1287+
1288+static inline
1289+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1290+{
1291+ return au_sbr(sb, bindex)->br_mnt;
1292+}
1293+
1294+static inline
1295+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1296+{
1297+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1298+}
1299+
1300+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1301+{
dece6358 1302+ atomic_dec_return(&au_sbr(sb, bindex)->br_count);
1facf9fc 1303+}
1304+
1305+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1306+{
1307+ return au_sbr(sb, bindex)->br_perm;
1308+}
1309+
1310+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1311+{
1312+ return au_br_whable(au_sbr_perm(sb, bindex));
1313+}
1314+
1315+/* ---------------------------------------------------------------------- */
1316+
1317+/*
1318+ * wbr_wh_read_lock, wbr_wh_write_lock
1319+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1320+ */
1321+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1322+
dece6358
AM
1323+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1324+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1325+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1326+
1facf9fc 1327+#endif /* __KERNEL__ */
1328+#endif /* __AUFS_BRANCH_H__ */
dece6358
AM
1329diff -urN linux-2.6.30.org/fs/aufs/cpup.c linux-2.6.30/fs/aufs/cpup.c
1330--- linux-2.6.30.org/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
1331+++ linux-2.6.30/fs/aufs/cpup.c 2009-07-21 08:54:18.000000000 +0200
1332@@ -0,0 +1,1039 @@
1facf9fc 1333+/*
1334+ * Copyright (C) 2005-2009 Junjiro R. Okajima
1335+ *
1336+ * This program, aufs is free software; you can redistribute it and/or modify
1337+ * it under the terms of the GNU General Public License as published by
1338+ * the Free Software Foundation; either version 2 of the License, or
1339+ * (at your option) any later version.
dece6358
AM
1340+ *
1341+ * This program is distributed in the hope that it will be useful,
1342+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1343+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1344+ * GNU General Public License for more details.
1345+ *
1346+ * You should have received a copy of the GNU General Public License
1347+ * along with this program; if not, write to the Free Software
1348+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1349+ */
1350+
1351+/*
1352+ * copy-up functions, see wbr_policy.c for copy-down
1353+ */
1354+
dece6358 1355+#include <linux/file.h>
1facf9fc 1356+#include <linux/fs_stack.h>
dece6358 1357+#include <linux/mm.h>
1facf9fc 1358+#include <linux/uaccess.h>
1359+#include "aufs.h"
1360+
1361+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1362+{
1363+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1364+ | S_NOATIME | S_NOCMTIME;
1365+
1366+ dst->i_flags |= src->i_flags & ~mask;
1367+ if (au_test_fs_notime(dst->i_sb))
1368+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1369+}
1370+
1371+void au_cpup_attr_timesizes(struct inode *inode)
1372+{
1373+ struct inode *h_inode;
1374+
1375+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1376+ fsstack_copy_attr_times(inode, h_inode);
1377+ vfsub_copy_inode_size(inode, h_inode);
1378+}
1379+
1380+void au_cpup_attr_nlink(struct inode *inode, int force)
1381+{
1382+ struct inode *h_inode;
1383+ struct super_block *sb;
1384+ aufs_bindex_t bindex, bend;
1385+
1386+ sb = inode->i_sb;
1387+ bindex = au_ibstart(inode);
1388+ h_inode = au_h_iptr(inode, bindex);
1389+ if (!force
1390+ && !S_ISDIR(h_inode->i_mode)
1391+ && au_opt_test(au_mntflags(sb), PLINK)
1392+ && au_plink_test(inode))
1393+ return;
1394+
1395+ inode->i_nlink = h_inode->i_nlink;
1396+
1397+ /*
1398+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1399+ * it may includes whplink directory.
1400+ */
1401+ if (S_ISDIR(h_inode->i_mode)) {
1402+ bend = au_ibend(inode);
1403+ for (bindex++; bindex <= bend; bindex++) {
1404+ h_inode = au_h_iptr(inode, bindex);
1405+ if (h_inode)
1406+ au_add_nlink(inode, h_inode);
1407+ }
1408+ }
1409+}
1410+
1411+void au_cpup_attr_changeable(struct inode *inode)
1412+{
1413+ struct inode *h_inode;
1414+
1415+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1416+ inode->i_mode = h_inode->i_mode;
1417+ inode->i_uid = h_inode->i_uid;
1418+ inode->i_gid = h_inode->i_gid;
1419+ au_cpup_attr_timesizes(inode);
1420+ au_cpup_attr_flags(inode, h_inode);
1421+}
1422+
1423+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1424+{
1425+ struct au_iinfo *iinfo = au_ii(inode);
1426+
1427+ iinfo->ii_higen = h_inode->i_generation;
1428+ iinfo->ii_hsb1 = h_inode->i_sb;
1429+}
1430+
1431+void au_cpup_attr_all(struct inode *inode, int force)
1432+{
1433+ struct inode *h_inode;
1434+
1435+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1436+ au_cpup_attr_changeable(inode);
1437+ if (inode->i_nlink > 0)
1438+ au_cpup_attr_nlink(inode, force);
1439+ inode->i_rdev = h_inode->i_rdev;
1440+ inode->i_blkbits = h_inode->i_blkbits;
1441+ au_cpup_igen(inode, h_inode);
1442+}
1443+
1444+/* ---------------------------------------------------------------------- */
1445+
1446+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1447+
1448+/* keep the timestamps of the parent dir when cpup */
1449+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1450+ struct path *h_path)
1451+{
1452+ struct inode *h_inode;
1453+
1454+ dt->dt_dentry = dentry;
1455+ dt->dt_h_path = *h_path;
1456+ h_inode = h_path->dentry->d_inode;
1457+ dt->dt_atime = h_inode->i_atime;
1458+ dt->dt_mtime = h_inode->i_mtime;
1459+ /* smp_mb(); */
1460+}
1461+
1462+void au_dtime_revert(struct au_dtime *dt)
1463+{
1464+ struct iattr attr;
1465+ int err;
1466+
1467+ attr.ia_atime = dt->dt_atime;
1468+ attr.ia_mtime = dt->dt_mtime;
1469+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1470+ | ATTR_ATIME | ATTR_ATIME_SET;
1471+
1472+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
1473+ if (unlikely(err))
1474+ AuWarn("restoring timestamps failed(%d). ignored\n", err);
1475+}
1476+
1477+/* ---------------------------------------------------------------------- */
1478+
1479+static noinline_for_stack
1480+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1481+{
1482+ int err, sbits;
1483+ struct iattr ia;
1484+ struct path h_path;
1485+ struct inode *h_isrc;
1486+
1487+ h_path.dentry = au_h_dptr(dst, bindex);
1488+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1489+ h_isrc = h_src->d_inode;
1490+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
1491+ | ATTR_ATIME | ATTR_MTIME
1492+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1493+ ia.ia_mode = h_isrc->i_mode;
1494+ ia.ia_uid = h_isrc->i_uid;
1495+ ia.ia_gid = h_isrc->i_gid;
1496+ ia.ia_atime = h_isrc->i_atime;
1497+ ia.ia_mtime = h_isrc->i_mtime;
1498+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
1499+ au_cpup_attr_flags(h_path.dentry->d_inode, h_isrc);
1500+ err = vfsub_notify_change(&h_path, &ia);
1501+
1502+ /* is this nfs only? */
1503+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1504+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1505+ ia.ia_mode = h_isrc->i_mode;
1506+ err = vfsub_notify_change(&h_path, &ia);
1507+ }
1508+
1509+ return err;
1510+}
1511+
1512+/* ---------------------------------------------------------------------- */
1513+
1514+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
1515+ char *buf, unsigned long blksize)
1516+{
1517+ int err;
1518+ size_t sz, rbytes, wbytes;
1519+ unsigned char all_zero;
1520+ char *p, *zp;
1521+ struct mutex *h_mtx;
1522+ /* reduce stack usage */
1523+ struct iattr *ia;
1524+
1525+ zp = page_address(ZERO_PAGE(0));
1526+ if (unlikely(!zp))
1527+ return -ENOMEM; /* possible? */
1528+
1529+ err = 0;
1530+ all_zero = 0;
1531+ while (len) {
1532+ AuDbg("len %lld\n", len);
1533+ sz = blksize;
1534+ if (len < blksize)
1535+ sz = len;
1536+
1537+ rbytes = 0;
1538+ /* todo: signal_pending? */
1539+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
1540+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
1541+ err = rbytes;
1542+ }
1543+ if (unlikely(err < 0))
1544+ break;
1545+
1546+ all_zero = 0;
1547+ if (len >= rbytes && rbytes == blksize)
1548+ all_zero = !memcmp(buf, zp, rbytes);
1549+ if (!all_zero) {
1550+ wbytes = rbytes;
1551+ p = buf;
1552+ while (wbytes) {
1553+ size_t b;
1554+
1555+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
1556+ err = b;
1557+ /* todo: signal_pending? */
1558+ if (unlikely(err == -EAGAIN || err == -EINTR))
1559+ continue;
1560+ if (unlikely(err < 0))
1561+ break;
1562+ wbytes -= b;
1563+ p += b;
1564+ }
1565+ } else {
1566+ loff_t res;
1567+
1568+ AuLabel(hole);
1569+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
1570+ err = res;
1571+ if (unlikely(res < 0))
1572+ break;
1573+ }
1574+ len -= rbytes;
1575+ err = 0;
1576+ }
1577+
1578+ /* the last block may be a hole */
1579+ if (!err && all_zero) {
1580+ AuLabel(last hole);
1581+
1582+ err = 1;
1583+ if (au_test_nfs(dst->f_dentry->d_sb)) {
1584+ /* nfs requires this step to make last hole */
1585+ /* is this only nfs? */
1586+ do {
1587+ /* todo: signal_pending? */
1588+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
1589+ } while (err == -EAGAIN || err == -EINTR);
1590+ if (err == 1)
1591+ dst->f_pos--;
1592+ }
1593+
1594+ if (err == 1) {
1595+ ia = (void *)buf;
1596+ ia->ia_size = dst->f_pos;
1597+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
1598+ ia->ia_file = dst;
1599+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
1600+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
1601+ err = vfsub_notify_change(&dst->f_path, ia);
1602+ mutex_unlock(h_mtx);
1603+ }
1604+ }
1605+
1606+ return err;
1607+}
1608+
1609+int au_copy_file(struct file *dst, struct file *src, loff_t len)
1610+{
1611+ int err;
1612+ unsigned long blksize;
1613+ unsigned char do_kfree;
1614+ char *buf;
1615+
1616+ err = -ENOMEM;
1617+ blksize = dst->f_dentry->d_sb->s_blocksize;
1618+ if (!blksize || PAGE_SIZE < blksize)
1619+ blksize = PAGE_SIZE;
1620+ AuDbg("blksize %lu\n", blksize);
1621+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
1622+ if (do_kfree)
1623+ buf = kmalloc(blksize, GFP_NOFS);
1624+ else
1625+ buf = (void *)__get_free_page(GFP_NOFS);
1626+ if (unlikely(!buf))
1627+ goto out;
1628+
1629+ if (len > (1 << 22))
1630+ AuDbg("copying a large file %lld\n", (long long)len);
1631+
1632+ src->f_pos = 0;
1633+ dst->f_pos = 0;
1634+ err = au_do_copy_file(dst, src, len, buf, blksize);
1635+ if (do_kfree)
1636+ kfree(buf);
1637+ else
1638+ free_page((unsigned long)buf);
1639+
1640+ out:
1641+ return err;
1642+}
1643+
1644+/*
1645+ * to support a sparse file which is opened with O_APPEND,
1646+ * we need to close the file.
1647+ */
1648+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
1649+ aufs_bindex_t bsrc, loff_t len)
1650+{
1651+ int err, i;
1652+ enum { SRC, DST };
1653+ struct {
1654+ aufs_bindex_t bindex;
1655+ unsigned int flags;
1656+ struct dentry *dentry;
1657+ struct file *file;
1658+ void *label, *label_file;
1659+ } *f, file[] = {
1660+ {
1661+ .bindex = bsrc,
1662+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1663+ .file = NULL,
1664+ .label = &&out,
1665+ .label_file = &&out_src
1666+ },
1667+ {
1668+ .bindex = bdst,
1669+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
1670+ .file = NULL,
1671+ .label = &&out_src,
1672+ .label_file = &&out_dst
1673+ }
1674+ };
1675+ struct super_block *sb;
1676+
1677+ /* bsrc branch can be ro/rw. */
1678+ sb = dentry->d_sb;
1679+ f = file;
1680+ for (i = 0; i < 2; i++, f++) {
1681+ f->dentry = au_h_dptr(dentry, f->bindex);
1682+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
1683+ err = PTR_ERR(f->file);
1684+ if (IS_ERR(f->file))
1685+ goto *f->label;
1686+ err = -EINVAL;
1687+ if (unlikely(!f->file->f_op))
1688+ goto *f->label_file;
1689+ }
1690+
1691+ /* try stopping to update while we copyup */
1692+ IMustLock(file[SRC].dentry->d_inode);
1693+ err = au_copy_file(file[DST].file, file[SRC].file, len);
1694+
1695+ out_dst:
1696+ fput(file[DST].file);
1697+ au_sbr_put(sb, file[DST].bindex);
1698+ out_src:
1699+ fput(file[SRC].file);
1700+ au_sbr_put(sb, file[SRC].bindex);
1701+ out:
1702+ return err;
1703+}
1704+
1705+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
1706+ aufs_bindex_t bsrc, loff_t len,
1707+ struct inode *h_dir, struct path *h_path)
1708+{
1709+ int err, rerr;
1710+ loff_t l;
1711+
1712+ err = 0;
1713+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
1714+ if (len == -1 || l < len)
1715+ len = l;
1716+ if (len)
1717+ err = au_cp_regular(dentry, bdst, bsrc, len);
1718+ if (!err)
1719+ goto out; /* success */
1720+
1721+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
1722+ if (rerr) {
1723+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
1724+ AuDLNPair(h_path->dentry), err, rerr);
1725+ err = -EIO;
1726+ }
1727+
1728+ out:
1729+ return err;
1730+}
1731+
1732+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
1733+ struct inode *h_dir)
1734+{
1735+ int err, symlen;
1736+ mm_segment_t old_fs;
1737+ char *sym;
1738+
1739+ err = -ENOSYS;
1740+ if (unlikely(!h_src->d_inode->i_op->readlink))
1741+ goto out;
1742+
1743+ err = -ENOMEM;
1744+ sym = __getname();
1745+ if (unlikely(!sym))
1746+ goto out;
1747+
1748+ old_fs = get_fs();
1749+ set_fs(KERNEL_DS);
1750+ symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
1751+ PATH_MAX);
1752+ err = symlen;
1753+ set_fs(old_fs);
1754+
1755+ if (symlen > 0) {
1756+ sym[symlen] = 0;
1757+ err = vfsub_symlink(h_dir, h_path, sym);
1758+ }
1759+ __putname(sym);
1760+
1761+ out:
1762+ return err;
1763+}
1764+
1765+/* return with the lower dst inode is locked */
1766+static noinline_for_stack
1767+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
1768+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1769+ struct dentry *dst_parent)
1770+{
1771+ int err;
1772+ umode_t mode;
1773+ unsigned int mnt_flags;
1774+ unsigned char isdir;
1775+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
1776+ struct au_dtime dt;
1777+ struct path h_path;
1778+ struct dentry *h_src, *h_dst, *h_parent;
1779+ struct inode *h_inode, *h_dir;
1780+ struct super_block *sb;
1781+
1782+ /* bsrc branch can be ro/rw. */
1783+ h_src = au_h_dptr(dentry, bsrc);
1784+ h_inode = h_src->d_inode;
1785+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
1786+
1787+ /* try stopping to be referenced while we are creating */
1788+ h_dst = au_h_dptr(dentry, bdst);
1789+ h_parent = h_dst->d_parent; /* dir inode is locked */
1790+ h_dir = h_parent->d_inode;
1791+ IMustLock(h_dir);
1792+ AuDebugOn(h_parent != h_dst->d_parent);
1793+
1794+ sb = dentry->d_sb;
1795+ h_path.mnt = au_sbr_mnt(sb, bdst);
1796+ if (do_dt) {
1797+ h_path.dentry = h_parent;
1798+ au_dtime_store(&dt, dst_parent, &h_path);
1799+ }
1800+ h_path.dentry = h_dst;
1801+
1802+ isdir = 0;
1803+ mode = h_inode->i_mode;
1804+ switch (mode & S_IFMT) {
1805+ case S_IFREG:
1806+ /* try stopping to update while we are referencing */
1807+ IMustLock(h_inode);
1808+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
1809+ if (!err)
1810+ err = au_do_cpup_regular
1811+ (dentry, bdst, bsrc, len,
1812+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
1813+ break;
1814+ case S_IFDIR:
1815+ isdir = 1;
1816+ err = vfsub_mkdir(h_dir, &h_path, mode);
1817+ if (!err) {
1818+ /*
1819+ * strange behaviour from the users view,
1820+ * particularry setattr case
1821+ */
1822+ if (au_ibstart(dst_parent->d_inode) == bdst)
1823+ au_cpup_attr_nlink(dst_parent->d_inode,
1824+ /*force*/1);
1825+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
1826+ }
1827+ break;
1828+ case S_IFLNK:
1829+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
1830+ break;
1831+ case S_IFCHR:
1832+ case S_IFBLK:
1833+ AuDebugOn(!capable(CAP_MKNOD));
1834+ /*FALLTHROUGH*/
1835+ case S_IFIFO:
1836+ case S_IFSOCK:
1837+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
1838+ break;
1839+ default:
1840+ AuIOErr("Unknown inode type 0%o\n", mode);
1841+ err = -EIO;
1842+ }
1843+
1844+ mnt_flags = au_mntflags(sb);
1845+ if (!au_opt_test(mnt_flags, UDBA_NONE)
1846+ && !isdir
1847+ && au_opt_test(mnt_flags, XINO)
1848+ && h_inode->i_nlink == 1
1849+ /* todo: unnecessary? */
1850+ /* && dentry->d_inode->i_nlink == 1 */
1851+ && bdst < bsrc
1852+ && !au_ftest_cpup(flags, KEEPLINO))
1853+ au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
1854+ /* ignore this error */
1855+
1856+ if (do_dt)
1857+ au_dtime_revert(&dt);
1858+ return err;
1859+}
1860+
1861+/*
1862+ * copyup the @dentry from @bsrc to @bdst.
1863+ * the caller must set the both of lower dentries.
1864+ * @len is for truncating when it is -1 copyup the entire file.
1865+ * in link/rename cases, @dst_parent may be different from the real one.
1866+ */
1867+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
1868+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1869+ struct dentry *dst_parent)
1870+{
1871+ int err, rerr;
1872+ aufs_bindex_t old_ibstart;
1873+ unsigned char isdir, plink;
1874+ struct au_dtime dt;
1875+ struct path h_path;
1876+ struct dentry *h_src, *h_dst, *h_parent;
1877+ struct inode *dst_inode, *h_dir, *inode;
1878+ struct super_block *sb;
1879+
1880+ AuDebugOn(bsrc <= bdst);
1881+
1882+ sb = dentry->d_sb;
1883+ h_path.mnt = au_sbr_mnt(sb, bdst);
1884+ h_dst = au_h_dptr(dentry, bdst);
1885+ h_parent = h_dst->d_parent; /* dir inode is locked */
1886+ h_dir = h_parent->d_inode;
1887+ IMustLock(h_dir);
1888+
1889+ h_src = au_h_dptr(dentry, bsrc);
1890+ inode = dentry->d_inode;
1891+
1892+ if (!dst_parent)
1893+ dst_parent = dget_parent(dentry);
1894+ else
1895+ dget(dst_parent);
1896+
1897+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
1898+ dst_inode = au_h_iptr(inode, bdst);
1899+ if (dst_inode) {
1900+ if (unlikely(!plink)) {
1901+ err = -EIO;
1902+ AuIOErr("i%lu exists on a upper branch "
1903+ "but plink is disabled\n", inode->i_ino);
1904+ goto out;
1905+ }
1906+
1907+ if (dst_inode->i_nlink) {
1908+ const int do_dt = au_ftest_cpup(flags, DTIME);
1909+
1910+ h_src = au_plink_lkup(inode, bdst);
1911+ err = PTR_ERR(h_src);
1912+ if (IS_ERR(h_src))
1913+ goto out;
1914+ if (unlikely(!h_src->d_inode)) {
1915+ err = -EIO;
1916+ AuIOErr("i%lu exists on a upper branch "
1917+ "but plink is broken\n", inode->i_ino);
1918+ dput(h_src);
1919+ goto out;
1920+ }
1921+
1922+ if (do_dt) {
1923+ h_path.dentry = h_parent;
1924+ au_dtime_store(&dt, dst_parent, &h_path);
1925+ }
1926+ h_path.dentry = h_dst;
1927+ err = vfsub_link(h_src, h_dir, &h_path);
1928+ if (do_dt)
1929+ au_dtime_revert(&dt);
1930+ dput(h_src);
1931+ goto out;
1932+ } else
1933+ /* todo: cpup_wh_file? */
1934+ /* udba work */
1935+ au_update_brange(inode, 1);
1936+ }
1937+
1938+ old_ibstart = au_ibstart(inode);
1939+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
1940+ if (unlikely(err))
1941+ goto out;
1942+ dst_inode = h_dst->d_inode;
1943+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
1944+
1945+ err = cpup_iattr(dentry, bdst, h_src);
1946+ isdir = S_ISDIR(dst_inode->i_mode);
1947+ if (!err) {
1948+ if (bdst < old_ibstart)
1949+ au_set_ibstart(inode, bdst);
1950+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
1951+ au_hi_flags(inode, isdir));
1952+ mutex_unlock(&dst_inode->i_mutex);
1953+ if (!isdir
1954+ && h_src->d_inode->i_nlink > 1
1955+ && plink)
1956+ au_plink_append(inode, bdst, h_dst);
1957+ goto out; /* success */
1958+ }
1959+
1960+ /* revert */
1961+ h_path.dentry = h_parent;
1962+ mutex_unlock(&dst_inode->i_mutex);
1963+ au_dtime_store(&dt, dst_parent, &h_path);
1964+ h_path.dentry = h_dst;
1965+ if (!isdir)
1966+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
1967+ else
1968+ rerr = vfsub_rmdir(h_dir, &h_path);
1969+ au_dtime_revert(&dt);
1970+ if (rerr) {
1971+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
1972+ err = -EIO;
1973+ }
1974+
1975+ out:
1976+ dput(dst_parent);
1977+ return err;
1978+}
1979+
1980+struct au_cpup_single_args {
1981+ int *errp;
1982+ struct dentry *dentry;
1983+ aufs_bindex_t bdst, bsrc;
1984+ loff_t len;
1985+ unsigned int flags;
1986+ struct dentry *dst_parent;
1987+};
1988+
1989+static void au_call_cpup_single(void *args)
1990+{
1991+ struct au_cpup_single_args *a = args;
1992+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
1993+ a->flags, a->dst_parent);
1994+}
1995+
1996+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
1997+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1998+ struct dentry *dst_parent)
1999+{
2000+ int err, wkq_err;
2001+ umode_t mode;
2002+ struct dentry *h_dentry;
2003+
2004+ h_dentry = au_h_dptr(dentry, bsrc);
2005+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2006+ if ((mode != S_IFCHR && mode != S_IFBLK)
2007+ || capable(CAP_MKNOD))
2008+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2009+ dst_parent);
2010+ else {
2011+ struct au_cpup_single_args args = {
2012+ .errp = &err,
2013+ .dentry = dentry,
2014+ .bdst = bdst,
2015+ .bsrc = bsrc,
2016+ .len = len,
2017+ .flags = flags,
2018+ .dst_parent = dst_parent
2019+ };
2020+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2021+ if (unlikely(wkq_err))
2022+ err = wkq_err;
2023+ }
2024+
2025+ return err;
2026+}
2027+
2028+/*
2029+ * copyup the @dentry from the first active lower branch to @bdst,
2030+ * using au_cpup_single().
2031+ */
2032+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2033+ unsigned int flags)
2034+{
2035+ int err;
2036+ aufs_bindex_t bsrc, bend;
2037+
2038+ bend = au_dbend(dentry);
2039+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2040+ if (au_h_dptr(dentry, bsrc))
2041+ break;
2042+
2043+ err = au_lkup_neg(dentry, bdst);
2044+ if (!err) {
2045+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2046+ if (!err)
2047+ return 0; /* success */
2048+
2049+ /* revert */
2050+ au_set_h_dptr(dentry, bdst, NULL);
2051+ au_set_dbstart(dentry, bsrc);
2052+ }
2053+
2054+ return err;
2055+}
2056+
2057+struct au_cpup_simple_args {
2058+ int *errp;
2059+ struct dentry *dentry;
2060+ aufs_bindex_t bdst;
2061+ loff_t len;
2062+ unsigned int flags;
2063+};
2064+
2065+static void au_call_cpup_simple(void *args)
2066+{
2067+ struct au_cpup_simple_args *a = args;
2068+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2069+}
2070+
2071+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2072+ unsigned int flags)
2073+{
2074+ int err, wkq_err;
2075+ unsigned char do_sio;
2076+ struct dentry *parent;
2077+ struct inode *h_dir;
2078+
2079+ parent = dget_parent(dentry);
2080+ h_dir = au_h_iptr(parent->d_inode, bdst);
2081+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2082+ if (!do_sio) {
2083+ /*
2084+ * testing CAP_MKNOD is for generic fs,
2085+ * but CAP_FSETID is for xfs only, currently.
2086+ */
2087+ umode_t mode = dentry->d_inode->i_mode;
2088+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2089+ && !capable(CAP_MKNOD))
2090+ || ((mode & (S_ISUID | S_ISGID))
2091+ && !capable(CAP_FSETID)));
2092+ }
2093+ if (!do_sio)
2094+ err = au_cpup_simple(dentry, bdst, len, flags);
2095+ else {
2096+ struct au_cpup_simple_args args = {
2097+ .errp = &err,
2098+ .dentry = dentry,
2099+ .bdst = bdst,
2100+ .len = len,
2101+ .flags = flags
2102+ };
2103+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2104+ if (unlikely(wkq_err))
2105+ err = wkq_err;
2106+ }
2107+
2108+ dput(parent);
2109+ return err;
2110+}
2111+
2112+/* ---------------------------------------------------------------------- */
2113+
2114+/*
2115+ * copyup the deleted file for writing.
2116+ */
2117+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2118+ struct dentry *wh_dentry, struct file *file,
2119+ loff_t len)
2120+{
2121+ int err;
2122+ aufs_bindex_t bstart;
2123+ struct au_dinfo *dinfo;
2124+ struct dentry *h_d_dst, *h_d_start;
2125+
2126+ dinfo = au_di(dentry);
2127+ bstart = dinfo->di_bstart;
2128+ h_d_dst = dinfo->di_hdentry[0 + bdst].hd_dentry;
2129+ dinfo->di_bstart = bdst;
2130+ dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
2131+ h_d_start = dinfo->di_hdentry[0 + bstart].hd_dentry;
2132+ if (file)
2133+ dinfo->di_hdentry[0 + bstart].hd_dentry
2134+ = au_h_fptr(file, au_fbstart(file))->f_dentry;
2135+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2136+ /*h_parent*/NULL);
2137+ if (!err && file) {
2138+ err = au_reopen_nondir(file);
2139+ dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_start;
2140+ }
2141+ dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_dst;
2142+ dinfo->di_bstart = bstart;
2143+
2144+ return err;
2145+}
2146+
2147+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2148+ struct file *file)
2149+{
2150+ int err;
2151+ struct au_dtime dt;
2152+ struct dentry *parent, *h_parent, *wh_dentry;
2153+ struct au_branch *br;
2154+ struct path h_path;
2155+
2156+ br = au_sbr(dentry->d_sb, bdst);
2157+ parent = dget_parent(dentry);
2158+ h_parent = au_h_dptr(parent, bdst);
2159+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2160+ err = PTR_ERR(wh_dentry);
2161+ if (IS_ERR(wh_dentry))
2162+ goto out;
2163+
2164+ h_path.dentry = h_parent;
2165+ h_path.mnt = br->br_mnt;
2166+ au_dtime_store(&dt, parent, &h_path);
2167+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2168+ if (unlikely(err))
2169+ goto out_wh;
2170+
2171+ dget(wh_dentry);
2172+ h_path.dentry = wh_dentry;
2173+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2174+ if (unlikely(err)) {
2175+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2176+ AuDLNPair(wh_dentry), err);
2177+ err = -EIO;
2178+ }
2179+ au_dtime_revert(&dt);
2180+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2181+
2182+ out_wh:
2183+ dput(wh_dentry);
2184+ out:
2185+ dput(parent);
2186+ return err;
2187+}
2188+
2189+struct au_cpup_wh_args {
2190+ int *errp;
2191+ struct dentry *dentry;
2192+ aufs_bindex_t bdst;
2193+ loff_t len;
2194+ struct file *file;
2195+};
2196+
2197+static void au_call_cpup_wh(void *args)
2198+{
2199+ struct au_cpup_wh_args *a = args;
2200+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2201+}
2202+
2203+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2204+ struct file *file)
2205+{
2206+ int err, wkq_err;
2207+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2208+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2209+ struct au_wbr *wbr;
2210+
2211+ parent = dget_parent(dentry);
2212+ dir = parent->d_inode;
2213+ h_orph = NULL;
2214+ h_parent = NULL;
2215+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2216+ h_tmpdir = h_dir;
2217+ if (!h_dir->i_nlink) {
2218+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2219+ h_orph = wbr->wbr_orph;
2220+
2221+ h_parent = dget(au_h_dptr(parent, bdst));
2222+ au_set_h_dptr(parent, bdst, NULL);
2223+ au_set_h_dptr(parent, bdst, dget(h_orph));
2224+ h_tmpdir = h_orph->d_inode;
2225+ au_set_h_iptr(dir, bdst, NULL, 0);
2226+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2227+
2228+ /* this temporary unlock is safe */
2229+ if (file)
2230+ h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
2231+ else
2232+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2233+ h_inode = h_dentry->d_inode;
2234+ IMustLock(h_inode);
2235+ mutex_unlock(&h_inode->i_mutex);
dece6358 2236+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2237+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
2238+ }
2239+
2240+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2241+ err = au_cpup_wh(dentry, bdst, len, file);
2242+ else {
2243+ struct au_cpup_wh_args args = {
2244+ .errp = &err,
2245+ .dentry = dentry,
2246+ .bdst = bdst,
2247+ .len = len,
2248+ .file = file
2249+ };
2250+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2251+ if (unlikely(wkq_err))
2252+ err = wkq_err;
2253+ }
2254+
2255+ if (h_orph) {
2256+ mutex_unlock(&h_tmpdir->i_mutex);
2257+ au_set_h_iptr(dir, bdst, NULL, 0);
2258+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
2259+ au_set_h_dptr(parent, bdst, NULL);
2260+ au_set_h_dptr(parent, bdst, h_parent);
2261+ }
2262+ iput(h_dir);
2263+ dput(parent);
2264+
2265+ return err;
2266+}
2267+
2268+/* ---------------------------------------------------------------------- */
2269+
2270+/*
2271+ * generic routine for both of copy-up and copy-down.
2272+ */
2273+/* cf. revalidate function in file.c */
2274+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2275+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2276+ struct dentry *h_parent, void *arg),
2277+ void *arg)
2278+{
2279+ int err;
2280+ struct au_pin pin;
2281+ struct dentry *d, *parent, *h_parent, *real_parent;
2282+
2283+ err = 0;
2284+ parent = dget_parent(dentry);
2285+ if (IS_ROOT(parent))
2286+ goto out;
2287+
2288+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2289+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2290+
2291+ /* do not use au_dpage */
2292+ real_parent = parent;
2293+ while (1) {
2294+ dput(parent);
2295+ parent = dget_parent(dentry);
2296+ h_parent = au_h_dptr(parent, bdst);
2297+ if (h_parent)
2298+ goto out; /* success */
2299+
2300+ /* find top dir which is necessary to cpup */
2301+ do {
2302+ d = parent;
2303+ dput(parent);
2304+ parent = dget_parent(d);
2305+ di_read_lock_parent3(parent, !AuLock_IR);
2306+ h_parent = au_h_dptr(parent, bdst);
2307+ di_read_unlock(parent, !AuLock_IR);
2308+ } while (!h_parent);
2309+
2310+ if (d != real_parent)
2311+ di_write_lock_child3(d);
2312+
2313+ /* somebody else might create while we were sleeping */
2314+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2315+ if (au_h_dptr(d, bdst))
2316+ au_update_dbstart(d);
2317+
2318+ au_pin_set_dentry(&pin, d);
2319+ err = au_do_pin(&pin);
2320+ if (!err) {
2321+ err = cp(d, bdst, h_parent, arg);
2322+ au_unpin(&pin);
2323+ }
2324+ }
2325+
2326+ if (d != real_parent)
2327+ di_write_unlock(d);
2328+ if (unlikely(err))
2329+ break;
2330+ }
2331+
2332+ out:
2333+ dput(parent);
2334+ return err;
2335+}
2336+
2337+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2338+ struct dentry *h_parent __maybe_unused ,
2339+ void *arg __maybe_unused)
2340+{
2341+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2342+}
2343+
2344+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2345+{
2346+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2347+}
2348+
2349+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2350+{
2351+ int err;
2352+ struct dentry *parent;
2353+ struct inode *dir;
2354+
2355+ parent = dget_parent(dentry);
2356+ dir = parent->d_inode;
2357+ err = 0;
2358+ if (au_h_iptr(dir, bdst))
2359+ goto out;
2360+
2361+ di_read_unlock(parent, AuLock_IR);
2362+ di_write_lock_parent(parent);
2363+ /* someone else might change our inode while we were sleeping */
2364+ if (!au_h_iptr(dir, bdst))
2365+ err = au_cpup_dirs(dentry, bdst);
2366+ di_downgrade_lock(parent, AuLock_IR);
2367+
2368+ out:
2369+ dput(parent);
2370+ return err;
2371+}
dece6358
AM
2372diff -urN linux-2.6.30.org/fs/aufs/cpup.h linux-2.6.30/fs/aufs/cpup.h
2373--- linux-2.6.30.org/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
2374+++ linux-2.6.30/fs/aufs/cpup.h 2009-07-21 08:54:18.000000000 +0200
2375@@ -0,0 +1,81 @@
1facf9fc 2376+/*
2377+ * Copyright (C) 2005-2009 Junjiro R. Okajima
2378+ *
2379+ * This program, aufs is free software; you can redistribute it and/or modify
2380+ * it under the terms of the GNU General Public License as published by
2381+ * the Free Software Foundation; either version 2 of the License, or
2382+ * (at your option) any later version.
dece6358
AM
2383+ *
2384+ * This program is distributed in the hope that it will be useful,
2385+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2386+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2387+ * GNU General Public License for more details.
2388+ *
2389+ * You should have received a copy of the GNU General Public License
2390+ * along with this program; if not, write to the Free Software
2391+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2392+ */
2393+
2394+/*
2395+ * copy-up/down functions
2396+ */
2397+
2398+#ifndef __AUFS_CPUP_H__
2399+#define __AUFS_CPUP_H__
2400+
2401+#ifdef __KERNEL__
2402+
dece6358
AM
2403+#include <linux/path.h>
2404+#include <linux/time.h>
1facf9fc 2405+#include <linux/aufs_type.h>
2406+
dece6358
AM
2407+struct inode;
2408+struct file;
2409+
1facf9fc 2410+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2411+void au_cpup_attr_timesizes(struct inode *inode);
2412+void au_cpup_attr_nlink(struct inode *inode, int force);
2413+void au_cpup_attr_changeable(struct inode *inode);
2414+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2415+void au_cpup_attr_all(struct inode *inode, int force);
2416+
2417+/* ---------------------------------------------------------------------- */
2418+
2419+/* cpup flags */
2420+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2421+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2422+ for link(2) */
2423+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
2424+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
2425+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
2426+
2427+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2428+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2429+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2430+ struct dentry *dst_parent);
2431+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2432+ unsigned int flags);
2433+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2434+ struct file *file);
2435+
2436+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2437+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2438+ struct dentry *h_parent, void *arg),
2439+ void *arg);
2440+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2441+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2442+
2443+/* ---------------------------------------------------------------------- */
2444+
2445+/* keep timestamps when copyup */
2446+struct au_dtime {
2447+ struct dentry *dt_dentry;
2448+ struct path dt_h_path;
2449+ struct timespec dt_atime, dt_mtime;
2450+};
2451+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2452+ struct path *h_path);
2453+void au_dtime_revert(struct au_dtime *dt);
2454+
2455+#endif /* __KERNEL__ */
2456+#endif /* __AUFS_CPUP_H__ */
dece6358
AM
2457diff -urN linux-2.6.30.org/fs/aufs/dbgaufs.c linux-2.6.30/fs/aufs/dbgaufs.c
2458--- linux-2.6.30.org/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
2459+++ linux-2.6.30/fs/aufs/dbgaufs.c 2009-07-21 08:54:18.000000000 +0200
2460@@ -0,0 +1,331 @@
1facf9fc 2461+/*
2462+ * Copyright (C) 2005-2009 Junjiro R. Okajima
2463+ *
2464+ * This program, aufs is free software; you can redistribute it and/or modify
2465+ * it under the terms of the GNU General Public License as published by
2466+ * the Free Software Foundation; either version 2 of the License, or
2467+ * (at your option) any later version.
dece6358
AM
2468+ *
2469+ * This program is distributed in the hope that it will be useful,
2470+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2471+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2472+ * GNU General Public License for more details.
2473+ *
2474+ * You should have received a copy of the GNU General Public License
2475+ * along with this program; if not, write to the Free Software
2476+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2477+ */
2478+
2479+/*
2480+ * debugfs interface
2481+ */
2482+
2483+#include <linux/debugfs.h>
2484+#include "aufs.h"
2485+
2486+#ifndef CONFIG_SYSFS
2487+#error DEBUG_FS depends upon SYSFS
2488+#endif
2489+
2490+static struct dentry *dbgaufs;
2491+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2492+
2493+/* 20 is max digits length of ulong 64 */
2494+struct dbgaufs_arg {
2495+ int n;
2496+ char a[20 * 4];
2497+};
2498+
2499+/*
2500+ * common function for all XINO files
2501+ */
2502+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
2503+ struct file *file)
2504+{
2505+ kfree(file->private_data);
2506+ return 0;
2507+}
2508+
2509+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
2510+{
2511+ int err;
2512+ struct kstat st;
2513+ struct dbgaufs_arg *p;
2514+
2515+ err = -ENOMEM;
2516+ p = kmalloc(sizeof(*p), GFP_NOFS);
2517+ if (unlikely(!p))
2518+ goto out;
2519+
2520+ err = 0;
2521+ p->n = 0;
2522+ file->private_data = p;
2523+ if (!xf)
2524+ goto out;
2525+
2526+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
2527+ if (!err) {
2528+ if (do_fcnt)
2529+ p->n = snprintf
2530+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
2531+ (long)file_count(xf), st.blocks, st.blksize,
2532+ (long long)st.size);
2533+ else
2534+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
2535+ st.blocks, st.blksize,
2536+ (long long)st.size);
2537+ AuDebugOn(p->n >= sizeof(p->a));
2538+ } else {
2539+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
2540+ err = 0;
2541+ }
2542+
2543+ out:
2544+ return err;
2545+
2546+}
2547+
2548+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
2549+ size_t count, loff_t *ppos)
2550+{
2551+ struct dbgaufs_arg *p;
2552+
2553+ p = file->private_data;
2554+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
2555+}
2556+
2557+/* ---------------------------------------------------------------------- */
2558+
2559+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
2560+{
2561+ int err;
2562+ struct au_sbinfo *sbinfo;
2563+ struct super_block *sb;
2564+
2565+ sbinfo = inode->i_private;
2566+ sb = sbinfo->si_sb;
2567+ si_noflush_read_lock(sb);
2568+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
2569+ si_read_unlock(sb);
2570+ return err;
2571+}
2572+
2573+static const struct file_operations dbgaufs_xib_fop = {
2574+ .open = dbgaufs_xib_open,
2575+ .release = dbgaufs_xi_release,
2576+ .read = dbgaufs_xi_read
2577+};
2578+
2579+/* ---------------------------------------------------------------------- */
2580+
2581+#define DbgaufsXi_PREFIX "xi"
2582+
2583+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
2584+{
2585+ int err;
2586+ long l;
2587+ struct au_sbinfo *sbinfo;
2588+ struct super_block *sb;
2589+ struct file *xf;
2590+ struct qstr *name;
2591+
2592+ err = -ENOENT;
2593+ xf = NULL;
2594+ name = &file->f_dentry->d_name;
2595+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
2596+ || memcmp(name->name, DbgaufsXi_PREFIX,
2597+ sizeof(DbgaufsXi_PREFIX) - 1)))
2598+ goto out;
2599+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
2600+ if (unlikely(err))
2601+ goto out;
2602+
2603+ sbinfo = inode->i_private;
2604+ sb = sbinfo->si_sb;
2605+ si_noflush_read_lock(sb);
2606+ if (l <= au_sbend(sb)) {
2607+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
2608+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
2609+ } else
2610+ err = -ENOENT;
2611+ si_read_unlock(sb);
2612+
2613+ out:
2614+ return err;
2615+}
2616+
2617+static const struct file_operations dbgaufs_xino_fop = {
2618+ .open = dbgaufs_xino_open,
2619+ .release = dbgaufs_xi_release,
2620+ .read = dbgaufs_xi_read
2621+};
2622+
2623+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
2624+{
2625+ aufs_bindex_t bend;
2626+ struct au_branch *br;
2627+ struct au_xino_file *xi;
2628+
2629+ if (!au_sbi(sb)->si_dbgaufs)
2630+ return;
2631+
2632+ bend = au_sbend(sb);
2633+ for (; bindex <= bend; bindex++) {
2634+ br = au_sbr(sb, bindex);
2635+ xi = &br->br_xino;
2636+ if (xi->xi_dbgaufs) {
2637+ debugfs_remove(xi->xi_dbgaufs);
2638+ xi->xi_dbgaufs = NULL;
2639+ }
2640+ }
2641+}
2642+
2643+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
2644+{
2645+ struct au_sbinfo *sbinfo;
2646+ struct dentry *parent;
2647+ struct au_branch *br;
2648+ struct au_xino_file *xi;
2649+ aufs_bindex_t bend;
2650+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
2651+
2652+ sbinfo = au_sbi(sb);
2653+ parent = sbinfo->si_dbgaufs;
2654+ if (!parent)
2655+ return;
2656+
2657+ bend = au_sbend(sb);
2658+ for (; bindex <= bend; bindex++) {
2659+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
2660+ br = au_sbr(sb, bindex);
2661+ xi = &br->br_xino;
2662+ AuDebugOn(xi->xi_dbgaufs);
2663+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
2664+ sbinfo, &dbgaufs_xino_fop);
2665+ /* ignore an error */
2666+ if (unlikely(!xi->xi_dbgaufs))
2667+ AuWarn1("failed %s under debugfs\n", name);
2668+ }
2669+}
2670+
2671+/* ---------------------------------------------------------------------- */
2672+
2673+#ifdef CONFIG_AUFS_EXPORT
2674+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
2675+{
2676+ int err;
2677+ struct au_sbinfo *sbinfo;
2678+ struct super_block *sb;
2679+
2680+ sbinfo = inode->i_private;
2681+ sb = sbinfo->si_sb;
2682+ si_noflush_read_lock(sb);
2683+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
2684+ si_read_unlock(sb);
2685+ return err;
2686+}
2687+
2688+static const struct file_operations dbgaufs_xigen_fop = {
2689+ .open = dbgaufs_xigen_open,
2690+ .release = dbgaufs_xi_release,
2691+ .read = dbgaufs_xi_read
2692+};
2693+
2694+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
2695+{
2696+ int err;
2697+
dece6358
AM
2698+ /*
2699+ * This function is a dynamic '__init' fucntion actually,
2700+ * so the tiny check for si_rwsem is unnecessary.
2701+ */
2702+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2703+
1facf9fc 2704+ err = -EIO;
2705+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
2706+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
2707+ &dbgaufs_xigen_fop);
2708+ if (sbinfo->si_dbgaufs_xigen)
2709+ err = 0;
2710+
2711+ return err;
2712+}
2713+#else
2714+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
2715+{
2716+ return 0;
2717+}
2718+#endif /* CONFIG_AUFS_EXPORT */
2719+
2720+/* ---------------------------------------------------------------------- */
2721+
2722+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
2723+{
dece6358
AM
2724+ /*
2725+ * This function is a dynamic '__init' fucntion actually,
2726+ * so the tiny check for si_rwsem is unnecessary.
2727+ */
2728+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2729+
1facf9fc 2730+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
2731+ sbinfo->si_dbgaufs = NULL;
2732+ kobject_put(&sbinfo->si_kobj);
2733+}
2734+
2735+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
2736+{
2737+ int err;
2738+ char name[SysaufsSiNameLen];
2739+
dece6358
AM
2740+ /*
2741+ * This function is a dynamic '__init' fucntion actually,
2742+ * so the tiny check for si_rwsem is unnecessary.
2743+ */
2744+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2745+
1facf9fc 2746+ err = -ENOENT;
2747+ if (!dbgaufs) {
2748+ AuErr1("/debug/aufs is uninitialized\n");
2749+ goto out;
2750+ }
2751+
2752+ err = -EIO;
2753+ sysaufs_name(sbinfo, name);
2754+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
2755+ if (unlikely(!sbinfo->si_dbgaufs))
2756+ goto out;
2757+ kobject_get(&sbinfo->si_kobj);
2758+
2759+ sbinfo->si_dbgaufs_xib = debugfs_create_file
2760+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
2761+ &dbgaufs_xib_fop);
2762+ if (unlikely(!sbinfo->si_dbgaufs_xib))
2763+ goto out_dir;
2764+
2765+ err = dbgaufs_xigen_init(sbinfo);
2766+ if (!err)
2767+ goto out; /* success */
2768+
2769+ out_dir:
2770+ dbgaufs_si_fin(sbinfo);
2771+ out:
2772+ return err;
2773+}
2774+
2775+/* ---------------------------------------------------------------------- */
2776+
2777+void dbgaufs_fin(void)
2778+{
2779+ debugfs_remove(dbgaufs);
2780+}
2781+
2782+int __init dbgaufs_init(void)
2783+{
2784+ int err;
2785+
2786+ err = -EIO;
2787+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
2788+ if (dbgaufs)
2789+ err = 0;
2790+ return err;
2791+}
dece6358
AM
2792diff -urN linux-2.6.30.org/fs/aufs/dbgaufs.h linux-2.6.30/fs/aufs/dbgaufs.h
2793--- linux-2.6.30.org/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
2794+++ linux-2.6.30/fs/aufs/dbgaufs.h 2009-07-21 08:54:19.000000000 +0200
2795@@ -0,0 +1,79 @@
1facf9fc 2796+/*
2797+ * Copyright (C) 2005-2009 Junjiro R. Okajima
2798+ *
2799+ * This program, aufs is free software; you can redistribute it and/or modify
2800+ * it under the terms of the GNU General Public License as published by
2801+ * the Free Software Foundation; either version 2 of the License, or
2802+ * (at your option) any later version.
dece6358
AM
2803+ *
2804+ * This program is distributed in the hope that it will be useful,
2805+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2806+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2807+ * GNU General Public License for more details.
2808+ *
2809+ * You should have received a copy of the GNU General Public License
2810+ * along with this program; if not, write to the Free Software
2811+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2812+ */
2813+
2814+/*
2815+ * debugfs interface
2816+ */
2817+
2818+#ifndef __DBGAUFS_H__
2819+#define __DBGAUFS_H__
2820+
2821+#ifdef __KERNEL__
2822+
dece6358 2823+#include <linux/init.h>
1facf9fc 2824+#include <linux/aufs_type.h>
2825+
dece6358 2826+struct super_block;
1facf9fc 2827+struct au_sbinfo;
dece6358 2828+
1facf9fc 2829+#ifdef CONFIG_DEBUG_FS
2830+/* dbgaufs.c */
2831+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
2832+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
2833+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
2834+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
2835+void dbgaufs_fin(void);
2836+int __init dbgaufs_init(void);
2837+
2838+#else
2839+
2840+static inline
2841+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
2842+{
2843+ /* empty */
2844+}
2845+
2846+static inline
2847+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
2848+{
2849+ /* empty */
2850+}
2851+
2852+static inline
2853+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
2854+{
2855+ /* empty */
2856+}
2857+
2858+static inline
2859+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
2860+{
2861+ return 0;
2862+}
2863+
2864+#define dbgaufs_fin() do {} while (0)
2865+
2866+static inline
2867+int __init dbgaufs_init(void)
2868+{
2869+ return 0;
2870+}
2871+#endif /* CONFIG_DEBUG_FS */
2872+
2873+#endif /* __KERNEL__ */
2874+#endif /* __DBGAUFS_H__ */
dece6358
AM
2875diff -urN linux-2.6.30.org/fs/aufs/dcsub.c linux-2.6.30/fs/aufs/dcsub.c
2876--- linux-2.6.30.org/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
2877+++ linux-2.6.30/fs/aufs/dcsub.c 2009-07-21 08:54:19.000000000 +0200
2878@@ -0,0 +1,223 @@
1facf9fc 2879+/*
2880+ * Copyright (C) 2005-2009 Junjiro R. Okajima
2881+ *
2882+ * This program, aufs is free software; you can redistribute it and/or modify
2883+ * it under the terms of the GNU General Public License as published by
2884+ * the Free Software Foundation; either version 2 of the License, or
2885+ * (at your option) any later version.
dece6358
AM
2886+ *
2887+ * This program is distributed in the hope that it will be useful,
2888+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2889+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2890+ * GNU General Public License for more details.
2891+ *
2892+ * You should have received a copy of the GNU General Public License
2893+ * along with this program; if not, write to the Free Software
2894+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2895+ */
2896+
2897+/*
2898+ * sub-routines for dentry cache
2899+ */
2900+
2901+#include "aufs.h"
2902+
2903+static void au_dpage_free(struct au_dpage *dpage)
2904+{
2905+ int i;
2906+ struct dentry **p;
2907+
2908+ p = dpage->dentries;
2909+ for (i = 0; i < dpage->ndentry; i++)
2910+ dput(*p++);
2911+ free_page((unsigned long)dpage->dentries);
2912+}
2913+
2914+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
2915+{
2916+ int err;
2917+ void *p;
2918+
2919+ err = -ENOMEM;
2920+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
2921+ if (unlikely(!dpages->dpages))
2922+ goto out;
2923+
2924+ p = (void *)__get_free_page(gfp);
2925+ if (unlikely(!p))
2926+ goto out_dpages;
2927+
2928+ dpages->dpages[0].ndentry = 0;
2929+ dpages->dpages[0].dentries = p;
2930+ dpages->ndpage = 1;
2931+ return 0; /* success */
2932+
2933+ out_dpages:
2934+ kfree(dpages->dpages);
2935+ out:
2936+ return err;
2937+}
2938+
2939+void au_dpages_free(struct au_dcsub_pages *dpages)
2940+{
2941+ int i;
2942+ struct au_dpage *p;
2943+
2944+ p = dpages->dpages;
2945+ for (i = 0; i < dpages->ndpage; i++)
2946+ au_dpage_free(p++);
2947+ kfree(dpages->dpages);
2948+}
2949+
2950+static int au_dpages_append(struct au_dcsub_pages *dpages,
2951+ struct dentry *dentry, gfp_t gfp)
2952+{
2953+ int err, sz;
2954+ struct au_dpage *dpage;
2955+ void *p;
2956+
2957+ dpage = dpages->dpages + dpages->ndpage - 1;
2958+ sz = PAGE_SIZE / sizeof(dentry);
2959+ if (unlikely(dpage->ndentry >= sz)) {
2960+ AuLabel(new dpage);
2961+ err = -ENOMEM;
2962+ sz = dpages->ndpage * sizeof(*dpages->dpages);
2963+ p = au_kzrealloc(dpages->dpages, sz,
2964+ sz + sizeof(*dpages->dpages), gfp);
2965+ if (unlikely(!p))
2966+ goto out;
2967+
2968+ dpages->dpages = p;
2969+ dpage = dpages->dpages + dpages->ndpage;
2970+ p = (void *)__get_free_page(gfp);
2971+ if (unlikely(!p))
2972+ goto out;
2973+
2974+ dpage->ndentry = 0;
2975+ dpage->dentries = p;
2976+ dpages->ndpage++;
2977+ }
2978+
2979+ dpage->dentries[dpage->ndentry++] = dget(dentry);
2980+ return 0; /* success */
2981+
2982+ out:
2983+ return err;
2984+}
2985+
2986+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
2987+ au_dpages_test test, void *arg)
2988+{
2989+ int err;
2990+ struct dentry *this_parent = root;
2991+ struct list_head *next;
2992+ struct super_block *sb = root->d_sb;
2993+
2994+ err = 0;
2995+ spin_lock(&dcache_lock);
2996+ repeat:
2997+ next = this_parent->d_subdirs.next;
2998+ resume:
2999+ if (this_parent->d_sb == sb
3000+ && !IS_ROOT(this_parent)
3001+ && atomic_read(&this_parent->d_count)
3002+ && this_parent->d_inode
3003+ && (!test || test(this_parent, arg))) {
3004+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3005+ if (unlikely(err))
3006+ goto out;
3007+ }
3008+
3009+ while (next != &this_parent->d_subdirs) {
3010+ struct list_head *tmp = next;
3011+ struct dentry *dentry = list_entry(tmp, struct dentry,
3012+ d_u.d_child);
3013+ next = tmp->next;
3014+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3015+ continue;
3016+ if (!list_empty(&dentry->d_subdirs)) {
3017+ this_parent = dentry;
3018+ goto repeat;
3019+ }
3020+ if (dentry->d_sb == sb
3021+ && atomic_read(&dentry->d_count)
3022+ && (!test || test(dentry, arg))) {
3023+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3024+ if (unlikely(err))
3025+ goto out;
3026+ }
3027+ }
3028+
3029+ if (this_parent != root) {
3030+ next = this_parent->d_u.d_child.next;
3031+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3032+ goto resume;
3033+ }
3034+ out:
3035+ spin_unlock(&dcache_lock);
3036+ return err;
3037+}
3038+
3039+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3040+ int do_include, au_dpages_test test, void *arg)
3041+{
3042+ int err;
3043+
3044+ err = 0;
3045+ spin_lock(&dcache_lock);
3046+ if (do_include && (!test || test(dentry, arg))) {
3047+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3048+ if (unlikely(err))
3049+ goto out;
3050+ }
3051+ while (!IS_ROOT(dentry)) {
3052+ dentry = dentry->d_parent; /* dcache_lock is locked */
3053+ if (!test || test(dentry, arg)) {
3054+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3055+ if (unlikely(err))
3056+ break;
3057+ }
3058+ }
3059+
3060+ out:
3061+ spin_unlock(&dcache_lock);
3062+
3063+ return err;
3064+}
3065+
3066+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
3067+{
3068+ struct dentry *trap, **dentries;
3069+ int err, i, j;
3070+ struct au_dcsub_pages dpages;
3071+ struct au_dpage *dpage;
3072+
3073+ trap = ERR_PTR(-ENOMEM);
3074+ err = au_dpages_init(&dpages, GFP_NOFS);
3075+ if (unlikely(err))
3076+ goto out;
3077+ err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
3078+ if (unlikely(err))
3079+ goto out_dpages;
3080+
3081+ trap = d1;
3082+ for (i = 0; !err && i < dpages.ndpage; i++) {
3083+ dpage = dpages.dpages + i;
3084+ dentries = dpage->dentries;
3085+ for (j = 0; !err && j < dpage->ndentry; j++) {
3086+ struct dentry *d;
3087+
3088+ d = dentries[j];
3089+ err = (d == d2);
3090+ if (!err)
3091+ trap = d;
3092+ }
3093+ }
3094+ if (!err)
3095+ trap = NULL;
3096+
3097+ out_dpages:
3098+ au_dpages_free(&dpages);
3099+ out:
3100+ return trap;
3101+}
dece6358
AM
3102diff -urN linux-2.6.30.org/fs/aufs/dcsub.h linux-2.6.30/fs/aufs/dcsub.h
3103--- linux-2.6.30.org/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
3104+++ linux-2.6.30/fs/aufs/dcsub.h 2009-07-21 08:54:19.000000000 +0200
3105@@ -0,0 +1,54 @@
1facf9fc 3106+/*
3107+ * Copyright (C) 2005-2009 Junjiro R. Okajima
3108+ *
3109+ * This program, aufs is free software; you can redistribute it and/or modify
3110+ * it under the terms of the GNU General Public License as published by
3111+ * the Free Software Foundation; either version 2 of the License, or
3112+ * (at your option) any later version.
dece6358
AM
3113+ *
3114+ * This program is distributed in the hope that it will be useful,
3115+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3116+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3117+ * GNU General Public License for more details.
3118+ *
3119+ * You should have received a copy of the GNU General Public License
3120+ * along with this program; if not, write to the Free Software
3121+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3122+ */
3123+
3124+/*
3125+ * sub-routines for dentry cache
3126+ */
3127+
3128+#ifndef __AUFS_DCSUB_H__
3129+#define __AUFS_DCSUB_H__
3130+
3131+#ifdef __KERNEL__
3132+
dece6358
AM
3133+#include <linux/types.h>
3134+
3135+struct dentry;
1facf9fc 3136+
3137+struct au_dpage {
3138+ int ndentry;
3139+ struct dentry **dentries;
3140+};
3141+
3142+struct au_dcsub_pages {
3143+ int ndpage;
3144+ struct au_dpage *dpages;
3145+};
3146+
3147+/* ---------------------------------------------------------------------- */
3148+
3149+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3150+void au_dpages_free(struct au_dcsub_pages *dpages);
3151+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3152+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3153+ au_dpages_test test, void *arg);
3154+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3155+ int do_include, au_dpages_test test, void *arg);
3156+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
3157+
3158+#endif /* __KERNEL__ */
3159+#endif /* __AUFS_DCSUB_H__ */
dece6358
AM
3160diff -urN linux-2.6.30.org/fs/aufs/debug.c linux-2.6.30/fs/aufs/debug.c
3161--- linux-2.6.30.org/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
3162+++ linux-2.6.30/fs/aufs/debug.c 2009-07-21 08:54:19.000000000 +0200
3163@@ -0,0 +1,427 @@
1facf9fc 3164+/*
3165+ * Copyright (C) 2005-2009 Junjiro R. Okajima
3166+ *
3167+ * This program, aufs is free software; you can redistribute it and/or modify
3168+ * it under the terms of the GNU General Public License as published by
3169+ * the Free Software Foundation; either version 2 of the License, or
3170+ * (at your option) any later version.
dece6358
AM
3171+ *
3172+ * This program is distributed in the hope that it will be useful,
3173+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3174+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3175+ * GNU General Public License for more details.
3176+ *
3177+ * You should have received a copy of the GNU General Public License
3178+ * along with this program; if not, write to the Free Software
3179+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3180+ */
3181+
3182+/*
3183+ * debug print functions
3184+ */
3185+
dece6358
AM
3186+#include <linux/module.h>
3187+#include <linux/vt_kern.h>
1facf9fc 3188+#include "aufs.h"
3189+
3190+int aufs_debug;
3191+MODULE_PARM_DESC(debug, "debug print");
3192+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3193+
3194+char *au_plevel = KERN_DEBUG;
3195+#define dpri(fmt, arg...) do { \
3196+ if (au_debug_test()) \
3197+ printk("%s" fmt, au_plevel, ##arg); \
3198+} while (0)
3199+
3200+/* ---------------------------------------------------------------------- */
3201+
3202+void au_dpri_whlist(struct au_nhash *whlist)
3203+{
3204+ unsigned long ul, n;
3205+ struct hlist_head *head;
3206+ struct au_vdir_wh *tpos;
3207+ struct hlist_node *pos;
3208+
3209+ n = whlist->nh_num;
3210+ head = whlist->nh_head;
3211+ for (ul = 0; ul < n; ul++) {
3212+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3213+ dpri("b%d, %.*s, %d\n",
3214+ tpos->wh_bindex,
3215+ tpos->wh_str.len, tpos->wh_str.name,
3216+ tpos->wh_str.len);
3217+ head++;
3218+ }
3219+}
3220+
3221+void au_dpri_vdir(struct au_vdir *vdir)
3222+{
3223+ unsigned long ul;
3224+ union au_vdir_deblk_p p;
3225+ unsigned char *o;
3226+
3227+ if (!vdir || IS_ERR(vdir)) {
3228+ dpri("err %ld\n", PTR_ERR(vdir));
3229+ return;
3230+ }
3231+
3232+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3233+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3234+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3235+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3236+ p.deblk = vdir->vd_deblk[ul];
3237+ o = p.deblk;
3238+ dpri("[%lu]: %p\n", ul, o);
3239+ }
3240+}
3241+
3242+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3243+ struct dentry *wh)
3244+{
3245+ char *n = NULL;
3246+ int l = 0;
3247+
3248+ if (!inode || IS_ERR(inode)) {
3249+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3250+ return -1;
3251+ }
3252+
3253+ /* the type of i_blocks depends upon CONFIG_LSF */
3254+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3255+ && sizeof(inode->i_blocks) != sizeof(u64));
3256+ if (wh) {
3257+ n = (void *)wh->d_name.name;
3258+ l = wh->d_name.len;
3259+ }
3260+
3261+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
3262+ " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
3263+ bindex,
3264+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3265+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3266+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3267+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3268+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
3269+ inode->i_state, inode->i_flags, inode->i_generation,
3270+ l ? ", wh " : "", l, n);
3271+ return 0;
3272+}
3273+
3274+void au_dpri_inode(struct inode *inode)
3275+{
3276+ struct au_iinfo *iinfo;
3277+ aufs_bindex_t bindex;
3278+ int err;
3279+
3280+ err = do_pri_inode(-1, inode, NULL);
3281+ if (err || !au_test_aufs(inode->i_sb))
3282+ return;
3283+
3284+ iinfo = au_ii(inode);
3285+ if (!iinfo)
3286+ return;
3287+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3288+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3289+ if (iinfo->ii_bstart < 0)
3290+ return;
3291+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3292+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3293+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3294+}
3295+
3296+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3297+{
3298+ struct dentry *wh = NULL;
3299+
3300+ if (!dentry || IS_ERR(dentry)) {
3301+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3302+ return -1;
3303+ }
3304+ /* do not call dget_parent() here */
3305+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3306+ bindex,
3307+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3308+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3309+ atomic_read(&dentry->d_count), dentry->d_flags);
3310+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3311+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3312+ if (iinfo)
3313+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3314+ }
3315+ do_pri_inode(bindex, dentry->d_inode, wh);
3316+ return 0;
3317+}
3318+
3319+void au_dpri_dentry(struct dentry *dentry)
3320+{
3321+ struct au_dinfo *dinfo;
3322+ aufs_bindex_t bindex;
3323+ int err;
3324+
3325+ err = do_pri_dentry(-1, dentry);
3326+ if (err || !au_test_aufs(dentry->d_sb))
3327+ return;
3328+
3329+ dinfo = au_di(dentry);
3330+ if (!dinfo)
3331+ return;
3332+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3333+ dinfo->di_bstart, dinfo->di_bend,
3334+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3335+ if (dinfo->di_bstart < 0)
3336+ return;
3337+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
3338+ do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
3339+}
3340+
3341+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3342+{
3343+ char a[32];
3344+
3345+ if (!file || IS_ERR(file)) {
3346+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3347+ return -1;
3348+ }
3349+ a[0] = 0;
3350+ if (bindex < 0
3351+ && file->f_dentry
3352+ && au_test_aufs(file->f_dentry->d_sb)
3353+ && au_fi(file))
3354+ snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
3355+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
3356+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
3357+ file->f_pos, a);
3358+ if (file->f_dentry)
3359+ do_pri_dentry(bindex, file->f_dentry);
3360+ return 0;
3361+}
3362+
3363+void au_dpri_file(struct file *file)
3364+{
3365+ struct au_finfo *finfo;
3366+ aufs_bindex_t bindex;
3367+ int err;
3368+
3369+ err = do_pri_file(-1, file);
3370+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3371+ return;
3372+
3373+ finfo = au_fi(file);
3374+ if (!finfo)
3375+ return;
3376+ if (finfo->fi_bstart < 0)
3377+ return;
3378+ for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
3379+ struct au_hfile *hf;
3380+
3381+ hf = finfo->fi_hfile + bindex;
3382+ do_pri_file(bindex, hf ? hf->hf_file : NULL);
3383+ }
3384+}
3385+
3386+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3387+{
3388+ struct vfsmount *mnt;
3389+ struct super_block *sb;
3390+
3391+ if (!br || IS_ERR(br))
3392+ goto out;
3393+ mnt = br->br_mnt;
3394+ if (!mnt || IS_ERR(mnt))
3395+ goto out;
3396+ sb = mnt->mnt_sb;
3397+ if (!sb || IS_ERR(sb))
3398+ goto out;
3399+
3400+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
3401+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
3402+ "xino %d\n",
3403+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3404+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
3405+ sb->s_flags, sb->s_count - S_BIAS,
3406+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3407+ return 0;
3408+
3409+ out:
3410+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3411+ return -1;
3412+}
3413+
3414+void au_dpri_sb(struct super_block *sb)
3415+{
3416+ struct au_sbinfo *sbinfo;
3417+ aufs_bindex_t bindex;
3418+ int err;
3419+ /* to reuduce stack size */
3420+ struct {
3421+ struct vfsmount mnt;
3422+ struct au_branch fake;
3423+ } *a;
3424+
3425+ /* this function can be called from magic sysrq */
3426+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3427+ if (unlikely(!a)) {
3428+ dpri("no memory\n");
3429+ return;
3430+ }
3431+
3432+ a->mnt.mnt_sb = sb;
3433+ a->fake.br_perm = 0;
3434+ a->fake.br_mnt = &a->mnt;
3435+ a->fake.br_xino.xi_file = NULL;
3436+ atomic_set(&a->fake.br_count, 0);
3437+ smp_mb(); /* atomic_set */
3438+ err = do_pri_br(-1, &a->fake);
3439+ kfree(a);
3440+ dpri("dev 0x%x\n", sb->s_dev);
3441+ if (err || !au_test_aufs(sb))
3442+ return;
3443+
3444+ sbinfo = au_sbi(sb);
3445+ if (!sbinfo)
3446+ return;
3447+ dpri("nw %d, gen %u, kobj %d\n",
3448+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3449+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3450+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3451+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3452+}
3453+
3454+/* ---------------------------------------------------------------------- */
3455+
3456+void au_dbg_sleep_jiffy(int jiffy)
3457+{
3458+ while (jiffy)
3459+ jiffy = schedule_timeout_uninterruptible(jiffy);
3460+}
3461+
3462+void au_dbg_iattr(struct iattr *ia)
3463+{
3464+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3465+ dpri(#name "\n")
3466+ AuBit(MODE);
3467+ AuBit(UID);
3468+ AuBit(GID);
3469+ AuBit(SIZE);
3470+ AuBit(ATIME);
3471+ AuBit(MTIME);
3472+ AuBit(CTIME);
3473+ AuBit(ATIME_SET);
3474+ AuBit(MTIME_SET);
3475+ AuBit(FORCE);
3476+ AuBit(ATTR_FLAG);
3477+ AuBit(KILL_SUID);
3478+ AuBit(KILL_SGID);
3479+ AuBit(FILE);
3480+ AuBit(KILL_PRIV);
3481+ AuBit(OPEN);
3482+ AuBit(TIMES_SET);
3483+#undef AuBit
3484+ dpri("ia_file %p\n", ia->ia_file);
3485+}
3486+
3487+/* ---------------------------------------------------------------------- */
3488+
3489+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3490+{
3491+ struct dentry *parent;
3492+
3493+ parent = dget_parent(dentry);
3494+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3495+ || IS_ROOT(dentry)
3496+ || au_digen(parent) != sigen);
3497+ dput(parent);
3498+}
3499+
3500+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3501+{
3502+ struct dentry *parent;
3503+
3504+ parent = dget_parent(dentry);
3505+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3506+ || au_digen(parent) != sigen);
3507+ dput(parent);
3508+}
3509+
3510+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3511+{
3512+ int err, i, j;
3513+ struct au_dcsub_pages dpages;
3514+ struct au_dpage *dpage;
3515+ struct dentry **dentries;
3516+
3517+ err = au_dpages_init(&dpages, GFP_NOFS);
3518+ AuDebugOn(err);
3519+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3520+ AuDebugOn(err);
3521+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3522+ dpage = dpages.dpages + i;
3523+ dentries = dpage->dentries;
3524+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3525+ AuDebugOn(au_digen(dentries[j]) != sigen);
3526+ }
3527+ au_dpages_free(&dpages);
3528+}
3529+
3530+void au_dbg_verify_hf(struct au_finfo *finfo)
3531+{
3532+ struct au_hfile *hf;
3533+ aufs_bindex_t bend, bindex;
3534+
3535+ if (finfo->fi_bstart >= 0) {
3536+ bend = finfo->fi_bend;
3537+ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
3538+ hf = finfo->fi_hfile + bindex;
3539+ AuDebugOn(hf->hf_file || hf->hf_br);
3540+ }
3541+ }
3542+}
3543+
3544+void au_dbg_verify_kthread(void)
3545+{
3546+ if (au_test_wkq(current)) {
3547+ au_dbg_blocked();
3548+ BUG();
3549+ }
3550+}
3551+
3552+/* ---------------------------------------------------------------------- */
3553+
3554+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
3555+{
3556+#ifdef AuForceNoPlink
3557+ au_opt_clr(sbinfo->si_mntflags, PLINK);
3558+#endif
3559+#ifdef AuForceNoXino
3560+ au_opt_clr(sbinfo->si_mntflags, XINO);
3561+#endif
3562+#ifdef AuForceNoRefrof
3563+ au_opt_clr(sbinfo->si_mntflags, REFROF);
3564+#endif
3565+#ifdef AuForceHinotify
3566+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HINOTIFY);
3567+#endif
3568+}
3569+
3570+int __init au_debug_init(void)
3571+{
3572+ aufs_bindex_t bindex;
3573+ struct au_vdir_destr destr;
3574+
3575+ bindex = -1;
3576+ AuDebugOn(bindex >= 0);
3577+
3578+ destr.len = -1;
3579+ AuDebugOn(destr.len < NAME_MAX);
3580+
3581+#ifdef CONFIG_4KSTACKS
3582+ AuWarn("CONFIG_4KSTACKS is defined.\n");
3583+#endif
3584+
3585+#ifdef AuForceNoBrs
3586+ sysaufs_brs = 0;
3587+#endif
3588+
3589+ return 0;
3590+}
dece6358
AM
3591diff -urN linux-2.6.30.org/fs/aufs/debug.h linux-2.6.30/fs/aufs/debug.h
3592--- linux-2.6.30.org/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
3593+++ linux-2.6.30/fs/aufs/debug.h 2009-07-21 08:54:19.000000000 +0200
3594@@ -0,0 +1,260 @@
1facf9fc 3595+/*
3596+ * Copyright (C) 2005-2009 Junjiro R. Okajima
3597+ *
3598+ * This program, aufs is free software; you can redistribute it and/or modify
3599+ * it under the terms of the GNU General Public License as published by
3600+ * the Free Software Foundation; either version 2 of the License, or
3601+ * (at your option) any later version.
dece6358
AM
3602+ *
3603+ * This program is distributed in the hope that it will be useful,
3604+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3605+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3606+ * GNU General Public License for more details.
3607+ *
3608+ * You should have received a copy of the GNU General Public License
3609+ * along with this program; if not, write to the Free Software
3610+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3611+ */
3612+
3613+/*
3614+ * debug print functions
3615+ */
3616+
3617+#ifndef __AUFS_DEBUG_H__
3618+#define __AUFS_DEBUG_H__
3619+
3620+#ifdef __KERNEL__
3621+
dece6358
AM
3622+#include <linux/bug.h>
3623+/* #include <linux/err.h> */
3624+/* #include <linux/init.h> */
3625+/* #include <linux/kernel.h> */
1facf9fc 3626+#include <linux/delay.h>
dece6358
AM
3627+/* #include <linux/kd.h> */
3628+/* #include <linux/vt_kern.h> */
1facf9fc 3629+#include <linux/sysrq.h>
3630+#include <linux/aufs_type.h>
3631+
3632+#ifdef CONFIG_AUFS_DEBUG
3633+#define AuDebugOn(a) BUG_ON(a)
3634+
3635+/* module parameter */
3636+extern int aufs_debug;
3637+static inline void au_debug(int n)
3638+{
3639+ aufs_debug = n;
3640+ smp_mb();
3641+}
3642+
3643+static inline int au_debug_test(void)
3644+{
3645+ return aufs_debug;
3646+}
3647+#else
3648+#define AuDebugOn(a) do {} while (0)
3649+#define au_debug() do {} while (0)
3650+static inline int au_debug_test(void)
3651+{
3652+ return 0;
3653+}
3654+#endif /* CONFIG_AUFS_DEBUG */
3655+
3656+/* ---------------------------------------------------------------------- */
3657+
3658+/* debug print */
3659+
3660+#define AuDpri(lvl, fmt, arg...) \
3661+ printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
3662+ __func__, __LINE__, current->comm, current->pid, ##arg)
3663+#define AuDbg(fmt, arg...) do { \
3664+ if (au_debug_test()) \
3665+ AuDpri(KERN_DEBUG, fmt, ##arg); \
3666+} while (0)
3667+#define AuLabel(l) AuDbg(#l "\n")
3668+#define AuInfo(fmt, arg...) AuDpri(KERN_INFO, fmt, ##arg)
3669+#define AuWarn(fmt, arg...) AuDpri(KERN_WARNING, fmt, ##arg)
3670+#define AuErr(fmt, arg...) AuDpri(KERN_ERR, fmt, ##arg)
3671+#define AuIOErr(fmt, arg...) AuErr("I/O Error, " fmt, ##arg)
3672+#define AuWarn1(fmt, arg...) do { \
3673+ static unsigned char _c; \
3674+ if (!_c++) \
3675+ AuWarn(fmt, ##arg); \
3676+} while (0)
3677+
3678+#define AuErr1(fmt, arg...) do { \
3679+ static unsigned char _c; \
3680+ if (!_c++) \
3681+ AuErr(fmt, ##arg); \
3682+} while (0)
3683+
3684+#define AuIOErr1(fmt, arg...) do { \
3685+ static unsigned char _c; \
3686+ if (!_c++) \
3687+ AuIOErr(fmt, ##arg); \
3688+} while (0)
3689+
3690+#define AuUnsupportMsg "This operation is not supported." \
3691+ " Please report this application to aufs-users ML."
3692+#define AuUnsupport(fmt, args...) do { \
3693+ AuErr(AuUnsupportMsg "\n" fmt, ##args); \
3694+ dump_stack(); \
3695+} while (0)
3696+
3697+#define AuTraceErr(e) do { \
3698+ if (unlikely((e) < 0)) \
3699+ AuDbg("err %d\n", (int)(e)); \
3700+} while (0)
3701+
3702+#define AuTraceErrPtr(p) do { \
3703+ if (IS_ERR(p)) \
3704+ AuDbg("err %ld\n", PTR_ERR(p)); \
3705+} while (0)
3706+
3707+/* dirty macros for debug print, use with "%.*s" and caution */
3708+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
3709+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
3710+
3711+/* ---------------------------------------------------------------------- */
3712+
3713+struct au_sbinfo;
3714+struct au_finfo;
dece6358 3715+struct dentry;
1facf9fc 3716+#ifdef CONFIG_AUFS_DEBUG
3717+extern char *au_plevel;
3718+struct au_nhash;
3719+void au_dpri_whlist(struct au_nhash *whlist);
3720+struct au_vdir;
3721+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 3722+struct inode;
1facf9fc 3723+void au_dpri_inode(struct inode *inode);
3724+void au_dpri_dentry(struct dentry *dentry);
dece6358 3725+struct file;
1facf9fc 3726+void au_dpri_file(struct file *filp);
dece6358 3727+struct super_block;
1facf9fc 3728+void au_dpri_sb(struct super_block *sb);
3729+
3730+void au_dbg_sleep_jiffy(int jiffy);
dece6358 3731+struct iattr;
1facf9fc 3732+void au_dbg_iattr(struct iattr *ia);
3733+
3734+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
3735+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
3736+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
3737+void au_dbg_verify_hf(struct au_finfo *finfo);
3738+void au_dbg_verify_kthread(void);
3739+
3740+int __init au_debug_init(void);
3741+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
3742+#define AuDbgWhlist(w) do { \
3743+ AuDbg(#w "\n"); \
3744+ au_dpri_whlist(w); \
3745+} while (0)
3746+
3747+#define AuDbgVdir(v) do { \
3748+ AuDbg(#v "\n"); \
3749+ au_dpri_vdir(v); \
3750+} while (0)
3751+
3752+#define AuDbgInode(i) do { \
3753+ AuDbg(#i "\n"); \
3754+ au_dpri_inode(i); \
3755+} while (0)
3756+
3757+#define AuDbgDentry(d) do { \
3758+ AuDbg(#d "\n"); \
3759+ au_dpri_dentry(d); \
3760+} while (0)
3761+
3762+#define AuDbgFile(f) do { \
3763+ AuDbg(#f "\n"); \
3764+ au_dpri_file(f); \
3765+} while (0)
3766+
3767+#define AuDbgSb(sb) do { \
3768+ AuDbg(#sb "\n"); \
3769+ au_dpri_sb(sb); \
3770+} while (0)
3771+
3772+#define AuDbgSleep(sec) do { \
3773+ AuDbg("sleep %d sec\n", sec); \
3774+ ssleep(sec); \
3775+} while (0)
3776+
3777+#define AuDbgSleepJiffy(jiffy) do { \
3778+ AuDbg("sleep %d jiffies\n", jiffy); \
3779+ au_dbg_sleep_jiffy(jiffy); \
3780+} while (0)
3781+
3782+#define AuDbgIAttr(ia) do { \
3783+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
3784+ au_dbg_iattr(ia); \
3785+} while (0)
3786+#else
3787+static inline void au_dbg_verify_dir_parent(struct dentry *dentry,
3788+ unsigned int sigen)
3789+{
3790+ /* empty */
3791+}
3792+static inline void au_dbg_verify_nondir_parent(struct dentry *dentry,
dece6358 3793+ unsigned int sigen)
1facf9fc 3794+{
3795+ /* empty */
3796+}
3797+static inline void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3798+{
3799+ /* empty */
3800+}
3801+static inline void au_dbg_verify_hf(struct au_finfo *finfo)
3802+{
3803+ /* empty */
3804+}
3805+static inline void au_dbg_verify_kthread(void)
3806+{
3807+ /* empty */
3808+}
3809+
3810+static inline int au_debug_init(void)
3811+{
3812+ return 0;
3813+}
3814+static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
3815+{
3816+ /* empty */
3817+}
3818+#define AuDbgWhlist(w) do {} while (0)
3819+#define AuDbgVdir(v) do {} while (0)
3820+#define AuDbgInode(i) do {} while (0)
3821+#define AuDbgDentry(d) do {} while (0)
3822+#define AuDbgFile(f) do {} while (0)
3823+#define AuDbgSb(sb) do {} while (0)
3824+#define AuDbgSleep(sec) do {} while (0)
3825+#define AuDbgSleepJiffy(jiffy) do {} while (0)
3826+#define AuDbgIAttr(ia) do {} while (0)
3827+#endif /* CONFIG_AUFS_DEBUG */
3828+
3829+/* ---------------------------------------------------------------------- */
3830+
3831+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
3832+int __init au_sysrq_init(void);
3833+void au_sysrq_fin(void);
3834+
3835+#ifdef CONFIG_HW_CONSOLE
3836+#define au_dbg_blocked() do { \
3837+ WARN_ON(1); \
3838+ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
3839+} while (0)
3840+#else
3841+#define au_dbg_blocked() do {} while (0)
3842+#endif
3843+
3844+#else
3845+static inline int au_sysrq_init(void)
3846+{
3847+ return 0;
3848+}
3849+#define au_sysrq_fin() do {} while (0)
3850+#define au_dbg_blocked() do {} while (0)
3851+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
3852+
3853+#endif /* __KERNEL__ */
3854+#endif /* __AUFS_DEBUG_H__ */
dece6358
AM
3855diff -urN linux-2.6.30.org/fs/aufs/dentry.c linux-2.6.30/fs/aufs/dentry.c
3856--- linux-2.6.30.org/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
3857+++ linux-2.6.30/fs/aufs/dentry.c 2009-07-21 08:54:19.000000000 +0200
3858@@ -0,0 +1,876 @@
1facf9fc 3859+/*
3860+ * Copyright (C) 2005-2009 Junjiro R. Okajima
3861+ *
3862+ * This program, aufs is free software; you can redistribute it and/or modify
3863+ * it under the terms of the GNU General Public License as published by
3864+ * the Free Software Foundation; either version 2 of the License, or
3865+ * (at your option) any later version.
dece6358
AM
3866+ *
3867+ * This program is distributed in the hope that it will be useful,
3868+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3869+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3870+ * GNU General Public License for more details.
3871+ *
3872+ * You should have received a copy of the GNU General Public License
3873+ * along with this program; if not, write to the Free Software
3874+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3875+ */
3876+
3877+/*
3878+ * lookup and dentry operations
3879+ */
3880+
dece6358 3881+#include <linux/namei.h>
1facf9fc 3882+#include "aufs.h"
3883+
3884+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
3885+{
3886+ if (nd) {
3887+ *h_nd = *nd;
3888+
3889+ /*
3890+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
3891+ * due to whiteout and branch permission.
3892+ */
3893+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
3894+ | LOOKUP_FOLLOW);
3895+ /* unnecessary? */
3896+ h_nd->intent.open.file = NULL;
3897+ } else
3898+ memset(h_nd, 0, sizeof(*h_nd));
3899+}
3900+
3901+struct au_lkup_one_args {
3902+ struct dentry **errp;
3903+ struct qstr *name;
3904+ struct dentry *h_parent;
3905+ struct au_branch *br;
3906+ struct nameidata *nd;
3907+};
3908+
3909+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
3910+ struct au_branch *br, struct nameidata *nd)
3911+{
3912+ struct dentry *h_dentry;
3913+ int err;
3914+ struct nameidata h_nd;
3915+
3916+ if (au_test_fs_null_nd(h_parent->d_sb))
3917+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
3918+
3919+ au_h_nd(&h_nd, nd);
3920+ h_nd.path.dentry = h_parent;
3921+ h_nd.path.mnt = br->br_mnt;
3922+
3923+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
3924+ h_dentry = ERR_PTR(err);
3925+ if (!err) {
3926+ path_get(&h_nd.path);
3927+ h_dentry = vfsub_lookup_hash(&h_nd);
3928+ path_put(&h_nd.path);
3929+ }
3930+
3931+ return h_dentry;
3932+}
3933+
3934+static void au_call_lkup_one(void *args)
3935+{
3936+ struct au_lkup_one_args *a = args;
3937+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
3938+}
3939+
3940+#define AuLkup_ALLOW_NEG 1
3941+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
3942+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
3943+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
3944+
3945+struct au_do_lookup_args {
3946+ unsigned int flags;
3947+ mode_t type;
3948+ struct nameidata *nd;
3949+};
3950+
3951+/*
3952+ * returns positive/negative dentry, NULL or an error.
3953+ * NULL means whiteout-ed or not-found.
3954+ */
3955+static struct dentry*
3956+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
3957+ aufs_bindex_t bindex, struct qstr *wh_name,
3958+ struct au_do_lookup_args *args)
3959+{
3960+ struct dentry *h_dentry;
3961+ struct inode *h_inode, *inode;
3962+ struct qstr *name;
3963+ struct au_branch *br;
3964+ int wh_found, opq;
3965+ unsigned char wh_able;
3966+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
3967+
3968+ name = &dentry->d_name;
3969+ wh_found = 0;
3970+ br = au_sbr(dentry->d_sb, bindex);
3971+ wh_able = !!au_br_whable(br->br_perm);
3972+ if (wh_able)
3973+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
3974+ h_dentry = ERR_PTR(wh_found);
3975+ if (!wh_found)
3976+ goto real_lookup;
3977+ if (unlikely(wh_found < 0))
3978+ goto out;
3979+
3980+ /* We found a whiteout */
3981+ /* au_set_dbend(dentry, bindex); */
3982+ au_set_dbwh(dentry, bindex);
3983+ if (!allow_neg)
3984+ return NULL; /* success */
3985+
3986+ real_lookup:
3987+ h_dentry = au_lkup_one(name, h_parent, br, args->nd);
3988+ if (IS_ERR(h_dentry))
3989+ goto out;
3990+
3991+ h_inode = h_dentry->d_inode;
3992+ if (!h_inode) {
3993+ if (!allow_neg)
3994+ goto out_neg;
3995+ } else if (wh_found
3996+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
3997+ goto out_neg;
3998+
3999+ if (au_dbend(dentry) <= bindex)
4000+ au_set_dbend(dentry, bindex);
4001+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4002+ au_set_dbstart(dentry, bindex);
4003+ au_set_h_dptr(dentry, bindex, h_dentry);
4004+
4005+ inode = dentry->d_inode;
4006+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4007+ || (inode && !S_ISDIR(inode->i_mode)))
4008+ goto out; /* success */
4009+
4010+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4011+ opq = au_diropq_test(h_dentry, br);
4012+ mutex_unlock(&h_inode->i_mutex);
4013+ if (opq > 0)
4014+ au_set_dbdiropq(dentry, bindex);
4015+ else if (unlikely(opq < 0)) {
4016+ au_set_h_dptr(dentry, bindex, NULL);
4017+ h_dentry = ERR_PTR(opq);
4018+ }
4019+ goto out;
4020+
4021+ out_neg:
4022+ dput(h_dentry);
4023+ h_dentry = NULL;
4024+ out:
4025+ return h_dentry;
4026+}
4027+
dece6358
AM
4028+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4029+{
4030+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4031+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4032+ return -EPERM;
4033+ return 0;
4034+}
4035+
1facf9fc 4036+/*
4037+ * returns the number of lower positive dentries,
4038+ * otherwise an error.
4039+ * can be called at unlinking with @type is zero.
4040+ */
4041+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4042+ struct nameidata *nd)
4043+{
4044+ int npositive, err;
4045+ aufs_bindex_t bindex, btail, bdiropq;
4046+ unsigned char isdir;
4047+ struct qstr whname;
4048+ struct au_do_lookup_args args = {
4049+ .flags = 0,
4050+ .type = type,
4051+ .nd = nd
4052+ };
4053+ const struct qstr *name = &dentry->d_name;
4054+ struct dentry *parent;
4055+ struct inode *inode;
4056+
1facf9fc 4057+ parent = dget_parent(dentry);
dece6358
AM
4058+ err = au_test_shwh(dentry->d_sb, name);
4059+ if (unlikely(err))
1facf9fc 4060+ goto out;
4061+
4062+ err = au_wh_name_alloc(&whname, name);
4063+ if (unlikely(err))
4064+ goto out;
4065+
4066+ inode = dentry->d_inode;
4067+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4068+ if (!type)
4069+ au_fset_lkup(args.flags, ALLOW_NEG);
4070+
4071+ npositive = 0;
4072+ btail = au_dbtaildir(parent);
4073+ for (bindex = bstart; bindex <= btail; bindex++) {
4074+ struct dentry *h_parent, *h_dentry;
4075+ struct inode *h_inode, *h_dir;
4076+
4077+ h_dentry = au_h_dptr(dentry, bindex);
4078+ if (h_dentry) {
4079+ if (h_dentry->d_inode)
4080+ npositive++;
4081+ if (type != S_IFDIR)
4082+ break;
4083+ continue;
4084+ }
4085+ h_parent = au_h_dptr(parent, bindex);
4086+ if (!h_parent)
4087+ continue;
4088+ h_dir = h_parent->d_inode;
4089+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4090+ continue;
4091+
4092+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4093+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4094+ &args);
4095+ mutex_unlock(&h_dir->i_mutex);
4096+ err = PTR_ERR(h_dentry);
4097+ if (IS_ERR(h_dentry))
4098+ goto out_wh;
4099+ au_fclr_lkup(args.flags, ALLOW_NEG);
4100+
4101+ if (au_dbwh(dentry) >= 0)
4102+ break;
4103+ if (!h_dentry)
4104+ continue;
4105+ h_inode = h_dentry->d_inode;
4106+ if (!h_inode)
4107+ continue;
4108+ npositive++;
4109+ if (!args.type)
4110+ args.type = h_inode->i_mode & S_IFMT;
4111+ if (args.type != S_IFDIR)
4112+ break;
4113+ else if (isdir) {
4114+ /* the type of lower may be different */
4115+ bdiropq = au_dbdiropq(dentry);
4116+ if (bdiropq >= 0 && bdiropq <= bindex)
4117+ break;
4118+ }
4119+ }
4120+
4121+ if (npositive) {
4122+ AuLabel(positive);
4123+ au_update_dbstart(dentry);
4124+ }
4125+ err = npositive;
4126+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4127+ && au_dbstart(dentry) < 0))
4128+ /* both of real entry and whiteout found */
4129+ err = -EIO;
4130+
4131+ out_wh:
4132+ kfree(whname.name);
4133+ out:
4134+ dput(parent);
4135+ return err;
4136+}
4137+
4138+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4139+ struct au_branch *br)
4140+{
4141+ struct dentry *dentry;
4142+ int wkq_err;
4143+
4144+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4145+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4146+ else {
4147+ struct au_lkup_one_args args = {
4148+ .errp = &dentry,
4149+ .name = name,
4150+ .h_parent = parent,
4151+ .br = br,
4152+ .nd = NULL
4153+ };
4154+
4155+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4156+ if (unlikely(wkq_err))
4157+ dentry = ERR_PTR(wkq_err);
4158+ }
4159+
4160+ return dentry;
4161+}
4162+
4163+/*
4164+ * lookup @dentry on @bindex which should be negative.
4165+ */
4166+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4167+{
4168+ int err;
4169+ struct dentry *parent, *h_parent, *h_dentry;
4170+ struct qstr *name;
4171+
4172+ name = &dentry->d_name;
4173+ parent = dget_parent(dentry);
4174+ h_parent = au_h_dptr(parent, bindex);
4175+ h_dentry = au_sio_lkup_one(name, h_parent,
4176+ au_sbr(dentry->d_sb, bindex));
4177+ err = PTR_ERR(h_dentry);
4178+ if (IS_ERR(h_dentry))
4179+ goto out;
4180+ if (unlikely(h_dentry->d_inode)) {
4181+ err = -EIO;
4182+ AuIOErr("b%d %.*s should be negative.\n",
4183+ bindex, AuDLNPair(h_dentry));
4184+ dput(h_dentry);
4185+ goto out;
4186+ }
4187+
4188+ if (bindex < au_dbstart(dentry))
4189+ au_set_dbstart(dentry, bindex);
4190+ if (au_dbend(dentry) < bindex)
4191+ au_set_dbend(dentry, bindex);
4192+ au_set_h_dptr(dentry, bindex, h_dentry);
4193+ err = 0;
4194+
4195+ out:
4196+ dput(parent);
4197+ return err;
4198+}
4199+
4200+/* ---------------------------------------------------------------------- */
4201+
4202+/* subset of struct inode */
4203+struct au_iattr {
4204+ unsigned long i_ino;
4205+ /* unsigned int i_nlink; */
4206+ uid_t i_uid;
4207+ gid_t i_gid;
4208+ u64 i_version;
4209+/*
4210+ loff_t i_size;
4211+ blkcnt_t i_blocks;
4212+*/
4213+ umode_t i_mode;
4214+};
4215+
4216+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4217+{
4218+ ia->i_ino = h_inode->i_ino;
4219+ /* ia->i_nlink = h_inode->i_nlink; */
4220+ ia->i_uid = h_inode->i_uid;
4221+ ia->i_gid = h_inode->i_gid;
4222+ ia->i_version = h_inode->i_version;
4223+/*
4224+ ia->i_size = h_inode->i_size;
4225+ ia->i_blocks = h_inode->i_blocks;
4226+*/
4227+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4228+}
4229+
4230+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4231+{
4232+ return ia->i_ino != h_inode->i_ino
4233+ /* || ia->i_nlink != h_inode->i_nlink */
4234+ || ia->i_uid != h_inode->i_uid
4235+ || ia->i_gid != h_inode->i_gid
4236+ || ia->i_version != h_inode->i_version
4237+/*
4238+ || ia->i_size != h_inode->i_size
4239+ || ia->i_blocks != h_inode->i_blocks
4240+*/
4241+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4242+}
4243+
4244+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4245+ struct au_branch *br)
4246+{
4247+ int err;
4248+ struct au_iattr ia;
4249+ struct inode *h_inode;
4250+ struct dentry *h_d;
4251+ struct super_block *h_sb;
4252+
4253+ err = 0;
4254+ memset(&ia, -1, sizeof(ia));
4255+ h_sb = h_dentry->d_sb;
4256+ h_inode = h_dentry->d_inode;
4257+ if (h_inode)
4258+ au_iattr_save(&ia, h_inode);
4259+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4260+ /* nfs d_revalidate may return 0 for negative dentry */
4261+ /* fuse d_revalidate always return 0 for negative dentry */
4262+ goto out;
4263+
4264+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4265+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4266+ err = PTR_ERR(h_d);
4267+ if (IS_ERR(h_d))
4268+ goto out;
4269+
4270+ err = 0;
4271+ if (unlikely(h_d != h_dentry
4272+ || h_d->d_inode != h_inode
4273+ || (h_inode && au_iattr_test(&ia, h_inode))))
4274+ err = au_busy_or_stale();
4275+ dput(h_d);
4276+
4277+ out:
4278+ AuTraceErr(err);
4279+ return err;
4280+}
4281+
4282+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4283+ struct dentry *h_parent, struct au_branch *br)
4284+{
4285+ int err;
4286+
4287+ err = 0;
4288+ if (udba == AuOpt_UDBA_REVAL) {
4289+ IMustLock(h_dir);
4290+ err = (h_dentry->d_parent->d_inode != h_dir);
4291+ } else if (udba == AuOpt_UDBA_HINOTIFY)
4292+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4293+
4294+ return err;
4295+}
4296+
4297+/* ---------------------------------------------------------------------- */
4298+
4299+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4300+ struct dentry *parent)
4301+{
4302+ struct dentry *h_d, *h_dp;
4303+ struct au_hdentry tmp, *q;
4304+ struct super_block *sb;
4305+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4306+
4307+ bend = dinfo->di_bend;
4308+ bwh = dinfo->di_bwh;
4309+ bdiropq = dinfo->di_bdiropq;
4310+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4311+ h_d = p->hd_dentry;
4312+ if (!h_d)
4313+ continue;
4314+
4315+ h_dp = dget_parent(h_d);
4316+ if (h_dp == au_h_dptr(parent, bindex)) {
4317+ dput(h_dp);
4318+ continue;
4319+ }
4320+
4321+ new_bindex = au_find_dbindex(parent, h_dp);
4322+ dput(h_dp);
4323+ if (dinfo->di_bwh == bindex)
4324+ bwh = new_bindex;
4325+ if (dinfo->di_bdiropq == bindex)
4326+ bdiropq = new_bindex;
4327+ if (new_bindex < 0) {
4328+ au_hdput(p);
4329+ p->hd_dentry = NULL;
4330+ continue;
4331+ }
4332+
4333+ /* swap two lower dentries, and loop again */
4334+ q = dinfo->di_hdentry + new_bindex;
4335+ tmp = *q;
4336+ *q = *p;
4337+ *p = tmp;
4338+ if (tmp.hd_dentry) {
4339+ bindex--;
4340+ p--;
4341+ }
4342+ }
4343+
4344+ sb = parent->d_sb;
4345+ dinfo->di_bwh = -1;
4346+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4347+ dinfo->di_bwh = bwh;
4348+
4349+ dinfo->di_bdiropq = -1;
4350+ if (bdiropq >= 0
4351+ && bdiropq <= au_sbend(sb)
4352+ && au_sbr_whable(sb, bdiropq))
4353+ dinfo->di_bdiropq = bdiropq;
4354+
4355+ bend = au_dbend(parent);
4356+ p = dinfo->di_hdentry;
4357+ for (bindex = 0; bindex <= bend; bindex++, p++)
4358+ if (p->hd_dentry) {
4359+ dinfo->di_bstart = bindex;
4360+ break;
4361+ }
4362+
4363+ p = dinfo->di_hdentry + bend;
4364+ for (bindex = bend; bindex >= 0; bindex--, p--)
4365+ if (p->hd_dentry) {
4366+ dinfo->di_bend = bindex;
4367+ break;
4368+ }
4369+}
4370+
4371+/*
4372+ * returns the number of found lower positive dentries,
4373+ * otherwise an error.
4374+ */
4375+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4376+{
4377+ int npositive, err;
4378+ unsigned int sigen;
4379+ aufs_bindex_t bstart;
4380+ struct au_dinfo *dinfo;
4381+ struct super_block *sb;
4382+ struct dentry *parent;
4383+
4384+ sb = dentry->d_sb;
4385+ AuDebugOn(IS_ROOT(dentry));
4386+ sigen = au_sigen(sb);
4387+ parent = dget_parent(dentry);
4388+ AuDebugOn(au_digen(parent) != sigen
4389+ || au_iigen(parent->d_inode) != sigen);
4390+
4391+ dinfo = au_di(dentry);
4392+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4393+ npositive = err;
4394+ if (unlikely(err))
4395+ goto out;
4396+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4397+ parent);
4398+
4399+ npositive = 0;
4400+ bstart = au_dbstart(parent);
4401+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4402+ goto out_dgen; /* success */
4403+
4404+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4405+ if (npositive < 0)
4406+ goto out;
4407+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4408+ d_drop(dentry);
4409+
4410+ out_dgen:
4411+ au_update_digen(dentry);
4412+ out:
4413+ dput(parent);
4414+ AuTraceErr(npositive);
4415+ return npositive;
4416+}
4417+
4418+static noinline_for_stack
4419+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4420+ struct dentry *dentry, aufs_bindex_t bindex)
4421+{
4422+ int err, valid;
4423+ int (*reval)(struct dentry *, struct nameidata *);
4424+
4425+ err = 0;
4426+ reval = NULL;
4427+ if (h_dentry->d_op)
4428+ reval = h_dentry->d_op->d_revalidate;
4429+ if (!reval)
4430+ goto out;
4431+
4432+ AuDbg("b%d\n", bindex);
4433+ if (au_test_fs_null_nd(h_dentry->d_sb))
4434+ /* it may return tri-state */
4435+ valid = reval(h_dentry, NULL);
4436+ else {
4437+ struct nameidata h_nd;
4438+ int locked;
4439+ struct dentry *parent;
4440+
4441+ au_h_nd(&h_nd, nd);
4442+ parent = nd->path.dentry;
4443+ locked = (nd && nd->path.dentry != dentry);
4444+ if (locked)
4445+ di_read_lock_parent(parent, AuLock_IR);
4446+ BUG_ON(bindex > au_dbend(parent));
4447+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4448+ BUG_ON(!h_nd.path.dentry);
4449+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4450+ path_get(&h_nd.path);
4451+ valid = reval(h_dentry, &h_nd);
4452+ path_put(&h_nd.path);
4453+ if (locked)
4454+ di_read_unlock(parent, AuLock_IR);
4455+ }
4456+
4457+ if (unlikely(valid < 0))
4458+ err = valid;
4459+ else if (!valid)
4460+ err = -EINVAL;
4461+
4462+ out:
4463+ AuTraceErr(err);
4464+ return err;
4465+}
4466+
4467+/* todo: remove this */
4468+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4469+ struct nameidata *nd, int do_udba)
4470+{
4471+ int err;
4472+ umode_t mode, h_mode;
4473+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4474+ unsigned char plus, unhashed, is_root, h_plus;
4475+ struct inode *first, *h_inode, *h_cached_inode;
4476+ struct dentry *h_dentry;
4477+ struct qstr *name, *h_name;
4478+
4479+ err = 0;
4480+ plus = 0;
4481+ mode = 0;
4482+ first = NULL;
4483+ ibs = -1;
4484+ ibe = -1;
4485+ unhashed = !!d_unhashed(dentry);
4486+ is_root = !!IS_ROOT(dentry);
4487+ name = &dentry->d_name;
4488+
4489+ /*
4490+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
4491+ * But inotify doesn't fire some necessary events,
4492+ * IN_ATTRIB for atime/nlink/pageio
4493+ * IN_DELETE for NFS dentry
4494+ * Let's do REVAL test too.
4495+ */
4496+ if (do_udba && inode) {
4497+ mode = (inode->i_mode & S_IFMT);
4498+ plus = (inode->i_nlink > 0);
4499+ first = au_h_iptr(inode, au_ibstart(inode));
4500+ ibs = au_ibstart(inode);
4501+ ibe = au_ibend(inode);
4502+ }
4503+
4504+ bstart = au_dbstart(dentry);
4505+ btail = bstart;
4506+ if (inode && S_ISDIR(inode->i_mode))
4507+ btail = au_dbtaildir(dentry);
4508+ for (bindex = bstart; bindex <= btail; bindex++) {
4509+ h_dentry = au_h_dptr(dentry, bindex);
4510+ if (!h_dentry)
4511+ continue;
4512+
4513+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4514+ h_name = &h_dentry->d_name;
4515+ if (unlikely(do_udba
4516+ && !is_root
4517+ && (unhashed != !!d_unhashed(h_dentry)
4518+ || name->len != h_name->len
4519+ || memcmp(name->name, h_name->name, name->len))
4520+ )) {
4521+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4522+ unhashed, d_unhashed(h_dentry),
4523+ AuDLNPair(dentry), AuDLNPair(h_dentry));
4524+ goto err;
4525+ }
4526+
4527+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4528+ if (unlikely(err))
4529+ /* do not goto err, to keep the errno */
4530+ break;
4531+
4532+ /* todo: plink too? */
4533+ if (!do_udba)
4534+ continue;
4535+
4536+ /* UDBA tests */
4537+ h_inode = h_dentry->d_inode;
4538+ if (unlikely(!!inode != !!h_inode))
4539+ goto err;
4540+
4541+ h_plus = plus;
4542+ h_mode = mode;
4543+ h_cached_inode = h_inode;
4544+ if (h_inode) {
4545+ h_mode = (h_inode->i_mode & S_IFMT);
4546+ h_plus = (h_inode->i_nlink > 0);
4547+ }
4548+ if (inode && ibs <= bindex && bindex <= ibe)
4549+ h_cached_inode = au_h_iptr(inode, bindex);
4550+
4551+ if (unlikely(plus != h_plus
4552+ || mode != h_mode
4553+ || h_cached_inode != h_inode))
4554+ goto err;
4555+ continue;
4556+
4557+ err:
4558+ err = -EINVAL;
4559+ break;
4560+ }
4561+
4562+ return err;
4563+}
4564+
4565+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
4566+{
4567+ int err;
4568+ struct dentry *parent;
4569+ struct inode *inode;
4570+
4571+ inode = dentry->d_inode;
4572+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
4573+ return 0;
4574+
4575+ parent = dget_parent(dentry);
4576+ di_read_lock_parent(parent, AuLock_IR);
4577+ AuDebugOn(au_digen(parent) != sigen
4578+ || au_iigen(parent->d_inode) != sigen);
4579+ au_dbg_verify_gen(parent, sigen);
4580+
4581+ /* returns a number of positive dentries */
4582+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
4583+ if (err >= 0)
4584+ err = au_refresh_hinode(inode, dentry);
4585+
4586+ di_read_unlock(parent, AuLock_IR);
4587+ dput(parent);
4588+ return err;
4589+}
4590+
4591+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
4592+{
4593+ int err;
4594+ struct dentry *d, *parent;
4595+ struct inode *inode;
4596+
4597+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
4598+ return simple_reval_dpath(dentry, sigen);
4599+
4600+ /* slow loop, keep it simple and stupid */
4601+ /* cf: au_cpup_dirs() */
4602+ err = 0;
4603+ parent = NULL;
4604+ while (au_digen(dentry) != sigen
4605+ || au_iigen(dentry->d_inode) != sigen) {
4606+ d = dentry;
4607+ while (1) {
4608+ dput(parent);
4609+ parent = dget_parent(d);
4610+ if (au_digen(parent) == sigen
4611+ && au_iigen(parent->d_inode) == sigen)
4612+ break;
4613+ d = parent;
4614+ }
4615+
4616+ inode = d->d_inode;
4617+ if (d != dentry)
4618+ di_write_lock_child(d);
4619+
4620+ /* someone might update our dentry while we were sleeping */
4621+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
4622+ di_read_lock_parent(parent, AuLock_IR);
4623+ /* returns a number of positive dentries */
4624+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
4625+ if (err >= 0)
4626+ err = au_refresh_hinode(inode, d);
4627+ di_read_unlock(parent, AuLock_IR);
4628+ }
4629+
4630+ if (d != dentry)
4631+ di_write_unlock(d);
4632+ dput(parent);
4633+ if (unlikely(err))
4634+ break;
4635+ }
4636+
4637+ return err;
4638+}
4639+
4640+/*
4641+ * if valid returns 1, otherwise 0.
4642+ */
4643+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
4644+{
4645+ int valid, err;
4646+ unsigned int sigen;
4647+ unsigned char do_udba;
4648+ struct super_block *sb;
4649+ struct inode *inode;
4650+
4651+ err = -EINVAL;
4652+ sb = dentry->d_sb;
4653+ inode = dentry->d_inode;
4654+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
4655+ sigen = au_sigen(sb);
4656+ if (au_digen(dentry) != sigen) {
4657+ AuDebugOn(IS_ROOT(dentry));
4658+ if (inode)
4659+ err = au_reval_dpath(dentry, sigen);
4660+ if (unlikely(err))
4661+ goto out_dgrade;
4662+ AuDebugOn(au_digen(dentry) != sigen);
4663+ }
4664+ if (inode && au_iigen(inode) != sigen) {
4665+ AuDebugOn(IS_ROOT(dentry));
4666+ err = au_refresh_hinode(inode, dentry);
4667+ if (unlikely(err))
4668+ goto out_dgrade;
4669+ AuDebugOn(au_iigen(inode) != sigen);
4670+ }
4671+ di_downgrade_lock(dentry, AuLock_IR);
4672+
4673+ AuDebugOn(au_digen(dentry) != sigen);
4674+ AuDebugOn(inode && au_iigen(inode) != sigen);
4675+ err = -EINVAL;
4676+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
4677+ if (do_udba && inode) {
4678+ aufs_bindex_t bstart = au_ibstart(inode);
4679+
4680+ if (bstart >= 0
4681+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
4682+ goto out;
4683+ }
4684+
4685+ err = h_d_revalidate(dentry, inode, nd, do_udba);
4686+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
4687+ /* both of real entry and whiteout found */
4688+ err = -EIO;
4689+ goto out;
4690+
4691+ out_dgrade:
4692+ di_downgrade_lock(dentry, AuLock_IR);
4693+ out:
4694+ au_store_oflag(nd, inode);
4695+ aufs_read_unlock(dentry, AuLock_IR);
4696+ AuTraceErr(err);
4697+ valid = !err;
4698+ if (!valid)
4699+ AuDbg("%.*s invalid\n", AuDLNPair(dentry));
4700+ return valid;
4701+}
4702+
4703+static void aufs_d_release(struct dentry *dentry)
4704+{
4705+ struct au_dinfo *dinfo;
4706+ aufs_bindex_t bend, bindex;
4707+
4708+ dinfo = dentry->d_fsdata;
4709+ if (!dinfo)
4710+ return;
4711+
4712+ /* dentry may not be revalidated */
4713+ bindex = dinfo->di_bstart;
4714+ if (bindex >= 0) {
4715+ struct au_hdentry *p;
4716+
4717+ bend = dinfo->di_bend;
4718+ p = dinfo->di_hdentry + bindex;
4719+ while (bindex++ <= bend) {
4720+ if (p->hd_dentry)
4721+ au_hdput(p);
4722+ p++;
4723+ }
4724+ }
4725+ kfree(dinfo->di_hdentry);
dece6358 4726+ AuRwDestroy(&dinfo->di_rwsem);
1facf9fc 4727+ au_cache_free_dinfo(dinfo);
4728+ au_hin_di_reinit(dentry);
4729+}
4730+
4731+struct dentry_operations aufs_dop = {
4732+ .d_revalidate = aufs_d_revalidate,
4733+ .d_release = aufs_d_release
4734+};
dece6358
AM
4735diff -urN linux-2.6.30.org/fs/aufs/dentry.h linux-2.6.30/fs/aufs/dentry.h
4736--- linux-2.6.30.org/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
4737+++ linux-2.6.30/fs/aufs/dentry.h 2009-07-21 08:54:19.000000000 +0200
4738@@ -0,0 +1,223 @@
1facf9fc 4739+/*
4740+ * Copyright (C) 2005-2009 Junjiro R. Okajima
4741+ *
4742+ * This program, aufs is free software; you can redistribute it and/or modify
4743+ * it under the terms of the GNU General Public License as published by
4744+ * the Free Software Foundation; either version 2 of the License, or
4745+ * (at your option) any later version.
dece6358
AM
4746+ *
4747+ * This program is distributed in the hope that it will be useful,
4748+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4749+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4750+ * GNU General Public License for more details.
4751+ *
4752+ * You should have received a copy of the GNU General Public License
4753+ * along with this program; if not, write to the Free Software
4754+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4755+ */
4756+
4757+/*
4758+ * lookup and dentry operations
4759+ */
4760+
4761+#ifndef __AUFS_DENTRY_H__
4762+#define __AUFS_DENTRY_H__
4763+
4764+#ifdef __KERNEL__
4765+
dece6358 4766+#include <linux/dcache.h>
1facf9fc 4767+#include <linux/aufs_type.h>
4768+#include "rwsem.h"
4769+
4770+/* make a single member structure for future use */
4771+/* todo: remove this structure */
4772+struct au_hdentry {
4773+ struct dentry *hd_dentry;
4774+};
4775+
4776+struct au_dinfo {
4777+ atomic_t di_generation;
4778+
dece6358 4779+ struct au_rwsem di_rwsem;
1facf9fc 4780+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
4781+ struct au_hdentry *di_hdentry;
4782+};
4783+
4784+/* ---------------------------------------------------------------------- */
4785+
4786+/* dentry.c */
4787+extern struct dentry_operations aufs_dop;
4788+struct au_branch;
4789+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4790+ struct au_branch *br, struct nameidata *nd);
4791+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4792+ struct au_branch *br);
4793+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4794+ struct dentry *h_parent, struct au_branch *br);
4795+
4796+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4797+ struct nameidata *nd);
4798+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
4799+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
4800+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
4801+
4802+/* dinfo.c */
4803+int au_alloc_dinfo(struct dentry *dentry);
4804+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
4805+
4806+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
4807+void di_read_unlock(struct dentry *d, int flags);
4808+void di_downgrade_lock(struct dentry *d, int flags);
4809+void di_write_lock(struct dentry *d, unsigned int lsc);
4810+void di_write_unlock(struct dentry *d);
4811+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
4812+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
4813+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
4814+
4815+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
4816+aufs_bindex_t au_dbtail(struct dentry *dentry);
4817+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
4818+
4819+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
4820+ struct dentry *h_dentry);
4821+void au_update_digen(struct dentry *dentry);
4822+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
4823+void au_update_dbstart(struct dentry *dentry);
4824+void au_update_dbend(struct dentry *dentry);
4825+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
4826+
4827+/* ---------------------------------------------------------------------- */
4828+
4829+static inline struct au_dinfo *au_di(struct dentry *dentry)
4830+{
4831+ return dentry->d_fsdata;
4832+}
4833+
4834+/* ---------------------------------------------------------------------- */
4835+
4836+/* lock subclass for dinfo */
4837+enum {
4838+ AuLsc_DI_CHILD, /* child first */
4839+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
4840+ AuLsc_DI_CHILD3, /* copyup dirs */
4841+ AuLsc_DI_PARENT,
4842+ AuLsc_DI_PARENT2,
4843+ AuLsc_DI_PARENT3
4844+};
4845+
4846+/*
4847+ * di_read_lock_child, di_write_lock_child,
4848+ * di_read_lock_child2, di_write_lock_child2,
4849+ * di_read_lock_child3, di_write_lock_child3,
4850+ * di_read_lock_parent, di_write_lock_parent,
4851+ * di_read_lock_parent2, di_write_lock_parent2,
4852+ * di_read_lock_parent3, di_write_lock_parent3,
4853+ */
4854+#define AuReadLockFunc(name, lsc) \
4855+static inline void di_read_lock_##name(struct dentry *d, int flags) \
4856+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
4857+
4858+#define AuWriteLockFunc(name, lsc) \
4859+static inline void di_write_lock_##name(struct dentry *d) \
4860+{ di_write_lock(d, AuLsc_DI_##lsc); }
4861+
4862+#define AuRWLockFuncs(name, lsc) \
4863+ AuReadLockFunc(name, lsc) \
4864+ AuWriteLockFunc(name, lsc)
4865+
4866+AuRWLockFuncs(child, CHILD);
4867+AuRWLockFuncs(child2, CHILD2);
4868+AuRWLockFuncs(child3, CHILD3);
4869+AuRWLockFuncs(parent, PARENT);
4870+AuRWLockFuncs(parent2, PARENT2);
4871+AuRWLockFuncs(parent3, PARENT3);
4872+
4873+#undef AuReadLockFunc
4874+#undef AuWriteLockFunc
4875+#undef AuRWLockFuncs
4876+
4877+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
4878+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
4879+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 4880+
4881+/* ---------------------------------------------------------------------- */
4882+
4883+/* todo: memory barrier? */
4884+static inline unsigned int au_digen(struct dentry *d)
4885+{
4886+ return atomic_read(&au_di(d)->di_generation);
4887+}
4888+
4889+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
4890+{
4891+ hdentry->hd_dentry = NULL;
4892+}
4893+
4894+static inline void au_hdput(struct au_hdentry *hd)
4895+{
4896+ dput(hd->hd_dentry);
4897+}
4898+
4899+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
4900+{
4901+ return au_di(dentry)->di_bstart;
4902+}
4903+
4904+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
4905+{
4906+ return au_di(dentry)->di_bend;
4907+}
4908+
4909+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
4910+{
4911+ return au_di(dentry)->di_bwh;
4912+}
4913+
4914+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
4915+{
4916+ return au_di(dentry)->di_bdiropq;
4917+}
4918+
4919+/* todo: hard/soft set? */
4920+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
4921+{
4922+ au_di(dentry)->di_bstart = bindex;
4923+}
4924+
4925+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
4926+{
4927+ au_di(dentry)->di_bend = bindex;
4928+}
4929+
4930+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
4931+{
4932+ /* dbwh can be outside of bstart - bend range */
4933+ au_di(dentry)->di_bwh = bindex;
4934+}
4935+
4936+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
4937+{
4938+ au_di(dentry)->di_bdiropq = bindex;
4939+}
4940+
4941+/* ---------------------------------------------------------------------- */
4942+
4943+#ifdef CONFIG_AUFS_HINOTIFY
4944+static inline void au_digen_dec(struct dentry *d)
4945+{
dece6358 4946+ atomic_dec_return(&au_di(d)->di_generation);
1facf9fc 4947+}
4948+
4949+static inline void au_hin_di_reinit(struct dentry *dentry)
4950+{
4951+ dentry->d_fsdata = NULL;
4952+}
4953+#else
4954+static inline void au_hin_di_reinit(struct dentry *dentry __maybe_unused)
4955+{
4956+ /* empty */
4957+}
4958+#endif /* CONFIG_AUFS_HINOTIFY */
4959+
4960+#endif /* __KERNEL__ */
4961+#endif /* __AUFS_DENTRY_H__ */
dece6358
AM
4962diff -urN linux-2.6.30.org/fs/aufs/dinfo.c linux-2.6.30/fs/aufs/dinfo.c
4963--- linux-2.6.30.org/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
4964+++ linux-2.6.30/fs/aufs/dinfo.c 2009-07-21 08:54:19.000000000 +0200
4965@@ -0,0 +1,359 @@
1facf9fc 4966+/*
4967+ * Copyright (C) 2005-2009 Junjiro R. Okajima
4968+ *
4969+ * This program, aufs is free software; you can redistribute it and/or modify
4970+ * it under the terms of the GNU General Public License as published by
4971+ * the Free Software Foundation; either version 2 of the License, or
4972+ * (at your option) any later version.
dece6358
AM
4973+ *
4974+ * This program is distributed in the hope that it will be useful,
4975+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4976+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4977+ * GNU General Public License for more details.
4978+ *
4979+ * You should have received a copy of the GNU General Public License
4980+ * along with this program; if not, write to the Free Software
4981+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4982+ */
4983+
4984+/*
4985+ * dentry private data
4986+ */
4987+
4988+#include "aufs.h"
4989+
4990+int au_alloc_dinfo(struct dentry *dentry)
4991+{
4992+ struct au_dinfo *dinfo;
4993+ struct super_block *sb;
4994+ int nbr;
4995+
4996+ dinfo = au_cache_alloc_dinfo();
4997+ if (unlikely(!dinfo))
4998+ goto out;
4999+
5000+ sb = dentry->d_sb;
5001+ nbr = au_sbend(sb) + 1;
5002+ if (nbr <= 0)
5003+ nbr = 1;
5004+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5005+ if (unlikely(!dinfo->di_hdentry))
5006+ goto out_dinfo;
5007+
5008+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5009+ /* smp_mb(); */ /* atomic_set */
dece6358 5010+ au_rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5011+ dinfo->di_bstart = -1;
5012+ dinfo->di_bend = -1;
5013+ dinfo->di_bwh = -1;
5014+ dinfo->di_bdiropq = -1;
5015+
5016+ dentry->d_fsdata = dinfo;
5017+ dentry->d_op = &aufs_dop;
5018+ return 0; /* success */
5019+
5020+ out_dinfo:
5021+ au_cache_free_dinfo(dinfo);
5022+ out:
5023+ return -ENOMEM;
5024+}
5025+
5026+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5027+{
5028+ int err, sz;
5029+ struct au_hdentry *hdp;
5030+
5031+ err = -ENOMEM;
5032+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5033+ if (!sz)
5034+ sz = sizeof(*hdp);
5035+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5036+ if (hdp) {
5037+ dinfo->di_hdentry = hdp;
5038+ err = 0;
5039+ }
5040+
5041+ return err;
5042+}
5043+
5044+/* ---------------------------------------------------------------------- */
5045+
5046+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5047+{
5048+ switch (lsc) {
5049+ case AuLsc_DI_CHILD:
5050+ ii_write_lock_child(inode);
5051+ break;
5052+ case AuLsc_DI_CHILD2:
5053+ ii_write_lock_child2(inode);
5054+ break;
5055+ case AuLsc_DI_CHILD3:
5056+ ii_write_lock_child3(inode);
5057+ break;
5058+ case AuLsc_DI_PARENT:
5059+ ii_write_lock_parent(inode);
5060+ break;
5061+ case AuLsc_DI_PARENT2:
5062+ ii_write_lock_parent2(inode);
5063+ break;
5064+ case AuLsc_DI_PARENT3:
5065+ ii_write_lock_parent3(inode);
5066+ break;
5067+ default:
5068+ BUG();
5069+ }
5070+}
5071+
5072+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5073+{
5074+ switch (lsc) {
5075+ case AuLsc_DI_CHILD:
5076+ ii_read_lock_child(inode);
5077+ break;
5078+ case AuLsc_DI_CHILD2:
5079+ ii_read_lock_child2(inode);
5080+ break;
5081+ case AuLsc_DI_CHILD3:
5082+ ii_read_lock_child3(inode);
5083+ break;
5084+ case AuLsc_DI_PARENT:
5085+ ii_read_lock_parent(inode);
5086+ break;
5087+ case AuLsc_DI_PARENT2:
5088+ ii_read_lock_parent2(inode);
5089+ break;
5090+ case AuLsc_DI_PARENT3:
5091+ ii_read_lock_parent3(inode);
5092+ break;
5093+ default:
5094+ BUG();
5095+ }
5096+}
5097+
5098+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5099+{
dece6358 5100+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5101+ if (d->d_inode) {
5102+ if (au_ftest_lock(flags, IW))
5103+ do_ii_write_lock(d->d_inode, lsc);
5104+ else if (au_ftest_lock(flags, IR))
5105+ do_ii_read_lock(d->d_inode, lsc);
5106+ }
5107+}
5108+
5109+void di_read_unlock(struct dentry *d, int flags)
5110+{
5111+ if (d->d_inode) {
5112+ if (au_ftest_lock(flags, IW))
5113+ ii_write_unlock(d->d_inode);
5114+ else if (au_ftest_lock(flags, IR))
5115+ ii_read_unlock(d->d_inode);
5116+ }
dece6358 5117+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5118+}
5119+
5120+void di_downgrade_lock(struct dentry *d, int flags)
5121+{
1facf9fc 5122+ if (d->d_inode && au_ftest_lock(flags, IR))
5123+ ii_downgrade_lock(d->d_inode);
dece6358 5124+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5125+}
5126+
5127+void di_write_lock(struct dentry *d, unsigned int lsc)
5128+{
dece6358 5129+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5130+ if (d->d_inode)
5131+ do_ii_write_lock(d->d_inode, lsc);
5132+}
5133+
5134+void di_write_unlock(struct dentry *d)
5135+{
5136+ if (d->d_inode)
5137+ ii_write_unlock(d->d_inode);
dece6358 5138+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5139+}
5140+
5141+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5142+{
5143+ AuDebugOn(d1 == d2
5144+ || d1->d_inode == d2->d_inode
5145+ || d1->d_sb != d2->d_sb);
5146+
5147+ if (isdir && au_test_subdir(d1, d2)) {
5148+ di_write_lock_child(d1);
5149+ di_write_lock_child2(d2);
5150+ } else {
5151+ /* there should be no races */
5152+ di_write_lock_child(d2);
5153+ di_write_lock_child2(d1);
5154+ }
5155+}
5156+
5157+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5158+{
5159+ AuDebugOn(d1 == d2
5160+ || d1->d_inode == d2->d_inode
5161+ || d1->d_sb != d2->d_sb);
5162+
5163+ if (isdir && au_test_subdir(d1, d2)) {
5164+ di_write_lock_parent(d1);
5165+ di_write_lock_parent2(d2);
5166+ } else {
5167+ /* there should be no races */
5168+ di_write_lock_parent(d2);
5169+ di_write_lock_parent2(d1);
5170+ }
5171+}
5172+
5173+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5174+{
5175+ di_write_unlock(d1);
5176+ if (d1->d_inode == d2->d_inode)
dece6358 5177+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5178+ else
5179+ di_write_unlock(d2);
5180+}
5181+
5182+/* ---------------------------------------------------------------------- */
5183+
5184+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5185+{
5186+ struct dentry *d;
5187+
5188+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5189+ return NULL;
5190+ AuDebugOn(bindex < 0);
5191+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5192+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5193+ return d;
5194+}
5195+
5196+aufs_bindex_t au_dbtail(struct dentry *dentry)
5197+{
5198+ aufs_bindex_t bend, bwh;
5199+
5200+ bend = au_dbend(dentry);
5201+ if (0 <= bend) {
5202+ bwh = au_dbwh(dentry);
5203+ if (!bwh)
5204+ return bwh;
5205+ if (0 < bwh && bwh < bend)
5206+ return bwh - 1;
5207+ }
5208+ return bend;
5209+}
5210+
5211+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5212+{
5213+ aufs_bindex_t bend, bopq;
5214+
5215+ bend = au_dbtail(dentry);
5216+ if (0 <= bend) {
5217+ bopq = au_dbdiropq(dentry);
5218+ if (0 <= bopq && bopq < bend)
5219+ bend = bopq;
5220+ }
5221+ return bend;
5222+}
5223+
5224+/* ---------------------------------------------------------------------- */
5225+
5226+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5227+ struct dentry *h_dentry)
5228+{
5229+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5230+
5231+ if (hd->hd_dentry)
5232+ au_hdput(hd);
5233+ hd->hd_dentry = h_dentry;
5234+}
5235+
5236+void au_update_digen(struct dentry *dentry)
5237+{
5238+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5239+ /* smp_mb(); */ /* atomic_set */
5240+}
5241+
5242+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5243+{
5244+ struct au_dinfo *dinfo;
5245+ struct dentry *h_d;
5246+
5247+ dinfo = au_di(dentry);
5248+ if (!dinfo || dinfo->di_bstart < 0)
5249+ return;
5250+
5251+ if (do_put_zero) {
5252+ aufs_bindex_t bindex, bend;
5253+
5254+ bend = dinfo->di_bend;
5255+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
5256+ h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
5257+ if (h_d && !h_d->d_inode)
5258+ au_set_h_dptr(dentry, bindex, NULL);
5259+ }
5260+ }
5261+
5262+ dinfo->di_bstart = -1;
5263+ while (++dinfo->di_bstart <= dinfo->di_bend)
5264+ if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
5265+ break;
5266+ if (dinfo->di_bstart > dinfo->di_bend) {
5267+ dinfo->di_bstart = -1;
5268+ dinfo->di_bend = -1;
5269+ return;
5270+ }
5271+
5272+ dinfo->di_bend++;
5273+ while (0 <= --dinfo->di_bend)
5274+ if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
5275+ break;
5276+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5277+}
5278+
5279+void au_update_dbstart(struct dentry *dentry)
5280+{
5281+ aufs_bindex_t bindex, bend;
5282+ struct dentry *h_dentry;
5283+
5284+ bend = au_dbend(dentry);
5285+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5286+ h_dentry = au_h_dptr(dentry, bindex);
5287+ if (!h_dentry)
5288+ continue;
5289+ if (h_dentry->d_inode) {
5290+ au_set_dbstart(dentry, bindex);
5291+ return;
5292+ }
5293+ au_set_h_dptr(dentry, bindex, NULL);
5294+ }
5295+}
5296+
5297+void au_update_dbend(struct dentry *dentry)
5298+{
5299+ aufs_bindex_t bindex, bstart;
5300+ struct dentry *h_dentry;
5301+
5302+ bstart = au_dbstart(dentry);
5303+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5304+ h_dentry = au_h_dptr(dentry, bindex);
5305+ if (!h_dentry)
5306+ continue;
5307+ if (h_dentry->d_inode) {
5308+ au_set_dbend(dentry, bindex);
5309+ return;
5310+ }
5311+ au_set_h_dptr(dentry, bindex, NULL);
5312+ }
5313+}
5314+
5315+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5316+{
5317+ aufs_bindex_t bindex, bend;
5318+
5319+ bend = au_dbend(dentry);
5320+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5321+ if (au_h_dptr(dentry, bindex) == h_dentry)
5322+ return bindex;
5323+ return -1;
5324+}
dece6358
AM
5325diff -urN linux-2.6.30.org/fs/aufs/dir.c linux-2.6.30/fs/aufs/dir.c
5326--- linux-2.6.30.org/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
5327+++ linux-2.6.30/fs/aufs/dir.c 2009-07-21 08:54:19.000000000 +0200
5328@@ -0,0 +1,535 @@
1facf9fc 5329+/*
5330+ * Copyright (C) 2005-2009 Junjiro R. Okajima
5331+ *
5332+ * This program, aufs is free software; you can redistribute it and/or modify
5333+ * it under the terms of the GNU General Public License as published by
5334+ * the Free Software Foundation; either version 2 of the License, or
5335+ * (at your option) any later version.
dece6358
AM
5336+ *
5337+ * This program is distributed in the hope that it will be useful,
5338+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5339+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5340+ * GNU General Public License for more details.
5341+ *
5342+ * You should have received a copy of the GNU General Public License
5343+ * along with this program; if not, write to the Free Software
5344+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5345+ */
5346+
5347+/*
5348+ * directory operations
5349+ */
5350+
dece6358 5351+#include <linux/file.h>
1facf9fc 5352+#include <linux/fs_stack.h>
5353+#include "aufs.h"
5354+
5355+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5356+{
5357+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5358+
5359+ dir->i_nlink += h_dir->i_nlink - 2;
5360+ if (h_dir->i_nlink < 2)
5361+ dir->i_nlink += 2;
5362+}
5363+
5364+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5365+{
5366+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5367+
5368+ dir->i_nlink -= h_dir->i_nlink - 2;
5369+ if (h_dir->i_nlink < 2)
5370+ dir->i_nlink -= 2;
5371+}
5372+
5373+/* ---------------------------------------------------------------------- */
5374+
5375+static int reopen_dir(struct file *file)
5376+{
5377+ int err;
5378+ unsigned int flags;
5379+ aufs_bindex_t bindex, btail, bstart;
5380+ struct dentry *dentry, *h_dentry;
5381+ struct file *h_file;
5382+
5383+ /* open all lower dirs */
5384+ dentry = file->f_dentry;
5385+ bstart = au_dbstart(dentry);
5386+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5387+ au_set_h_fptr(file, bindex, NULL);
5388+ au_set_fbstart(file, bstart);
5389+
5390+ btail = au_dbtaildir(dentry);
5391+ for (bindex = au_fbend(file); btail < bindex; bindex--)
5392+ au_set_h_fptr(file, bindex, NULL);
5393+ au_set_fbend(file, btail);
5394+
5395+ flags = file->f_flags;
5396+ for (bindex = bstart; bindex <= btail; bindex++) {
5397+ h_dentry = au_h_dptr(dentry, bindex);
5398+ if (!h_dentry)
5399+ continue;
5400+ h_file = au_h_fptr(file, bindex);
5401+ if (h_file)
5402+ continue;
5403+
5404+ h_file = au_h_open(dentry, bindex, flags, file);
5405+ err = PTR_ERR(h_file);
5406+ if (IS_ERR(h_file))
5407+ goto out; /* close all? */
5408+ au_set_h_fptr(file, bindex, h_file);
5409+ }
5410+ au_update_figen(file);
5411+ /* todo: necessary? */
5412+ /* file->f_ra = h_file->f_ra; */
5413+ err = 0;
5414+
5415+ out:
5416+ return err;
5417+}
5418+
5419+static int do_open_dir(struct file *file, int flags)
5420+{
5421+ int err;
5422+ aufs_bindex_t bindex, btail;
5423+ struct dentry *dentry, *h_dentry;
5424+ struct file *h_file;
5425+
5426+ err = 0;
5427+ dentry = file->f_dentry;
5428+ au_set_fvdir_cache(file, NULL);
5429+ au_fi(file)->fi_maintain_plink = 0;
5430+ file->f_version = dentry->d_inode->i_version;
5431+ bindex = au_dbstart(dentry);
5432+ au_set_fbstart(file, bindex);
5433+ btail = au_dbtaildir(dentry);
5434+ au_set_fbend(file, btail);
5435+ for (; !err && bindex <= btail; bindex++) {
5436+ h_dentry = au_h_dptr(dentry, bindex);
5437+ if (!h_dentry)
5438+ continue;
5439+
5440+ h_file = au_h_open(dentry, bindex, flags, file);
5441+ if (IS_ERR(h_file)) {
5442+ err = PTR_ERR(h_file);
5443+ break;
5444+ }
5445+ au_set_h_fptr(file, bindex, h_file);
5446+ }
5447+ au_update_figen(file);
5448+ /* todo: necessary? */
5449+ /* file->f_ra = h_file->f_ra; */
5450+ if (!err)
5451+ return 0; /* success */
5452+
5453+ /* close all */
5454+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5455+ au_set_h_fptr(file, bindex, NULL);
5456+ au_set_fbstart(file, -1);
5457+ au_set_fbend(file, -1);
5458+ return err;
5459+}
5460+
5461+static int aufs_open_dir(struct inode *inode __maybe_unused,
5462+ struct file *file)
5463+{
5464+ return au_do_open(file, do_open_dir);
5465+}
5466+
5467+static int aufs_release_dir(struct inode *inode __maybe_unused,
5468+ struct file *file)
5469+{
5470+ struct au_vdir *vdir_cache;
5471+ struct super_block *sb;
5472+ struct au_sbinfo *sbinfo;
5473+
5474+ sb = file->f_dentry->d_sb;
5475+ si_noflush_read_lock(sb);
5476+ fi_write_lock(file);
5477+ vdir_cache = au_fvdir_cache(file);
5478+ if (vdir_cache)
5479+ au_vdir_free(vdir_cache);
5480+ if (au_fi(file)->fi_maintain_plink) {
5481+ sbinfo = au_sbi(sb);
dece6358
AM
5482+ /* clear the flag without write-lock */
5483+ sbinfo->au_si_status &= ~AuSi_MAINTAIN_PLINK;
1facf9fc 5484+ wake_up_all(&sbinfo->si_plink_wq);
5485+ }
5486+ fi_write_unlock(file);
5487+ au_finfo_fin(file);
5488+ si_read_unlock(sb);
5489+ return 0;
5490+}
5491+
5492+/* ---------------------------------------------------------------------- */
5493+
5494+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
5495+{
5496+ int err;
5497+ aufs_bindex_t bend, bindex;
5498+ struct inode *inode;
5499+ struct super_block *sb;
5500+
5501+ err = 0;
5502+ sb = dentry->d_sb;
5503+ inode = dentry->d_inode;
5504+ IMustLock(inode);
5505+ bend = au_dbend(dentry);
5506+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
5507+ struct path h_path;
5508+ struct inode *h_inode;
5509+
5510+ if (au_test_ro(sb, bindex, inode))
5511+ continue;
5512+ h_path.dentry = au_h_dptr(dentry, bindex);
5513+ if (!h_path.dentry)
5514+ continue;
5515+ h_inode = h_path.dentry->d_inode;
5516+ if (!h_inode)
5517+ continue;
5518+
5519+ /* no mnt_want_write() */
5520+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
5521+ /* todo: inotiry fired? */
5522+ h_path.mnt = au_sbr_mnt(sb, bindex);
5523+ mutex_lock(&h_inode->i_mutex);
5524+ err = filemap_fdatawrite(h_inode->i_mapping);
5525+ AuDebugOn(!h_inode->i_fop);
5526+ if (!err && h_inode->i_fop->fsync)
5527+ err = h_inode->i_fop->fsync(NULL, h_path.dentry,
5528+ datasync);
5529+ if (!err)
5530+ err = filemap_fdatawrite(h_inode->i_mapping);
5531+ if (!err)
5532+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
5533+ mutex_unlock(&h_inode->i_mutex);
5534+ }
5535+
5536+ return err;
5537+}
5538+
5539+static int au_do_fsync_dir(struct file *file, int datasync)
5540+{
5541+ int err;
5542+ aufs_bindex_t bend, bindex;
5543+ struct file *h_file;
5544+ struct super_block *sb;
5545+ struct inode *inode;
5546+ struct mutex *h_mtx;
5547+
5548+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
5549+ if (unlikely(err))
5550+ goto out;
5551+
5552+ sb = file->f_dentry->d_sb;
5553+ inode = file->f_dentry->d_inode;
5554+ bend = au_fbend(file);
5555+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
5556+ h_file = au_h_fptr(file, bindex);
5557+ if (!h_file || au_test_ro(sb, bindex, inode))
5558+ continue;
5559+
5560+ err = vfs_fsync(h_file, h_file->f_dentry, datasync);
5561+ if (!err) {
5562+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
5563+ mutex_lock(h_mtx);
5564+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
5565+ /*ignore*/
5566+ mutex_unlock(h_mtx);
5567+ }
5568+ }
5569+
5570+ out:
5571+ return err;
5572+}
5573+
5574+/*
5575+ * @file may be NULL
5576+ */
5577+static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
5578+ int datasync)
5579+{
5580+ int err;
5581+ struct super_block *sb;
5582+
5583+ IMustLock(dentry->d_inode);
5584+
5585+ err = 0;
5586+ sb = dentry->d_sb;
5587+ si_noflush_read_lock(sb);
5588+ if (file)
5589+ err = au_do_fsync_dir(file, datasync);
5590+ else {
5591+ di_write_lock_child(dentry);
5592+ err = au_do_fsync_dir_no_file(dentry, datasync);
5593+ }
5594+ au_cpup_attr_timesizes(dentry->d_inode);
5595+ di_write_unlock(dentry);
5596+ if (file)
5597+ fi_write_unlock(file);
5598+
5599+ si_read_unlock(sb);
5600+ return err;
5601+}
5602+
5603+/* ---------------------------------------------------------------------- */
5604+
5605+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
5606+{
5607+ int err;
5608+ struct dentry *dentry;
5609+ struct inode *inode;
5610+ struct super_block *sb;
5611+
5612+ dentry = file->f_dentry;
5613+ inode = dentry->d_inode;
5614+ IMustLock(inode);
5615+
5616+ sb = dentry->d_sb;
5617+ si_read_lock(sb, AuLock_FLUSH);
5618+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
5619+ if (unlikely(err))
5620+ goto out;
5621+ err = au_vdir_init(file);
5622+ di_downgrade_lock(dentry, AuLock_IR);
5623+ if (unlikely(err))
5624+ goto out_unlock;
5625+
5626+ if (!au_test_nfsd(current)) {
5627+ err = au_vdir_fill_de(file, dirent, filldir);
5628+ fsstack_copy_attr_atime(inode,
5629+ au_h_iptr(inode, au_ibstart(inode)));
5630+ } else {
5631+ /*
5632+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
5633+ * encode_fh() and others.
5634+ */
5635+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
5636+
5637+ di_read_unlock(dentry, AuLock_IR);
5638+ si_read_unlock(sb);
5639+ lockdep_off();
5640+ err = au_vdir_fill_de(file, dirent, filldir);
5641+ lockdep_on();
5642+ fsstack_copy_attr_atime(inode, h_inode);
5643+ fi_write_unlock(file);
5644+
5645+ AuTraceErr(err);
5646+ return err;
5647+ }
5648+
5649+ out_unlock:
5650+ di_read_unlock(dentry, AuLock_IR);
5651+ fi_write_unlock(file);
5652+ out:
5653+ si_read_unlock(sb);
5654+ return err;
5655+}
5656+
5657+/* ---------------------------------------------------------------------- */
5658+
5659+#define AuTestEmpty_WHONLY 1
dece6358
AM
5660+#define AuTestEmpty_CALLED (1 << 1)
5661+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 5662+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
5663+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
5664+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
5665+
dece6358
AM
5666+#ifndef CONFIG_AUFS_SHWH
5667+#undef AuTestEmpty_SHWH
5668+#define AuTestEmpty_SHWH 0
5669+#endif
5670+
1facf9fc 5671+struct test_empty_arg {
dece6358 5672+ struct au_nhash whlist;
1facf9fc 5673+ unsigned int flags;
5674+ int err;
5675+ aufs_bindex_t bindex;
5676+};
5677+
5678+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
5679+ loff_t offset __maybe_unused, u64 ino,
5680+ unsigned int d_type)
1facf9fc 5681+{
5682+ struct test_empty_arg *arg = __arg;
5683+ char *name = (void *)__name;
5684+
5685+ arg->err = 0;
5686+ au_fset_testempty(arg->flags, CALLED);
5687+ /* smp_mb(); */
5688+ if (name[0] == '.'
5689+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
5690+ goto out; /* success */
5691+
5692+ if (namelen <= AUFS_WH_PFX_LEN
5693+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
5694+ if (au_ftest_testempty(arg->flags, WHONLY)
dece6358 5695+ && !au_nhash_test_known_wh(&arg->whlist, name, namelen))
1facf9fc 5696+ arg->err = -ENOTEMPTY;
5697+ goto out;
5698+ }
5699+
5700+ name += AUFS_WH_PFX_LEN;
5701+ namelen -= AUFS_WH_PFX_LEN;
dece6358 5702+ if (!au_nhash_test_known_wh(&arg->whlist, name, namelen))
1facf9fc 5703+ arg->err = au_nhash_append_wh
dece6358
AM
5704+ (&arg->whlist, name, namelen, ino, d_type, arg->bindex,
5705+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 5706+
5707+ out:
5708+ /* smp_mb(); */
5709+ AuTraceErr(arg->err);
5710+ return arg->err;
5711+}
5712+
5713+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
5714+{
5715+ int err;
5716+ struct file *h_file;
5717+
5718+ h_file = au_h_open(dentry, arg->bindex,
5719+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
5720+ /*file*/NULL);
5721+ err = PTR_ERR(h_file);
5722+ if (IS_ERR(h_file))
5723+ goto out;
5724+
5725+ err = 0;
5726+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
5727+ && !h_file->f_dentry->d_inode->i_nlink)
5728+ goto out_put;
5729+
5730+ do {
5731+ arg->err = 0;
5732+ au_fclr_testempty(arg->flags, CALLED);
5733+ /* smp_mb(); */
5734+ err = vfsub_readdir(h_file, test_empty_cb, arg);
5735+ if (err >= 0)
5736+ err = arg->err;
5737+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
5738+
5739+ out_put:
5740+ fput(h_file);
5741+ au_sbr_put(dentry->d_sb, arg->bindex);
5742+ out:
5743+ return err;
5744+}
5745+
5746+struct do_test_empty_args {
5747+ int *errp;
5748+ struct dentry *dentry;
5749+ struct test_empty_arg *arg;
5750+};
5751+
5752+static void call_do_test_empty(void *args)
5753+{
5754+ struct do_test_empty_args *a = args;
5755+ *a->errp = do_test_empty(a->dentry, a->arg);
5756+}
5757+
5758+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
5759+{
5760+ int err, wkq_err;
5761+ struct dentry *h_dentry;
5762+ struct inode *h_inode;
5763+
5764+ h_dentry = au_h_dptr(dentry, arg->bindex);
5765+ h_inode = h_dentry->d_inode;
5766+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
5767+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
5768+ mutex_unlock(&h_inode->i_mutex);
5769+ if (!err)
5770+ err = do_test_empty(dentry, arg);
5771+ else {
5772+ struct do_test_empty_args args = {
5773+ .errp = &err,
5774+ .dentry = dentry,
5775+ .arg = arg
5776+ };
5777+ unsigned int flags = arg->flags;
5778+
5779+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
5780+ if (unlikely(wkq_err))
5781+ err = wkq_err;
5782+ arg->flags = flags;
5783+ }
5784+
5785+ return err;
5786+}
5787+
5788+int au_test_empty_lower(struct dentry *dentry)
5789+{
5790+ int err;
5791+ aufs_bindex_t bindex, bstart, btail;
5792+ struct test_empty_arg arg;
1facf9fc 5793+
dece6358
AM
5794+ SiMustAnyLock(dentry->d_sb);
5795+
5796+ err = au_nhash_alloc(&arg.whlist, au_sbi(dentry->d_sb)->si_rdhash,
5797+ GFP_NOFS);
5798+ if (unlikely(err))
1facf9fc 5799+ goto out;
5800+
5801+ bstart = au_dbstart(dentry);
1facf9fc 5802+ arg.flags = 0;
dece6358
AM
5803+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
5804+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 5805+ arg.bindex = bstart;
5806+ err = do_test_empty(dentry, &arg);
5807+ if (unlikely(err))
5808+ goto out_whlist;
5809+
5810+ au_fset_testempty(arg.flags, WHONLY);
5811+ btail = au_dbtaildir(dentry);
5812+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
5813+ struct dentry *h_dentry;
5814+
5815+ h_dentry = au_h_dptr(dentry, bindex);
5816+ if (h_dentry && h_dentry->d_inode) {
5817+ arg.bindex = bindex;
5818+ err = do_test_empty(dentry, &arg);
5819+ }
5820+ }
5821+
5822+ out_whlist:
dece6358 5823+ au_nhash_wh_free(&arg.whlist);
1facf9fc 5824+ out:
5825+ return err;
5826+}
5827+
5828+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
5829+{
5830+ int err;
5831+ struct test_empty_arg arg;
5832+ aufs_bindex_t bindex, btail;
5833+
5834+ err = 0;
dece6358 5835+ arg.whlist = *whlist;
1facf9fc 5836+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
5837+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
5838+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 5839+ btail = au_dbtaildir(dentry);
5840+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
5841+ struct dentry *h_dentry;
5842+
5843+ h_dentry = au_h_dptr(dentry, bindex);
5844+ if (h_dentry && h_dentry->d_inode) {
5845+ arg.bindex = bindex;
5846+ err = sio_test_empty(dentry, &arg);
5847+ }
5848+ }
5849+
5850+ return err;
5851+}
5852+
5853+/* ---------------------------------------------------------------------- */
5854+
5855+const struct file_operations aufs_dir_fop = {
5856+ .read = generic_read_dir,
5857+ .readdir = aufs_readdir,
5858+ .unlocked_ioctl = aufs_ioctl_dir,
5859+ .open = aufs_open_dir,
5860+ .release = aufs_release_dir,
5861+ .flush = aufs_flush,
5862+ .fsync = aufs_fsync_dir
5863+};
dece6358
AM
5864diff -urN linux-2.6.30.org/fs/aufs/dir.h linux-2.6.30/fs/aufs/dir.h
5865--- linux-2.6.30.org/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
5866+++ linux-2.6.30/fs/aufs/dir.h 2009-07-21 08:54:19.000000000 +0200
5867@@ -0,0 +1,114 @@
1facf9fc 5868+/*
5869+ * Copyright (C) 2005-2009 Junjiro R. Okajima
5870+ *
5871+ * This program, aufs is free software; you can redistribute it and/or modify
5872+ * it under the terms of the GNU General Public License as published by
5873+ * the Free Software Foundation; either version 2 of the License, or
5874+ * (at your option) any later version.
dece6358
AM
5875+ *
5876+ * This program is distributed in the hope that it will be useful,
5877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5879+ * GNU General Public License for more details.
5880+ *
5881+ * You should have received a copy of the GNU General Public License
5882+ * along with this program; if not, write to the Free Software
5883+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5884+ */
5885+
5886+/*
5887+ * directory operations
5888+ */
5889+
5890+#ifndef __AUFS_DIR_H__
5891+#define __AUFS_DIR_H__
5892+
5893+#ifdef __KERNEL__
5894+
5895+#include <linux/fs.h>
5896+#include <linux/aufs_type.h>
5897+
5898+/* ---------------------------------------------------------------------- */
5899+
5900+/* need to be faster and smaller */
5901+
5902+struct au_nhash {
dece6358
AM
5903+ unsigned int nh_num;
5904+ struct hlist_head *nh_head;
1facf9fc 5905+};
5906+
5907+struct au_vdir_destr {
5908+ unsigned char len;
5909+ unsigned char name[0];
5910+} __packed;
5911+
5912+struct au_vdir_dehstr {
5913+ struct hlist_node hash;
5914+ struct au_vdir_destr *str;
5915+};
5916+
5917+struct au_vdir_de {
5918+ ino_t de_ino;
5919+ unsigned char de_type;
5920+ /* caution: packed */
5921+ struct au_vdir_destr de_str;
5922+} __packed;
5923+
5924+struct au_vdir_wh {
5925+ struct hlist_node wh_hash;
dece6358
AM
5926+#ifdef CONFIG_AUFS_SHWH
5927+ ino_t wh_ino;
1facf9fc 5928+ aufs_bindex_t wh_bindex;
dece6358
AM
5929+ unsigned char wh_type;
5930+#else
5931+ aufs_bindex_t wh_bindex;
5932+#endif
5933+ /* caution: packed */
1facf9fc 5934+ struct au_vdir_destr wh_str;
5935+} __packed;
5936+
5937+union au_vdir_deblk_p {
5938+ unsigned char *deblk;
5939+ struct au_vdir_de *de;
5940+};
5941+
5942+struct au_vdir {
5943+ unsigned char **vd_deblk;
5944+ unsigned long vd_nblk;
1facf9fc 5945+ struct {
5946+ unsigned long ul;
5947+ union au_vdir_deblk_p p;
5948+ } vd_last;
5949+
5950+ unsigned long vd_version;
dece6358 5951+ unsigned int vd_deblk_sz;
1facf9fc 5952+ unsigned long vd_jiffy;
5953+};
5954+
5955+/* ---------------------------------------------------------------------- */
5956+
5957+/* dir.c */
5958+extern const struct file_operations aufs_dir_fop;
5959+void au_add_nlink(struct inode *dir, struct inode *h_dir);
5960+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
5961+int au_test_empty_lower(struct dentry *dentry);
5962+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
5963+
5964+/* vdir.c */
dece6358
AM
5965+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
5966+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 5967+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
5968+ int limit);
dece6358
AM
5969+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
5970+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
5971+ unsigned int d_type, aufs_bindex_t bindex,
5972+ unsigned char shwh);
1facf9fc 5973+void au_vdir_free(struct au_vdir *vdir);
5974+int au_vdir_init(struct file *file);
5975+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
5976+
5977+/* ioctl.c */
5978+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
5979+
5980+#endif /* __KERNEL__ */
5981+#endif /* __AUFS_DIR_H__ */
dece6358
AM
5982diff -urN linux-2.6.30.org/fs/aufs/export.c linux-2.6.30/fs/aufs/export.c
5983--- linux-2.6.30.org/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
5984+++ linux-2.6.30/fs/aufs/export.c 2009-07-21 08:54:19.000000000 +0200
5985@@ -0,0 +1,745 @@
1facf9fc 5986+/*
dece6358 5987+ * Copyright (C) 2005-2009 Junjiro R. Okajima
1facf9fc 5988+ *
5989+ * This program, aufs is free software; you can redistribute it and/or modify
5990+ * it under the terms of the GNU General Public License as published by
5991+ * the Free Software Foundation; either version 2 of the License, or
5992+ * (at your option) any later version.
dece6358
AM
5993+ *
5994+ * This program is distributed in the hope that it will be useful,
5995+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5996+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5997+ * GNU General Public License for more details.
5998+ *
5999+ * You should have received a copy of the GNU General Public License
6000+ * along with this program; if not, write to the Free Software
6001+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6002+ */
6003+
6004+/*
6005+ * export via nfs
6006+ */
6007+
6008+#include <linux/exportfs.h>
dece6358 6009+#include <linux/file.h>
1facf9fc 6010+#include <linux/mnt_namespace.h>
dece6358 6011+#include <linux/namei.h>
1facf9fc 6012+#include <linux/random.h>
6013+#include "aufs.h"
6014+
6015+union conv {
6016+#ifdef CONFIG_AUFS_INO_T_64
6017+ __u32 a[2];
6018+#else
6019+ __u32 a[1];
6020+#endif
6021+ ino_t ino;
6022+};
6023+
6024+static ino_t decode_ino(__u32 *a)
6025+{
6026+ union conv u;
6027+
6028+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
6029+ u.a[0] = a[0];
6030+#ifdef CONFIG_AUFS_INO_T_64
6031+ u.a[1] = a[1];
6032+#endif
6033+ return u.ino;
6034+}
6035+
6036+static void encode_ino(__u32 *a, ino_t ino)
6037+{
6038+ union conv u;
6039+
6040+ u.ino = ino;
6041+ a[0] = u.a[0];
6042+#ifdef CONFIG_AUFS_INO_T_64
6043+ a[1] = u.a[1];
6044+#endif
6045+}
6046+
6047+/* NFS file handle */
6048+enum {
6049+ Fh_br_id,
6050+ Fh_sigen,
6051+#ifdef CONFIG_AUFS_INO_T_64
6052+ /* support 64bit inode number */
6053+ Fh_ino1,
6054+ Fh_ino2,
6055+ Fh_dir_ino1,
6056+ Fh_dir_ino2,
6057+#else
6058+ Fh_ino1,
6059+ Fh_dir_ino1,
6060+#endif
6061+ Fh_igen,
6062+ Fh_h_type,
6063+ Fh_tail,
6064+
6065+ Fh_ino = Fh_ino1,
6066+ Fh_dir_ino = Fh_dir_ino1
6067+};
6068+
6069+static int au_test_anon(struct dentry *dentry)
6070+{
6071+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
6072+}
6073+
6074+/* ---------------------------------------------------------------------- */
6075+/* inode generation external table */
6076+
6077+int au_xigen_inc(struct inode *inode)
6078+{
6079+ int err;
6080+ loff_t pos;
6081+ ssize_t sz;
6082+ __u32 igen;
6083+ struct super_block *sb;
6084+ struct au_sbinfo *sbinfo;
6085+
6086+ err = 0;
6087+ sb = inode->i_sb;
dece6358
AM
6088+ sbinfo = au_sbi(sb);
6089+ /*
6090+ * temporary workaround for escaping from SiMustAnyLock() in
6091+ * au_mntflags(), since this function is called from au_iinfo_fin().
6092+ */
6093+ if (unlikely(!au_opt_test(sbinfo->si_mntflags, XINO)))
1facf9fc 6094+ goto out;
6095+
6096+ pos = inode->i_ino;
6097+ pos *= sizeof(igen);
6098+ igen = inode->i_generation + 1;
1facf9fc 6099+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
6100+ sizeof(igen), &pos);
6101+ if (sz == sizeof(igen))
6102+ goto out; /* success */
6103+
6104+ err = sz;
6105+ if (unlikely(sz >= 0)) {
6106+ err = -EIO;
6107+ AuIOErr("xigen error (%zd)\n", sz);
6108+ }
6109+
6110+ out:
6111+ return err;
6112+}
6113+
6114+int au_xigen_new(struct inode *inode)
6115+{
6116+ int err;
6117+ loff_t pos;
6118+ ssize_t sz;
6119+ struct super_block *sb;
6120+ struct au_sbinfo *sbinfo;
6121+ struct file *file;
6122+
6123+ err = 0;
6124+ /* todo: dirty, at mount time */
6125+ if (inode->i_ino == AUFS_ROOT_INO)
6126+ goto out;
6127+ sb = inode->i_sb;
dece6358 6128+ SiMustAnyLock(sb);
1facf9fc 6129+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
6130+ goto out;
6131+
6132+ err = -EFBIG;
6133+ pos = inode->i_ino;
6134+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
6135+ AuIOErr1("too large i%lld\n", pos);
6136+ goto out;
6137+ }
6138+ pos *= sizeof(inode->i_generation);
6139+
6140+ err = 0;
6141+ sbinfo = au_sbi(sb);
6142+ file = sbinfo->si_xigen;
6143+ BUG_ON(!file);
6144+
6145+ if (i_size_read(file->f_dentry->d_inode)
6146+ < pos + sizeof(inode->i_generation)) {
6147+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
6148+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
6149+ sizeof(inode->i_generation), &pos);
6150+ } else
6151+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
6152+ sizeof(inode->i_generation), &pos);
6153+ if (sz == sizeof(inode->i_generation))
6154+ goto out; /* success */
6155+
6156+ err = sz;
6157+ if (unlikely(sz >= 0)) {
6158+ err = -EIO;
6159+ AuIOErr("xigen error (%zd)\n", sz);
6160+ }
6161+
6162+ out:
6163+ return err;
6164+}
6165+
6166+int au_xigen_set(struct super_block *sb, struct file *base)
6167+{
6168+ int err;
6169+ struct au_sbinfo *sbinfo;
6170+ struct file *file;
6171+
dece6358
AM
6172+ SiMustWriteLock(sb);
6173+
1facf9fc 6174+ sbinfo = au_sbi(sb);
6175+ file = au_xino_create2(base, sbinfo->si_xigen);
6176+ err = PTR_ERR(file);
6177+ if (IS_ERR(file))
6178+ goto out;
6179+ err = 0;
6180+ if (sbinfo->si_xigen)
6181+ fput(sbinfo->si_xigen);
6182+ sbinfo->si_xigen = file;
6183+
6184+ out:
6185+ return err;
6186+}
6187+
6188+void au_xigen_clr(struct super_block *sb)
6189+{
6190+ struct au_sbinfo *sbinfo;
6191+
dece6358
AM
6192+ SiMustWriteLock(sb);
6193+
1facf9fc 6194+ sbinfo = au_sbi(sb);
6195+ if (sbinfo->si_xigen) {
6196+ fput(sbinfo->si_xigen);
6197+ sbinfo->si_xigen = NULL;
6198+ }
6199+}
6200+
6201+/* ---------------------------------------------------------------------- */
6202+
6203+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
6204+ ino_t dir_ino)
6205+{
6206+ struct dentry *dentry, *d;
6207+ struct inode *inode;
6208+ unsigned int sigen;
6209+
6210+ dentry = NULL;
6211+ inode = ilookup(sb, ino);
6212+ if (!inode)
6213+ goto out;
6214+
6215+ dentry = ERR_PTR(-ESTALE);
6216+ sigen = au_sigen(sb);
6217+ if (unlikely(is_bad_inode(inode)
6218+ || IS_DEADDIR(inode)
6219+ || sigen != au_iigen(inode)))
6220+ goto out_iput;
6221+
6222+ dentry = NULL;
6223+ if (!dir_ino || S_ISDIR(inode->i_mode))
6224+ dentry = d_find_alias(inode);
6225+ else {
6226+ spin_lock(&dcache_lock);
6227+ list_for_each_entry(d, &inode->i_dentry, d_alias)
6228+ if (!au_test_anon(d)
6229+ && d->d_parent->d_inode->i_ino == dir_ino) {
6230+ dentry = dget_locked(d);
6231+ break;
6232+ }
6233+ spin_unlock(&dcache_lock);
6234+ }
6235+ if (unlikely(dentry && sigen != au_digen(dentry))) {
6236+ dput(dentry);
6237+ dentry = ERR_PTR(-ESTALE);
6238+ }
6239+
6240+ out_iput:
6241+ iput(inode);
6242+ out:
6243+ return dentry;
6244+}
6245+
6246+/* ---------------------------------------------------------------------- */
6247+
6248+/* todo: dirty? */
6249+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
6250+static struct vfsmount *au_mnt_get(struct super_block *sb)
6251+{
6252+ struct mnt_namespace *ns;
6253+ struct vfsmount *pos, *mnt;
6254+
6255+ spin_lock(&vfsmount_lock);
6256+ /* no get/put ?? */
6257+ AuDebugOn(!current->nsproxy);
6258+ ns = current->nsproxy->mnt_ns;
6259+ AuDebugOn(!ns);
6260+ mnt = NULL;
6261+ /* the order (reverse) will not be a problem */
6262+ list_for_each_entry(pos, &ns->list, mnt_list)
6263+ if (pos->mnt_sb == sb) {
6264+ mnt = mntget(pos);
6265+ break;
6266+ }
6267+ spin_unlock(&vfsmount_lock);
6268+ AuDebugOn(!mnt);
6269+
6270+ return mnt;
6271+}
6272+
6273+struct au_nfsd_si_lock {
6274+ const unsigned int sigen;
6275+ const aufs_bindex_t br_id;
6276+ unsigned char force_lock;
6277+};
6278+
6279+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
6280+ struct au_nfsd_si_lock *nsi_lock)
6281+{
6282+ aufs_bindex_t bindex;
6283+
6284+ si_read_lock(sb, AuLock_FLUSH);
6285+
6286+ /* branch id may be wrapped around */
6287+ bindex = au_br_index(sb, nsi_lock->br_id);
6288+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
6289+ goto out; /* success */
6290+
6291+ if (!nsi_lock->force_lock)
6292+ si_read_unlock(sb);
6293+ bindex = -1;
6294+
6295+ out:
6296+ return bindex;
6297+}
6298+
6299+struct find_name_by_ino {
6300+ int called, found;
6301+ ino_t ino;
6302+ char *name;
6303+ int namelen;
6304+};
6305+
6306+static int
6307+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
6308+ u64 ino, unsigned int d_type)
6309+{
6310+ struct find_name_by_ino *a = arg;
6311+
6312+ a->called++;
6313+ if (a->ino != ino)
6314+ return 0;
6315+
6316+ memcpy(a->name, name, namelen);
6317+ a->namelen = namelen;
6318+ a->found = 1;
6319+ return 1;
6320+}
6321+
6322+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
6323+ struct au_nfsd_si_lock *nsi_lock)
6324+{
6325+ struct dentry *dentry, *parent;
6326+ struct file *file;
6327+ struct inode *dir;
6328+ struct find_name_by_ino arg;
6329+ int err;
6330+
6331+ parent = path->dentry;
6332+ if (nsi_lock)
6333+ si_read_unlock(parent->d_sb);
6334+ path_get(path);
6335+ file = dentry_open(parent, path->mnt, au_dir_roflags, current_cred());
6336+ dentry = (void *)file;
6337+ if (IS_ERR(file))
6338+ goto out;
6339+
6340+ dentry = ERR_PTR(-ENOMEM);
6341+ arg.name = __getname();
6342+ if (unlikely(!arg.name))
6343+ goto out_file;
6344+ arg.ino = ino;
6345+ arg.found = 0;
6346+ do {
6347+ arg.called = 0;
6348+ /* smp_mb(); */
6349+ err = vfsub_readdir(file, find_name_by_ino, &arg);
6350+ } while (!err && !arg.found && arg.called);
6351+ dentry = ERR_PTR(err);
6352+ if (unlikely(err))
6353+ goto out_name;
6354+ dentry = ERR_PTR(-ENOENT);
6355+ if (!arg.found)
6356+ goto out_name;
6357+
6358+ /* do not call au_lkup_one() */
6359+ dir = parent->d_inode;
6360+ mutex_lock(&dir->i_mutex);
6361+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
6362+ mutex_unlock(&dir->i_mutex);
6363+ AuTraceErrPtr(dentry);
6364+ if (IS_ERR(dentry))
6365+ goto out_name;
6366+ AuDebugOn(au_test_anon(dentry));
6367+ if (unlikely(!dentry->d_inode)) {
6368+ dput(dentry);
6369+ dentry = ERR_PTR(-ENOENT);
6370+ }
6371+
6372+ out_name:
6373+ __putname(arg.name);
6374+ out_file:
6375+ fput(file);
6376+ out:
6377+ if (unlikely(nsi_lock
6378+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
6379+ if (!IS_ERR(dentry)) {
6380+ dput(dentry);
6381+ dentry = ERR_PTR(-ESTALE);
6382+ }
6383+ AuTraceErrPtr(dentry);
6384+ return dentry;
6385+}
6386+
6387+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
6388+ ino_t dir_ino,
6389+ struct au_nfsd_si_lock *nsi_lock)
6390+{
6391+ struct dentry *dentry;
6392+ struct path path;
6393+
6394+ if (dir_ino != AUFS_ROOT_INO) {
6395+ path.dentry = decode_by_ino(sb, dir_ino, 0);
6396+ dentry = path.dentry;
6397+ if (!path.dentry || IS_ERR(path.dentry))
6398+ goto out;
6399+ AuDebugOn(au_test_anon(path.dentry));
6400+ } else
6401+ path.dentry = dget(sb->s_root);
6402+
6403+ path.mnt = au_mnt_get(sb);
6404+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
6405+ path_put(&path);
6406+
6407+ out:
6408+ AuTraceErrPtr(dentry);
6409+ return dentry;
6410+}
6411+
6412+/* ---------------------------------------------------------------------- */
6413+
6414+static int h_acceptable(void *expv, struct dentry *dentry)
6415+{
6416+ return 1;
6417+}
6418+
6419+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
6420+ char *buf, int len, struct super_block *sb)
6421+{
6422+ char *p;
6423+ int n;
6424+ struct path path;
6425+
6426+ p = d_path(h_rootpath, buf, len);
6427+ if (IS_ERR(p))
6428+ goto out;
6429+ n = strlen(p);
6430+
6431+ path.mnt = h_rootpath->mnt;
6432+ path.dentry = h_parent;
6433+ p = d_path(&path, buf, len);
6434+ if (IS_ERR(p))
6435+ goto out;
6436+ if (n != 1)
6437+ p += n;
6438+
6439+ path.mnt = au_mnt_get(sb);
6440+ path.dentry = sb->s_root;
6441+ p = d_path(&path, buf, len - strlen(p));
6442+ mntput(path.mnt);
6443+ if (IS_ERR(p))
6444+ goto out;
6445+ if (n != 1)
6446+ p[strlen(p)] = '/';
6447+
6448+ out:
6449+ AuTraceErrPtr(p);
6450+ return p;
6451+}
6452+
6453+static
6454+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
6455+ ino_t ino, __u32 *fh, int fh_len,
6456+ struct au_nfsd_si_lock *nsi_lock)
6457+{
6458+ struct dentry *dentry, *h_parent, *root;
6459+ struct super_block *h_sb;
6460+ char *pathname, *p;
6461+ struct vfsmount *h_mnt;
6462+ struct au_branch *br;
6463+ int err;
6464+ struct path path;
6465+
6466+ br = au_sbr(sb, bindex);
6467+ /* au_br_get(br); */
6468+ h_mnt = br->br_mnt;
6469+ h_sb = h_mnt->mnt_sb;
6470+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
6471+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
6472+ fh_len - Fh_tail, fh[Fh_h_type],
6473+ h_acceptable, /*context*/NULL);
6474+ dentry = h_parent;
6475+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
6476+ AuWarn1("%s decode_fh failed, %ld\n",
6477+ au_sbtype(h_sb), PTR_ERR(h_parent));
6478+ goto out;
6479+ }
6480+ dentry = NULL;
6481+ if (unlikely(au_test_anon(h_parent))) {
6482+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
6483+ au_sbtype(h_sb));
6484+ goto out_h_parent;
6485+ }
6486+
6487+ dentry = ERR_PTR(-ENOMEM);
6488+ pathname = (void *)__get_free_page(GFP_NOFS);
6489+ if (unlikely(!pathname))
6490+ goto out_h_parent;
6491+
6492+ root = sb->s_root;
6493+ path.mnt = h_mnt;
6494+ di_read_lock_parent(root, !AuLock_IR);
6495+ path.dentry = au_h_dptr(root, bindex);
6496+ di_read_unlock(root, !AuLock_IR);
6497+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
6498+ dentry = (void *)p;
6499+ if (IS_ERR(p))
6500+ goto out_pathname;
6501+
6502+ si_read_unlock(sb);
6503+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
6504+ dentry = ERR_PTR(err);
6505+ if (unlikely(err))
6506+ goto out_relock;
6507+
6508+ dentry = ERR_PTR(-ENOENT);
6509+ AuDebugOn(au_test_anon(path.dentry));
6510+ if (unlikely(!path.dentry->d_inode))
6511+ goto out_path;
6512+
6513+ if (ino != path.dentry->d_inode->i_ino)
6514+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
6515+ else
6516+ dentry = dget(path.dentry);
6517+
6518+ out_path:
6519+ path_put(&path);
6520+ out_relock:
6521+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
6522+ if (!IS_ERR(dentry)) {
6523+ dput(dentry);
6524+ dentry = ERR_PTR(-ESTALE);
6525+ }
6526+ out_pathname:
6527+ free_page((unsigned long)pathname);
6528+ out_h_parent:
6529+ dput(h_parent);
6530+ out:
6531+ /* au_br_put(br); */
6532+ AuTraceErrPtr(dentry);
6533+ return dentry;
6534+}
6535+
6536+/* ---------------------------------------------------------------------- */
6537+
6538+static struct dentry *
6539+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
6540+ int fh_type)
6541+{
6542+ struct dentry *dentry;
6543+ __u32 *fh = fid->raw;
6544+ ino_t ino, dir_ino;
6545+ aufs_bindex_t bindex;
6546+ struct au_nfsd_si_lock nsi_lock = {
6547+ .sigen = fh[Fh_sigen],
6548+ .br_id = fh[Fh_br_id],
6549+ .force_lock = 0
6550+ };
6551+
6552+ AuDebugOn(fh_len < Fh_tail);
6553+
6554+ dentry = ERR_PTR(-ESTALE);
6555+ /* branch id may be wrapped around */
6556+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
6557+ if (unlikely(bindex < 0))
6558+ goto out;
6559+ nsi_lock.force_lock = 1;
6560+
6561+ /* is this inode still cached? */
6562+ ino = decode_ino(fh + Fh_ino);
6563+ AuDebugOn(ino == AUFS_ROOT_INO);
6564+ dir_ino = decode_ino(fh + Fh_dir_ino);
6565+ dentry = decode_by_ino(sb, ino, dir_ino);
6566+ if (IS_ERR(dentry))
6567+ goto out_unlock;
6568+ if (dentry)
6569+ goto accept;
6570+
6571+ /* is the parent dir cached? */
6572+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
6573+ if (IS_ERR(dentry))
6574+ goto out_unlock;
6575+ if (dentry)
6576+ goto accept;
6577+
6578+ /* lookup path */
6579+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
6580+ if (IS_ERR(dentry))
6581+ goto out_unlock;
6582+ if (unlikely(!dentry))
6583+ /* todo?: make it ESTALE */
6584+ goto out_unlock;
6585+
6586+ accept:
6587+ if (dentry->d_inode->i_generation == fh[Fh_igen])
6588+ goto out_unlock; /* success */
6589+
6590+ dput(dentry);
6591+ dentry = ERR_PTR(-ESTALE);
6592+ out_unlock:
6593+ si_read_unlock(sb);
6594+ out:
6595+ AuTraceErrPtr(dentry);
6596+ return dentry;
6597+}
6598+
6599+#if 0 /* reserved for future use */
6600+/* support subtreecheck option */
6601+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
6602+ int fh_len, int fh_type)
6603+{
6604+ struct dentry *parent;
6605+ __u32 *fh = fid->raw;
6606+ ino_t dir_ino;
6607+
6608+ dir_ino = decode_ino(fh + Fh_dir_ino);
6609+ parent = decode_by_ino(sb, dir_ino, 0);
6610+ if (IS_ERR(parent))
6611+ goto out;
6612+ if (!parent)
6613+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
6614+ dir_ino, fh, fh_len);
6615+
6616+ out:
6617+ AuTraceErrPtr(parent);
6618+ return parent;
6619+}
6620+#endif
6621+
6622+/* ---------------------------------------------------------------------- */
6623+
6624+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
6625+ int connectable)
6626+{
6627+ int err;
6628+ aufs_bindex_t bindex, bend;
6629+ struct super_block *sb, *h_sb;
6630+ struct inode *inode;
6631+ struct dentry *parent, *h_parent;
6632+ struct au_branch *br;
6633+
6634+ AuDebugOn(au_test_anon(dentry));
6635+
6636+ parent = NULL;
6637+ err = -ENOSPC;
6638+ if (unlikely(*max_len <= Fh_tail)) {
6639+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
6640+ goto out;
6641+ }
6642+
6643+ err = FILEID_ROOT;
6644+ if (IS_ROOT(dentry)) {
6645+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
6646+ goto out;
6647+ }
6648+
6649+ err = -EIO;
6650+ h_parent = NULL;
6651+ sb = dentry->d_sb;
6652+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
6653+ parent = dget_parent(dentry);
6654+ di_read_lock_parent(parent, !AuLock_IR);
6655+ inode = dentry->d_inode;
6656+ AuDebugOn(!inode);
6657+#ifdef CONFIG_AUFS_DEBUG
6658+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
6659+ AuWarn1("NFS-exporting requires xino\n");
6660+#endif
6661+
6662+ bend = au_dbtaildir(parent);
6663+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
6664+ h_parent = au_h_dptr(parent, bindex);
6665+ if (h_parent) {
6666+ dget(h_parent);
6667+ break;
6668+ }
6669+ }
6670+ if (unlikely(!h_parent))
6671+ goto out_unlock;
6672+
6673+ err = -EPERM;
6674+ br = au_sbr(sb, bindex);
6675+ h_sb = br->br_mnt->mnt_sb;
6676+ if (unlikely(!h_sb->s_export_op)) {
6677+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
6678+ goto out_dput;
6679+ }
6680+
6681+ fh[Fh_br_id] = br->br_id;
6682+ fh[Fh_sigen] = au_sigen(sb);
6683+ encode_ino(fh + Fh_ino, inode->i_ino);
6684+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
6685+ fh[Fh_igen] = inode->i_generation;
6686+
6687+ *max_len -= Fh_tail;
6688+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
6689+ max_len,
6690+ /*connectable or subtreecheck*/0);
6691+ err = fh[Fh_h_type];
6692+ *max_len += Fh_tail;
6693+ /* todo: macros? */
6694+ if (err != 255)
6695+ err = 99;
6696+ else
6697+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
6698+
6699+ out_dput:
6700+ dput(h_parent);
6701+ out_unlock:
6702+ di_read_unlock(parent, !AuLock_IR);
6703+ dput(parent);
6704+ aufs_read_unlock(dentry, AuLock_IR);
6705+ out:
6706+ if (unlikely(err < 0))
6707+ err = 255;
6708+ return err;
6709+}
6710+
6711+/* ---------------------------------------------------------------------- */
6712+
6713+static struct export_operations aufs_export_op = {
6714+ .fh_to_dentry = aufs_fh_to_dentry,
6715+ /* .fh_to_parent = aufs_fh_to_parent, */
6716+ .encode_fh = aufs_encode_fh
6717+};
6718+
6719+void au_export_init(struct super_block *sb)
6720+{
6721+ struct au_sbinfo *sbinfo;
6722+ __u32 u;
6723+
6724+ sb->s_export_op = &aufs_export_op;
6725+ sbinfo = au_sbi(sb);
6726+ sbinfo->si_xigen = NULL;
6727+ get_random_bytes(&u, sizeof(u));
6728+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
6729+ atomic_set(&sbinfo->si_xigen_next, u);
6730+}
dece6358
AM
6731diff -urN linux-2.6.30.org/fs/aufs/file.c linux-2.6.30/fs/aufs/file.c
6732--- linux-2.6.30.org/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
6733+++ linux-2.6.30/fs/aufs/file.c 2009-07-21 08:54:19.000000000 +0200
6734@@ -0,0 +1,572 @@
1facf9fc 6735+/*
6736+ * Copyright (C) 2005-2009 Junjiro R. Okajima
6737+ *
6738+ * This program, aufs is free software; you can redistribute it and/or modify
6739+ * it under the terms of the GNU General Public License as published by
6740+ * the Free Software Foundation; either version 2 of the License, or
6741+ * (at your option) any later version.
dece6358
AM
6742+ *
6743+ * This program is distributed in the hope that it will be useful,
6744+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6745+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6746+ * GNU General Public License for more details.
6747+ *
6748+ * You should have received a copy of the GNU General Public License
6749+ * along with this program; if not, write to the Free Software
6750+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6751+ */
6752+
6753+/*
dece6358 6754+ * handling file/dir, and address_space operation
1facf9fc 6755+ */
6756+
dece6358
AM
6757+#include <linux/file.h>
6758+#include <linux/fsnotify.h>
6759+#include <linux/namei.h>
6760+#include <linux/pagemap.h>
1facf9fc 6761+#include "aufs.h"
6762+
dece6358
AM
6763+/*
6764+ * a dirty trick for handling deny_write_access().
6765+ * because FMODE_EXEC flag is not passed to f_op->open(),
6766+ * set it to file->private_data temporary.
6767+ */
6768+void au_store_oflag(struct nameidata *nd, struct inode *inode)
1facf9fc 6769+{
dece6358
AM
6770+ if (nd
6771+ /* && !(nd->flags & LOOKUP_CONTINUE) */
6772+ && (nd->flags & LOOKUP_OPEN)
6773+ && (nd->intent.open.flags & vfsub_fmode_to_uint(FMODE_EXEC))
6774+ && inode
6775+ && S_ISREG(inode->i_mode)) {
6776+ /* suppress a warning in lp64 */
6777+ unsigned long flags = nd->intent.open.flags;
6778+ nd->intent.open.file->private_data = (void *)flags;
6779+ /* smp_mb(); */
1facf9fc 6780+ }
1facf9fc 6781+}
6782+
dece6358
AM
6783+/* drop flags for writing */
6784+unsigned int au_file_roflags(unsigned int flags)
1facf9fc 6785+{
dece6358
AM
6786+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
6787+ flags |= O_RDONLY | O_NOATIME;
6788+ return flags;
1facf9fc 6789+}
6790+
dece6358
AM
6791+/* common functions to regular file and dir */
6792+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
6793+ struct file *file)
1facf9fc 6794+{
1facf9fc 6795+ struct file *h_file;
dece6358
AM
6796+ struct dentry *h_dentry;
6797+ struct inode *h_inode;
1facf9fc 6798+ struct super_block *sb;
dece6358
AM
6799+ struct au_branch *br;
6800+ int err;
6801+
6802+ /* a race condition can happen between open and unlink/rmdir */
6803+ h_file = ERR_PTR(-ENOENT);
6804+ h_dentry = au_h_dptr(dentry, bindex);
6805+ if (au_test_nfsd(current) && !h_dentry)
6806+ goto out;
6807+ h_inode = h_dentry->d_inode;
6808+ if (au_test_nfsd(current) && !h_inode)
6809+ goto out;
6810+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
6811+ || !h_inode))
6812+ goto out;
1facf9fc 6813+
1facf9fc 6814+ sb = dentry->d_sb;
dece6358
AM
6815+ br = au_sbr(sb, bindex);
6816+ h_file = ERR_PTR(-EACCES);
6817+ if (file && (file->f_mode & FMODE_EXEC)
6818+ && (br->br_mnt->mnt_flags & MNT_NOEXEC))
1facf9fc 6819+ goto out;
6820+
dece6358
AM
6821+ /* drop flags for writing */
6822+ if (au_test_ro(sb, bindex, dentry->d_inode))
6823+ flags = au_file_roflags(flags);
6824+ flags &= ~O_CREAT;
6825+ atomic_inc(&br->br_count);
6826+ h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags,
6827+ current_cred());
6828+ if (IS_ERR(h_file))
6829+ goto out_br;
1facf9fc 6830+
dece6358
AM
6831+ if (file && (file->f_mode & FMODE_EXEC)) {
6832+ h_file->f_mode |= FMODE_EXEC;
6833+ err = deny_write_access(h_file);
6834+ if (unlikely(err)) {
6835+ fput(h_file);
6836+ h_file = ERR_PTR(err);
6837+ goto out_br;
6838+ }
6839+ }
6840+ fsnotify_open(h_dentry);
6841+ goto out; /* success */
6842+
6843+ out_br:
6844+ atomic_dec(&br->br_count);
1facf9fc 6845+ out:
dece6358 6846+ return h_file;
1facf9fc 6847+}
6848+
dece6358 6849+int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
1facf9fc 6850+{
dece6358 6851+ int err;
1facf9fc 6852+ struct dentry *dentry;
1facf9fc 6853+ struct super_block *sb;
1facf9fc 6854+
6855+ dentry = file->f_dentry;
6856+ sb = dentry->d_sb;
1facf9fc 6857+ si_read_lock(sb, AuLock_FLUSH);
dece6358 6858+ err = au_finfo_init(file);
1facf9fc 6859+ if (unlikely(err))
6860+ goto out;
6861+
dece6358
AM
6862+ di_read_lock_child(dentry, AuLock_IR);
6863+ err = open(file, file->f_flags);
1facf9fc 6864+ di_read_unlock(dentry, AuLock_IR);
dece6358 6865+
1facf9fc 6866+ fi_write_unlock(file);
dece6358
AM
6867+ if (unlikely(err))
6868+ au_finfo_fin(file);
1facf9fc 6869+ out:
6870+ si_read_unlock(sb);
1facf9fc 6871+ return err;
6872+}
6873+
dece6358 6874+int au_reopen_nondir(struct file *file)
1facf9fc 6875+{
dece6358
AM
6876+ int err;
6877+ aufs_bindex_t bstart, bindex, bend;
1facf9fc 6878+ struct dentry *dentry;
dece6358 6879+ struct file *h_file, *h_file_tmp;
1facf9fc 6880+
6881+ dentry = file->f_dentry;
dece6358
AM
6882+ bstart = au_dbstart(dentry);
6883+ h_file_tmp = NULL;
6884+ if (au_fbstart(file) == bstart) {
6885+ h_file = au_h_fptr(file, bstart);
6886+ if (file->f_mode == h_file->f_mode)
6887+ return 0; /* success */
6888+ h_file_tmp = h_file;
6889+ get_file(h_file_tmp);
6890+ au_set_h_fptr(file, bstart, NULL);
1facf9fc 6891+ }
dece6358
AM
6892+ AuDebugOn(au_fbstart(file) < bstart
6893+ || au_fi(file)->fi_hfile[0 + bstart].hf_file);
6894+
6895+ h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
6896+ err = PTR_ERR(h_file);
6897+ if (IS_ERR(h_file))
6898+ goto out; /* todo: close all? */
6899+
6900+ err = 0;
6901+ au_set_fbstart(file, bstart);
6902+ au_set_h_fptr(file, bstart, h_file);
6903+ au_update_figen(file);
6904+ /* todo: necessary? */
1facf9fc 6905+ /* file->f_ra = h_file->f_ra; */
1facf9fc 6906+
dece6358
AM
6907+ /* close lower files */
6908+ bend = au_fbend(file);
6909+ for (bindex = bstart + 1; bindex <= bend; bindex++)
6910+ au_set_h_fptr(file, bindex, NULL);
6911+ au_set_fbend(file, bstart);
1facf9fc 6912+
6913+ out:
dece6358
AM
6914+ if (h_file_tmp)
6915+ fput(h_file_tmp);
1facf9fc 6916+ return err;
6917+}
6918+
dece6358 6919+/* ---------------------------------------------------------------------- */
1facf9fc 6920+
dece6358
AM
6921+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
6922+ struct dentry *hi_wh)
1facf9fc 6923+{
6924+ int err;
dece6358
AM
6925+ aufs_bindex_t bstart;
6926+ struct au_dinfo *dinfo;
6927+ struct dentry *h_dentry;
1facf9fc 6928+
dece6358
AM
6929+ dinfo = au_di(file->f_dentry);
6930+ bstart = dinfo->di_bstart;
6931+ dinfo->di_bstart = btgt;
6932+ h_dentry = dinfo->di_hdentry[0 + btgt].hd_dentry;
6933+ dinfo->di_hdentry[0 + btgt].hd_dentry = hi_wh;
6934+ err = au_reopen_nondir(file);
6935+ dinfo->di_hdentry[0 + btgt].hd_dentry = h_dentry;
6936+ dinfo->di_bstart = bstart;
1facf9fc 6937+
6938+ return err;
6939+}
6940+
dece6358
AM
6941+static int au_ready_to_write_wh(struct file *file, loff_t len,
6942+ aufs_bindex_t bcpup)
1facf9fc 6943+{
1facf9fc 6944+ int err;
dece6358
AM
6945+ struct inode *inode;
6946+ struct dentry *dentry, *hi_wh;
6947+ struct super_block *sb;
1facf9fc 6948+
dece6358
AM
6949+ dentry = file->f_dentry;
6950+ inode = dentry->d_inode;
6951+ hi_wh = au_hi_wh(inode, bcpup);
6952+ if (!hi_wh)
6953+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
6954+ else
6955+ /* already copied-up after unlink */
6956+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 6957+
dece6358
AM
6958+ sb = dentry->d_sb;
6959+ if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
6960+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1facf9fc 6961+
dece6358 6962+ return err;
1facf9fc 6963+}
6964+
dece6358
AM
6965+/*
6966+ * prepare the @file for writing.
6967+ */
6968+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 6969+{
6970+ int err;
dece6358
AM
6971+ aufs_bindex_t bstart, bcpup;
6972+ struct dentry *dentry, *parent, *h_dentry;
6973+ struct inode *h_inode, *inode;
1facf9fc 6974+ struct super_block *sb;
1facf9fc 6975+
6976+ dentry = file->f_dentry;
1facf9fc 6977+ sb = dentry->d_sb;
dece6358
AM
6978+ bstart = au_fbstart(file);
6979+ inode = dentry->d_inode;
6980+ err = au_test_ro(sb, bstart, inode);
6981+ if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
6982+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 6983+ goto out;
dece6358 6984+ }
1facf9fc 6985+
dece6358
AM
6986+ /* need to cpup */
6987+ parent = dget_parent(dentry);
6988+ di_write_lock_parent(parent);
6989+ err = AuWbrCopyup(au_sbi(sb), dentry);
6990+ bcpup = err;
6991+ if (unlikely(err < 0))
6992+ goto out_dgrade;
6993+ err = 0;
1facf9fc 6994+
dece6358
AM
6995+ if (!au_h_dptr(parent, bcpup)) {
6996+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 6997+ if (unlikely(err))
dece6358 6998+ goto out_dgrade;
1facf9fc 6999+ }
7000+
dece6358
AM
7001+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
7002+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
1facf9fc 7003+ if (unlikely(err))
dece6358 7004+ goto out_dgrade;
1facf9fc 7005+
dece6358
AM
7006+ h_dentry = au_h_fptr(file, bstart)->f_dentry;
7007+ h_inode = h_dentry->d_inode;
7008+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
7009+ if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
7010+ /* || !h_inode->i_nlink */) {
7011+ err = au_ready_to_write_wh(file, len, bcpup);
7012+ di_downgrade_lock(parent, AuLock_IR);
7013+ } else {
7014+ di_downgrade_lock(parent, AuLock_IR);
7015+ if (!au_h_dptr(dentry, bcpup))
7016+ err = au_sio_cpup_simple(dentry, bcpup, len,
7017+ AuCpup_DTIME);
7018+ if (!err)
7019+ err = au_reopen_nondir(file);
7020+ }
7021+ mutex_unlock(&h_inode->i_mutex);
7022+
7023+ if (!err) {
7024+ au_pin_set_parent_lflag(pin, /*lflag*/0);
7025+ goto out_dput; /* success */
7026+ }
7027+ au_unpin(pin);
7028+ goto out_unlock;
1facf9fc 7029+
dece6358
AM
7030+ out_dgrade:
7031+ di_downgrade_lock(parent, AuLock_IR);
1facf9fc 7032+ out_unlock:
dece6358
AM
7033+ di_read_unlock(parent, AuLock_IR);
7034+ out_dput:
7035+ dput(parent);
1facf9fc 7036+ out:
1facf9fc 7037+ return err;
7038+}
7039+
7040+/* ---------------------------------------------------------------------- */
7041+
dece6358 7042+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 7043+{
1facf9fc 7044+ int err;
dece6358
AM
7045+ aufs_bindex_t bstart;
7046+ struct au_pin pin;
7047+ struct au_finfo *finfo;
7048+ struct dentry *dentry, *parent, *hi_wh;
7049+ struct inode *inode;
1facf9fc 7050+ struct super_block *sb;
7051+
dece6358
AM
7052+ err = 0;
7053+ finfo = au_fi(file);
1facf9fc 7054+ dentry = file->f_dentry;
7055+ sb = dentry->d_sb;
dece6358
AM
7056+ inode = dentry->d_inode;
7057+ bstart = au_ibstart(inode);
7058+ if (bstart == finfo->fi_bstart)
1facf9fc 7059+ goto out;
7060+
dece6358
AM
7061+ parent = dget_parent(dentry);
7062+ if (au_test_ro(sb, bstart, inode)) {
7063+ di_read_lock_parent(parent, !AuLock_IR);
7064+ err = AuWbrCopyup(au_sbi(sb), dentry);
7065+ bstart = err;
7066+ di_read_unlock(parent, !AuLock_IR);
7067+ if (unlikely(err < 0))
7068+ goto out_parent;
7069+ err = 0;
7070+ }
1facf9fc 7071+
dece6358
AM
7072+ di_read_lock_parent(parent, AuLock_IR);
7073+ hi_wh = au_hi_wh(inode, bstart);
7074+ if (au_opt_test(au_mntflags(sb), PLINK)
7075+ && au_plink_test(inode)
7076+ && !d_unhashed(dentry)) {
7077+ err = au_test_and_cpup_dirs(dentry, bstart);
7078+ if (unlikely(err))
7079+ goto out_unlock;
7080+
7081+ /* always superio. */
7082+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
7083+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
7084+ if (!err)
7085+ err = au_sio_cpup_simple(dentry, bstart, -1,
7086+ AuCpup_DTIME);
7087+ au_unpin(&pin);
7088+ } else if (hi_wh) {
7089+ /* already copied-up after unlink */
7090+ err = au_reopen_wh(file, bstart, hi_wh);
7091+ *need_reopen = 0;
7092+ }
1facf9fc 7093+
dece6358
AM
7094+ out_unlock:
7095+ di_read_unlock(parent, AuLock_IR);
7096+ out_parent:
7097+ dput(parent);
1facf9fc 7098+ out:
dece6358 7099+ return err;
1facf9fc 7100+}
7101+
dece6358 7102+static void au_do_refresh_file(struct file *file)
1facf9fc 7103+{
dece6358
AM
7104+ aufs_bindex_t bindex, bend, new_bindex, brid;
7105+ struct au_hfile *p, tmp, *q;
7106+ struct au_finfo *finfo;
1facf9fc 7107+ struct super_block *sb;
7108+
dece6358
AM
7109+ sb = file->f_dentry->d_sb;
7110+ finfo = au_fi(file);
7111+ p = finfo->fi_hfile + finfo->fi_bstart;
7112+ brid = p->hf_br->br_id;
7113+ bend = finfo->fi_bend;
7114+ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
7115+ if (!p->hf_file)
7116+ continue;
7117+
7118+ new_bindex = au_br_index(sb, p->hf_br->br_id);
7119+ if (new_bindex == bindex)
7120+ continue;
7121+ if (new_bindex < 0) {
7122+ au_set_h_fptr(file, bindex, NULL);
7123+ continue;
7124+ }
7125+
7126+ /* swap two lower inode, and loop again */
7127+ q = finfo->fi_hfile + new_bindex;
7128+ tmp = *q;
7129+ *q = *p;
7130+ *p = tmp;
7131+ if (tmp.hf_file) {
7132+ bindex--;
7133+ p--;
7134+ }
1facf9fc 7135+ }
1facf9fc 7136+
dece6358
AM
7137+ p = finfo->fi_hfile;
7138+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
7139+ bend = au_sbend(sb);
7140+ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
7141+ finfo->fi_bstart++, p++)
7142+ if (p->hf_file) {
7143+ if (p->hf_file->f_dentry
7144+ && p->hf_file->f_dentry->d_inode)
7145+ break;
7146+ else
7147+ au_hfput(p, file);
7148+ }
7149+ } else {
7150+ bend = au_br_index(sb, brid);
7151+ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
7152+ finfo->fi_bstart++, p++)
7153+ if (p->hf_file)
7154+ au_hfput(p, file);
7155+ bend = au_sbend(sb);
7156+ }
1facf9fc 7157+
dece6358
AM
7158+ p = finfo->fi_hfile + bend;
7159+ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
7160+ finfo->fi_bend--, p--)
7161+ if (p->hf_file) {
7162+ if (p->hf_file->f_dentry
7163+ && p->hf_file->f_dentry->d_inode)
7164+ break;
7165+ else
7166+ au_hfput(p, file);
7167+ }
7168+ AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
7169+}
1facf9fc 7170+
dece6358
AM
7171+/*
7172+ * after branch manipulating, refresh the file.
7173+ */
7174+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
7175+{
7176+ int err, need_reopen;
7177+ struct dentry *dentry;
7178+ aufs_bindex_t bend, bindex;
1facf9fc 7179+
dece6358
AM
7180+ dentry = file->f_dentry;
7181+ err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1);
7182+ if (unlikely(err))
7183+ goto out;
7184+ au_do_refresh_file(file);
1facf9fc 7185+
dece6358
AM
7186+ err = 0;
7187+ need_reopen = 1;
7188+ if (!au_test_mmapped(file))
7189+ err = au_file_refresh_by_inode(file, &need_reopen);
7190+ if (!err && need_reopen && !d_unhashed(dentry))
7191+ err = reopen(file);
7192+ if (!err) {
7193+ au_update_figen(file);
7194+ return 0; /* success */
1facf9fc 7195+ }
7196+
dece6358
AM
7197+ /* error, close all lower files */
7198+ bend = au_fbend(file);
7199+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
7200+ au_set_h_fptr(file, bindex, NULL);
7201+
1facf9fc 7202+ out:
1facf9fc 7203+ return err;
7204+}
7205+
dece6358
AM
7206+/* common function to regular file and dir */
7207+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
7208+ int wlock)
1facf9fc 7209+{
7210+ int err;
dece6358
AM
7211+ unsigned int sigen, figen;
7212+ aufs_bindex_t bstart;
7213+ unsigned char pseudo_link;
1facf9fc 7214+ struct dentry *dentry;
1facf9fc 7215+
dece6358 7216+ err = 0;
1facf9fc 7217+ dentry = file->f_dentry;
dece6358
AM
7218+ sigen = au_sigen(dentry->d_sb);
7219+ fi_write_lock(file);
7220+ figen = au_figen(file);
7221+ di_write_lock_child(dentry);
7222+ bstart = au_dbstart(dentry);
7223+ pseudo_link = (bstart != au_ibstart(dentry->d_inode));
7224+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
7225+ if (!wlock) {
7226+ di_downgrade_lock(dentry, AuLock_IR);
7227+ fi_downgrade_lock(file);
7228+ }
7229+ goto out; /* success */
7230+ }
1facf9fc 7231+
dece6358
AM
7232+ AuDbg("sigen %d, figen %d\n", sigen, figen);
7233+ if (sigen != au_digen(dentry)
7234+ || sigen != au_iigen(dentry->d_inode)) {
7235+ err = au_reval_dpath(dentry, sigen);
7236+ if (unlikely(err < 0))
7237+ goto out;
7238+ AuDebugOn(au_digen(dentry) != sigen
7239+ || au_iigen(dentry->d_inode) != sigen);
7240+ }
1facf9fc 7241+
dece6358
AM
7242+ err = refresh_file(file, reopen);
7243+ if (!err) {
7244+ if (!wlock) {
7245+ di_downgrade_lock(dentry, AuLock_IR);
7246+ fi_downgrade_lock(file);
7247+ }
7248+ } else {
7249+ di_write_unlock(dentry);
7250+ fi_write_unlock(file);
7251+ }
1facf9fc 7252+
7253+ out:
1facf9fc 7254+ return err;
7255+}
7256+
7257+/* ---------------------------------------------------------------------- */
7258+
dece6358
AM
7259+/* cf. aufs_nopage() */
7260+/* for madvise(2) */
7261+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
7262+{
7263+ unlock_page(page);
7264+ return 0;
7265+}
1facf9fc 7266+
dece6358
AM
7267+/* they will never be called. */
7268+#ifdef CONFIG_AUFS_DEBUG
7269+static int aufs_write_begin(struct file *file, struct address_space *mapping,
7270+ loff_t pos, unsigned len, unsigned flags,
7271+ struct page **pagep, void **fsdata)
7272+{ AuUnsupport(); return 0; }
7273+static int aufs_write_end(struct file *file, struct address_space *mapping,
7274+ loff_t pos, unsigned len, unsigned copied,
7275+ struct page *page, void *fsdata)
7276+{ AuUnsupport(); return 0; }
7277+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
7278+{ AuUnsupport(); return 0; }
7279+static void aufs_sync_page(struct page *page)
7280+{ AuUnsupport(); }
7281+
7282+static int aufs_set_page_dirty(struct page *page)
7283+{ AuUnsupport(); return 0; }
7284+static void aufs_invalidatepage(struct page *page, unsigned long offset)
7285+{ AuUnsupport(); }
7286+static int aufs_releasepage(struct page *page, gfp_t gfp)
7287+{ AuUnsupport(); return 0; }
7288+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
7289+ const struct iovec *iov, loff_t offset,
7290+ unsigned long nr_segs)
7291+{ AuUnsupport(); return 0; }
7292+#endif /* CONFIG_AUFS_DEBUG */
7293+
7294+struct address_space_operations aufs_aop = {
7295+ .readpage = aufs_readpage,
7296+#ifdef CONFIG_AUFS_DEBUG
7297+ .writepage = aufs_writepage,
7298+ .sync_page = aufs_sync_page,
7299+ .set_page_dirty = aufs_set_page_dirty,
7300+ .write_begin = aufs_write_begin,
7301+ .write_end = aufs_write_end,
7302+ .invalidatepage = aufs_invalidatepage,
7303+ .releasepage = aufs_releasepage,
7304+ .direct_IO = aufs_direct_IO,
7305+#endif /* CONFIG_AUFS_DEBUG */
1facf9fc 7306+};
dece6358
AM
7307diff -urN linux-2.6.30.org/fs/aufs/file.h linux-2.6.30/fs/aufs/file.h
7308--- linux-2.6.30.org/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
7309+++ linux-2.6.30/fs/aufs/file.h 2009-07-21 08:54:19.000000000 +0200
7310@@ -0,0 +1,167 @@
1facf9fc 7311+/*
7312+ * Copyright (C) 2005-2009 Junjiro R. Okajima
7313+ *
7314+ * This program, aufs is free software; you can redistribute it and/or modify
7315+ * it under the terms of the GNU General Public License as published by
7316+ * the Free Software Foundation; either version 2 of the License, or
7317+ * (at your option) any later version.
dece6358
AM
7318+ *
7319+ * This program is distributed in the hope that it will be useful,
7320+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7321+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7322+ * GNU General Public License for more details.
7323+ *
7324+ * You should have received a copy of the GNU General Public License
7325+ * along with this program; if not, write to the Free Software
7326+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7327+ */
7328+
7329+/*
dece6358 7330+ * file operations
1facf9fc 7331+ */
7332+
dece6358
AM
7333+#ifndef __AUFS_FILE_H__
7334+#define __AUFS_FILE_H__
1facf9fc 7335+
dece6358 7336+#ifdef __KERNEL__
1facf9fc 7337+
dece6358
AM
7338+#include <linux/fs.h>
7339+#include <linux/poll.h>
7340+#include <linux/aufs_type.h>
7341+#include "rwsem.h"
1facf9fc 7342+
dece6358
AM
7343+struct au_branch;
7344+struct au_hfile {
7345+ struct file *hf_file;
7346+ struct au_branch *hf_br;
7347+};
1facf9fc 7348+
dece6358
AM
7349+struct au_vdir;
7350+struct au_finfo {
7351+ atomic_t fi_generation;
1facf9fc 7352+
dece6358
AM
7353+ struct au_rwsem fi_rwsem;
7354+ struct au_hfile *fi_hfile;
7355+ aufs_bindex_t fi_bstart, fi_bend;
1facf9fc 7356+
dece6358
AM
7357+ union {
7358+ /* non-dir only */
7359+ struct {
7360+ struct vm_operations_struct *fi_h_vm_ops;
7361+ struct vm_operations_struct *fi_vm_ops;
7362+ };
1facf9fc 7363+
dece6358
AM
7364+ /* dir only */
7365+ struct {
7366+ struct au_vdir *fi_vdir_cache;
7367+ int fi_maintain_plink;
7368+ };
7369+ };
7370+};
1facf9fc 7371+
dece6358 7372+/* ---------------------------------------------------------------------- */
1facf9fc 7373+
dece6358
AM
7374+/* file.c */
7375+extern struct address_space_operations aufs_aop;
7376+void au_store_oflag(struct nameidata *nd, struct inode *inode);
7377+unsigned int au_file_roflags(unsigned int flags);
7378+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7379+ struct file *file);
7380+int au_do_open(struct file *file, int (*open)(struct file *file, int flags));
7381+int au_reopen_nondir(struct file *file);
7382+struct au_pin;
7383+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
7384+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
7385+ int wlock);
1facf9fc 7386+
dece6358
AM
7387+/* poll.c */
7388+#ifdef CONFIG_AUFS_POLL
7389+unsigned int aufs_poll(struct file *file, poll_table *wait);
7390+#endif
1facf9fc 7391+
dece6358
AM
7392+/* f_op.c */
7393+extern const struct file_operations aufs_file_fop;
7394+int aufs_flush(struct file *file, fl_owner_t id);
1facf9fc 7395+
dece6358
AM
7396+/* finfo.c */
7397+void au_hfput(struct au_hfile *hf, struct file *file);
7398+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
7399+ struct file *h_file);
1facf9fc 7400+
dece6358 7401+void au_update_figen(struct file *file);
1facf9fc 7402+
dece6358
AM
7403+void au_finfo_fin(struct file *file);
7404+int au_finfo_init(struct file *file);
7405+int au_fi_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 7406+
dece6358 7407+/* ---------------------------------------------------------------------- */
1facf9fc 7408+
dece6358
AM
7409+static inline struct au_finfo *au_fi(struct file *file)
7410+{
7411+ return file->private_data;
7412+}
1facf9fc 7413+
dece6358 7414+/* ---------------------------------------------------------------------- */
1facf9fc 7415+
dece6358
AM
7416+/*
7417+ * fi_read_lock, fi_write_lock,
7418+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
7419+ */
7420+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
7421+
7422+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
7423+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
7424+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 7425+
7426+/* ---------------------------------------------------------------------- */
7427+
dece6358
AM
7428+/* todo: hard/soft set? */
7429+static inline aufs_bindex_t au_fbstart(struct file *file)
1facf9fc 7430+{
dece6358
AM
7431+ return au_fi(file)->fi_bstart;
7432+}
1facf9fc 7433+
dece6358
AM
7434+static inline aufs_bindex_t au_fbend(struct file *file)
7435+{
7436+ return au_fi(file)->fi_bend;
7437+}
1facf9fc 7438+
dece6358
AM
7439+static inline struct au_vdir *au_fvdir_cache(struct file *file)
7440+{
7441+ return au_fi(file)->fi_vdir_cache;
1facf9fc 7442+}
7443+
dece6358 7444+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
1facf9fc 7445+{
dece6358
AM
7446+ au_fi(file)->fi_bstart = bindex;
7447+}
1facf9fc 7448+
dece6358
AM
7449+static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
7450+{
7451+ au_fi(file)->fi_bend = bindex;
7452+}
1facf9fc 7453+
dece6358
AM
7454+static inline void au_set_fvdir_cache(struct file *file,
7455+ struct au_vdir *vdir_cache)
7456+{
7457+ au_fi(file)->fi_vdir_cache = vdir_cache;
7458+}
1facf9fc 7459+
dece6358
AM
7460+static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
7461+{
7462+ return au_fi(file)->fi_hfile[0 + bindex].hf_file;
1facf9fc 7463+}
7464+
dece6358
AM
7465+/* todo: memory barrier? */
7466+static inline unsigned int au_figen(struct file *f)
1facf9fc 7467+{
dece6358
AM
7468+ return atomic_read(&au_fi(f)->fi_generation);
7469+}
1facf9fc 7470+
dece6358
AM
7471+static inline int au_test_mmapped(struct file *f)
7472+{
7473+ return !!(au_fi(f)->fi_h_vm_ops);
7474+}
1facf9fc 7475+
dece6358
AM
7476+#endif /* __KERNEL__ */
7477+#endif /* __AUFS_FILE_H__ */
7478diff -urN linux-2.6.30.org/fs/aufs/finfo.c linux-2.6.30/fs/aufs/finfo.c
7479--- linux-2.6.30.org/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
7480+++ linux-2.6.30/fs/aufs/finfo.c 2009-07-21 08:54:19.000000000 +0200
7481@@ -0,0 +1,133 @@
7482+/*
7483+ * Copyright (C) 2005-2009 Junjiro R. Okajima
7484+ *
7485+ * This program, aufs is free software; you can redistribute it and/or modify
7486+ * it under the terms of the GNU General Public License as published by
7487+ * the Free Software Foundation; either version 2 of the License, or
7488+ * (at your option) any later version.
7489+ *
7490+ * This program is distributed in the hope that it will be useful,
7491+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7492+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7493+ * GNU General Public License for more details.
7494+ *
7495+ * You should have received a copy of the GNU General Public License
7496+ * along with this program; if not, write to the Free Software
7497+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7498+ */
1facf9fc 7499+
dece6358
AM
7500+/*
7501+ * file private data
7502+ */
1facf9fc 7503+
dece6358
AM
7504+#include <linux/file.h>
7505+#include "aufs.h"
1facf9fc 7506+
dece6358
AM
7507+void au_hfput(struct au_hfile *hf, struct file *file)
7508+{
7509+ if (file->f_mode & FMODE_EXEC)
7510+ allow_write_access(hf->hf_file);
7511+ fput(hf->hf_file);
7512+ hf->hf_file = NULL;
7513+ atomic_dec_return(&hf->hf_br->br_count);
7514+ hf->hf_br = NULL;
7515+}
1facf9fc 7516+
dece6358
AM
7517+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
7518+{
7519+ struct au_finfo *finfo = au_fi(file);
7520+ struct au_hfile *hf;
7521+
7522+ hf = finfo->fi_hfile + bindex;
7523+ if (hf->hf_file)
7524+ au_hfput(hf, file);
7525+ if (val) {
7526+ hf->hf_file = val;
7527+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1facf9fc 7528+ }
dece6358 7529+}
1facf9fc 7530+
dece6358
AM
7531+void au_update_figen(struct file *file)
7532+{
7533+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
7534+ /* smp_mb(); */ /* atomic_set */
1facf9fc 7535+}
7536+
7537+/* ---------------------------------------------------------------------- */
7538+
dece6358 7539+void au_finfo_fin(struct file *file)
1facf9fc 7540+{
1facf9fc 7541+ struct au_finfo *finfo;
dece6358
AM
7542+ aufs_bindex_t bindex, bend;
7543+
7544+ fi_write_lock(file);
7545+ bend = au_fbend(file);
7546+ bindex = au_fbstart(file);
7547+ if (bindex >= 0)
7548+ /*
7549+ * calls fput() instead of filp_close(),
7550+ * since no dnotify or lock for the lower file.
7551+ */
7552+ for (; bindex <= bend; bindex++)
7553+ au_set_h_fptr(file, bindex, NULL);
1facf9fc 7554+
1facf9fc 7555+ finfo = au_fi(file);
dece6358
AM
7556+ au_dbg_verify_hf(finfo);
7557+ kfree(finfo->fi_hfile);
7558+ fi_write_unlock(file);
7559+ AuRwDestroy(&finfo->fi_rwsem);
7560+ au_cache_free_finfo(finfo);
7561+}
7562+
7563+int au_finfo_init(struct file *file)
7564+{
7565+ struct au_finfo *finfo;
7566+ struct dentry *dentry;
7567+ unsigned long ul;
7568+
1facf9fc 7569+ dentry = file->f_dentry;
dece6358
AM
7570+ finfo = au_cache_alloc_finfo();
7571+ if (unlikely(!finfo))
1facf9fc 7572+ goto out;
7573+
dece6358
AM
7574+ finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
7575+ sizeof(*finfo->fi_hfile), GFP_NOFS);
7576+ if (unlikely(!finfo->fi_hfile))
7577+ goto out_finfo;
1facf9fc 7578+
dece6358
AM
7579+ au_rw_init_wlock(&finfo->fi_rwsem);
7580+ finfo->fi_bstart = -1;
7581+ finfo->fi_bend = -1;
7582+ atomic_set(&finfo->fi_generation, au_digen(dentry));
7583+ /* smp_mb(); */ /* atomic_set */
1facf9fc 7584+
dece6358
AM
7585+ /* cf. au_store_oflag() */
7586+ /* suppress a warning in lp64 */
7587+ ul = (unsigned long)file->private_data;
7588+ file->f_mode |= (vfsub_uint_to_fmode(ul) & FMODE_EXEC);
7589+ file->private_data = finfo;
7590+ return 0; /* success */
1facf9fc 7591+
dece6358
AM
7592+ out_finfo:
7593+ au_cache_free_finfo(finfo);
1facf9fc 7594+ out:
dece6358 7595+ return -ENOMEM;
1facf9fc 7596+}
7597+
dece6358 7598+int au_fi_realloc(struct au_finfo *finfo, int nbr)
1facf9fc 7599+{
dece6358
AM
7600+ int err, sz;
7601+ struct au_hfile *hfp;
1facf9fc 7602+
dece6358
AM
7603+ err = -ENOMEM;
7604+ sz = sizeof(*hfp) * (finfo->fi_bend + 1);
7605+ if (!sz)
7606+ sz = sizeof(*hfp);
7607+ hfp = au_kzrealloc(finfo->fi_hfile, sz, sizeof(*hfp) * nbr, GFP_NOFS);
7608+ if (hfp) {
7609+ finfo->fi_hfile = hfp;
7610+ err = 0;
1facf9fc 7611+ }
7612+
dece6358 7613+ return err;
1facf9fc 7614+}
dece6358
AM
7615diff -urN linux-2.6.30.org/fs/aufs/f_op.c linux-2.6.30/fs/aufs/f_op.c
7616--- linux-2.6.30.org/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
7617+++ linux-2.6.30/fs/aufs/f_op.c 2009-07-21 08:54:19.000000000 +0200
7618@@ -0,0 +1,801 @@
7619+/*
7620+ * Copyright (C) 2005-2009 Junjiro R. Okajima
7621+ *
7622+ * This program, aufs is free software; you can redistribute it and/or modify
7623+ * it under the terms of the GNU General Public License as published by
7624+ * the Free Software Foundation; either version 2 of the License, or
7625+ * (at your option) any later version.
7626+ *
7627+ * This program is distributed in the hope that it will be useful,
7628+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7629+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7630+ * GNU General Public License for more details.
7631+ *
7632+ * You should have received a copy of the GNU General Public License
7633+ * along with this program; if not, write to the Free Software
7634+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7635+ */
1facf9fc 7636+
7637+/*
dece6358 7638+ * file and vm operations
1facf9fc 7639+ */
dece6358
AM
7640+
7641+#include <linux/file.h>
7642+#include <linux/fs_stack.h>
7643+#include <linux/mm.h>
7644+#include <linux/security.h>
7645+#include "aufs.h"
7646+
7647+/* common function to regular file and dir */
7648+int aufs_flush(struct file *file, fl_owner_t id)
1facf9fc 7649+{
dece6358
AM
7650+ int err;
7651+ aufs_bindex_t bindex, bend;
1facf9fc 7652+ struct dentry *dentry;
dece6358 7653+ struct file *h_file;
1facf9fc 7654+
7655+ dentry = file->f_dentry;
dece6358
AM
7656+ si_noflush_read_lock(dentry->d_sb);
7657+ fi_read_lock(file);
7658+ di_read_lock_child(dentry, AuLock_IW);
1facf9fc 7659+
7660+ err = 0;
1facf9fc 7661+ bend = au_fbend(file);
dece6358
AM
7662+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
7663+ h_file = au_h_fptr(file, bindex);
7664+ if (!h_file || !h_file->f_op || !h_file->f_op->flush)
7665+ continue;
1facf9fc 7666+
dece6358
AM
7667+ err = h_file->f_op->flush(h_file, id);
7668+ if (!err)
7669+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
7670+ /*ignore*/
7671+ }
7672+ au_cpup_attr_timesizes(dentry->d_inode);
7673+
7674+ di_read_unlock(dentry, AuLock_IW);
7675+ fi_read_unlock(file);
7676+ si_read_unlock(dentry->d_sb);
1facf9fc 7677+ return err;
7678+}
7679+
dece6358
AM
7680+/* ---------------------------------------------------------------------- */
7681+
7682+static int do_open_nondir(struct file *file, int flags)
1facf9fc 7683+{
7684+ int err;
dece6358
AM
7685+ aufs_bindex_t bindex;
7686+ struct file *h_file;
1facf9fc 7687+ struct dentry *dentry;
dece6358 7688+ struct au_finfo *finfo;
1facf9fc 7689+
7690+ err = 0;
7691+ dentry = file->f_dentry;
dece6358
AM
7692+ finfo = au_fi(file);
7693+ finfo->fi_h_vm_ops = NULL;
7694+ finfo->fi_vm_ops = NULL;
7695+ bindex = au_dbstart(dentry);
7696+ /* O_TRUNC is processed already */
7697+ BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode)
7698+ && (flags & O_TRUNC));
1facf9fc 7699+
dece6358
AM
7700+ h_file = au_h_open(dentry, bindex, flags, file);
7701+ if (IS_ERR(h_file))
7702+ err = PTR_ERR(h_file);
7703+ else {
7704+ au_set_fbstart(file, bindex);
7705+ au_set_fbend(file, bindex);
7706+ au_set_h_fptr(file, bindex, h_file);
7707+ au_update_figen(file);
7708+ /* todo: necessary? */
7709+ /* file->f_ra = h_file->f_ra; */
1facf9fc 7710+ }
1facf9fc 7711+ return err;
7712+}
7713+
dece6358
AM
7714+static int aufs_open_nondir(struct inode *inode __maybe_unused,
7715+ struct file *file)
7716+{
7717+ return au_do_open(file, do_open_nondir);
7718+}
1facf9fc 7719+
dece6358
AM
7720+static int aufs_release_nondir(struct inode *inode __maybe_unused,
7721+ struct file *file)
1facf9fc 7722+{
dece6358
AM
7723+ struct super_block *sb = file->f_dentry->d_sb;
7724+
7725+ si_noflush_read_lock(sb);
7726+ kfree(au_fi(file)->fi_vm_ops);
7727+ au_finfo_fin(file);
7728+ si_read_unlock(sb);
1facf9fc 7729+ return 0;
7730+}
7731+
dece6358 7732+/* ---------------------------------------------------------------------- */
1facf9fc 7733+
dece6358
AM
7734+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
7735+ loff_t *ppos)
7736+{
7737+ ssize_t err;
7738+ struct dentry *dentry;
7739+ struct file *h_file;
7740+ struct super_block *sb;
1facf9fc 7741+
dece6358
AM
7742+ dentry = file->f_dentry;
7743+ sb = dentry->d_sb;
7744+ si_read_lock(sb, AuLock_FLUSH);
7745+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
7746+ if (unlikely(err))
7747+ goto out;
1facf9fc 7748+
dece6358
AM
7749+ h_file = au_h_fptr(file, au_fbstart(file));
7750+ err = vfsub_read_u(h_file, buf, count, ppos);
7751+ /* todo: necessary? */
7752+ /* file->f_ra = h_file->f_ra; */
7753+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 7754+
dece6358
AM
7755+ di_read_unlock(dentry, AuLock_IR);
7756+ fi_read_unlock(file);
7757+ out:
7758+ si_read_unlock(sb);
7759+ return err;
7760+}
1facf9fc 7761+
dece6358
AM
7762+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
7763+ size_t count, loff_t *ppos)
7764+{
7765+ ssize_t err;
7766+ aufs_bindex_t bstart;
7767+ struct au_pin pin;
7768+ struct dentry *dentry;
7769+ struct inode *inode;
7770+ struct super_block *sb;
7771+ struct file *h_file;
7772+ char __user *buf = (char __user *)ubuf;
1facf9fc 7773+
dece6358
AM
7774+ dentry = file->f_dentry;
7775+ sb = dentry->d_sb;
7776+ inode = dentry->d_inode;
7777+ mutex_lock(&inode->i_mutex);
7778+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 7779+
dece6358
AM
7780+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
7781+ if (unlikely(err))
7782+ goto out;
1facf9fc 7783+
dece6358
AM
7784+ err = au_ready_to_write(file, -1, &pin);
7785+ di_downgrade_lock(dentry, AuLock_IR);
7786+ if (unlikely(err))
7787+ goto out_unlock;
1facf9fc 7788+
dece6358
AM
7789+ bstart = au_fbstart(file);
7790+ h_file = au_h_fptr(file, bstart);
7791+ au_unpin(&pin);
7792+ err = vfsub_write_u(h_file, buf, count, ppos);
7793+ au_cpup_attr_timesizes(inode);
7794+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 7795+
dece6358
AM
7796+ out_unlock:
7797+ di_read_unlock(dentry, AuLock_IR);
7798+ fi_write_unlock(file);
7799+ out:
7800+ si_read_unlock(sb);
7801+ mutex_unlock(&inode->i_mutex);
7802+ return err;
7803+}
1facf9fc 7804+
dece6358
AM
7805+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
7806+ unsigned long nv, loff_t pos)
7807+{
7808+ ssize_t err;
7809+ struct file *file, *h_file;
7810+ struct dentry *dentry;
7811+ struct super_block *sb;
1facf9fc 7812+
dece6358
AM
7813+ file = kio->ki_filp;
7814+ dentry = file->f_dentry;
7815+ sb = dentry->d_sb;
7816+ si_read_lock(sb, AuLock_FLUSH);
7817+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
7818+ if (unlikely(err))
7819+ goto out;
1facf9fc 7820+
dece6358
AM
7821+ err = -ENOSYS;
7822+ h_file = au_h_fptr(file, au_fbstart(file));
7823+ if (h_file->f_op && h_file->f_op->aio_read) {
7824+ err = security_file_permission(h_file, MAY_READ);
7825+ if (unlikely(err))
7826+ goto out_unlock;
7827+ if (!is_sync_kiocb(kio)) {
7828+ get_file(h_file);
7829+ fput(file);
7830+ }
7831+ kio->ki_filp = h_file;
7832+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
7833+ /* todo: necessary? */
7834+ /* file->f_ra = h_file->f_ra; */
7835+ fsstack_copy_attr_atime(dentry->d_inode,
7836+ h_file->f_dentry->d_inode);
7837+ } else
7838+ /* currently there is no such fs */
7839+ WARN_ON_ONCE(h_file->f_op && h_file->f_op->read);
1facf9fc 7840+
dece6358
AM
7841+ out_unlock:
7842+ di_read_unlock(dentry, AuLock_IR);
7843+ fi_read_unlock(file);
7844+ out:
7845+ si_read_unlock(sb);
7846+ return err;
7847+}
1facf9fc 7848+
dece6358
AM
7849+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
7850+ unsigned long nv, loff_t pos)
1facf9fc 7851+{
dece6358
AM
7852+ ssize_t err;
7853+ aufs_bindex_t bstart;
7854+ struct au_pin pin;
7855+ struct dentry *dentry;
7856+ struct inode *inode;
7857+ struct super_block *sb;
7858+ struct file *file, *h_file;
1facf9fc 7859+
dece6358
AM
7860+ file = kio->ki_filp;
7861+ dentry = file->f_dentry;
7862+ sb = dentry->d_sb;
7863+ inode = dentry->d_inode;
7864+ mutex_lock(&inode->i_mutex);
7865+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 7866+
dece6358
AM
7867+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
7868+ if (unlikely(err))
7869+ goto out;
1facf9fc 7870+
dece6358
AM
7871+ err = au_ready_to_write(file, -1, &pin);
7872+ di_downgrade_lock(dentry, AuLock_IR);
7873+ if (unlikely(err))
7874+ goto out_unlock;
1facf9fc 7875+
dece6358
AM
7876+ err = -ENOSYS;
7877+ bstart = au_fbstart(file);
7878+ h_file = au_h_fptr(file, bstart);
7879+ au_unpin(&pin);
7880+ if (h_file->f_op && h_file->f_op->aio_write) {
7881+ err = security_file_permission(h_file, MAY_WRITE);
7882+ if (unlikely(err))
7883+ goto out_unlock;
7884+ if (!is_sync_kiocb(kio)) {
7885+ get_file(h_file);
7886+ fput(file);
7887+ }
7888+ kio->ki_filp = h_file;
7889+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
7890+ au_cpup_attr_timesizes(inode);
7891+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
7892+ } else
7893+ /* currently there is no such fs */
7894+ WARN_ON_ONCE(h_file->f_op && h_file->f_op->write);
1facf9fc 7895+
dece6358
AM
7896+ out_unlock:
7897+ di_read_unlock(dentry, AuLock_IR);
7898+ fi_write_unlock(file);
7899+ out:
7900+ si_read_unlock(sb);
7901+ mutex_unlock(&inode->i_mutex);
7902+ return err;
1facf9fc 7903+}
7904+
dece6358
AM
7905+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
7906+ struct pipe_inode_info *pipe, size_t len,
7907+ unsigned int flags)
1facf9fc 7908+{
dece6358
AM
7909+ ssize_t err;
7910+ struct file *h_file;
7911+ struct dentry *dentry;
7912+ struct super_block *sb;
1facf9fc 7913+
dece6358
AM
7914+ dentry = file->f_dentry;
7915+ sb = dentry->d_sb;
7916+ si_read_lock(sb, AuLock_FLUSH);
7917+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
7918+ if (unlikely(err))
7919+ goto out;
1facf9fc 7920+
dece6358
AM
7921+ err = -EINVAL;
7922+ h_file = au_h_fptr(file, au_fbstart(file));
7923+ if (au_test_loopback_kthread()) {
7924+ file->f_mapping = h_file->f_mapping;
7925+ smp_mb(); /* unnecessary? */
7926+ }
7927+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
7928+ /* todo: necessasry? */
7929+ /* file->f_ra = h_file->f_ra; */
7930+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 7931+
dece6358
AM
7932+ di_read_unlock(dentry, AuLock_IR);
7933+ fi_read_unlock(file);
1facf9fc 7934+
dece6358
AM
7935+ out:
7936+ si_read_unlock(sb);
7937+ return err;
1facf9fc 7938+}
7939+
dece6358
AM
7940+static ssize_t
7941+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
7942+ size_t len, unsigned int flags)
1facf9fc 7943+{
dece6358
AM
7944+ ssize_t err;
7945+ struct au_pin pin;
7946+ struct dentry *dentry;
7947+ struct inode *inode;
7948+ struct super_block *sb;
7949+ struct file *h_file;
1facf9fc 7950+
dece6358
AM
7951+ dentry = file->f_dentry;
7952+ inode = dentry->d_inode;
7953+ mutex_lock(&inode->i_mutex);
7954+ sb = dentry->d_sb;
7955+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 7956+
dece6358
AM
7957+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
7958+ if (unlikely(err))
7959+ goto out;
1facf9fc 7960+
dece6358
AM
7961+ err = au_ready_to_write(file, -1, &pin);
7962+ di_downgrade_lock(dentry, AuLock_IR);
7963+ if (unlikely(err))
7964+ goto out_unlock;
1facf9fc 7965+
dece6358
AM
7966+ h_file = au_h_fptr(file, au_fbstart(file));
7967+ au_unpin(&pin);
7968+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
7969+ au_cpup_attr_timesizes(inode);
7970+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 7971+
dece6358
AM
7972+ out_unlock:
7973+ di_read_unlock(dentry, AuLock_IR);
7974+ fi_write_unlock(file);
7975+ out:
7976+ si_read_unlock(sb);
7977+ mutex_unlock(&inode->i_mutex);
7978+ return err;
1facf9fc 7979+}
7980+
dece6358
AM
7981+/* ---------------------------------------------------------------------- */
7982+
7983+static struct file *au_safe_file(struct vm_area_struct *vma)
1facf9fc 7984+{
dece6358 7985+ struct file *file;
1facf9fc 7986+
dece6358
AM
7987+ file = vma->vm_file;
7988+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
7989+ return file;
7990+ return NULL;
1facf9fc 7991+}
7992+
dece6358 7993+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 7994+{
dece6358
AM
7995+ vma->vm_file = file;
7996+ /* smp_mb(); */ /* flush vm_file */
1facf9fc 7997+}
7998+
dece6358 7999+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 8000+{
dece6358
AM
8001+ int err;
8002+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8003+ struct file *file, *h_file;
1facf9fc 8004+ struct au_finfo *finfo;
1facf9fc 8005+
dece6358
AM
8006+ /* todo: non-robr mode, user vm_file as it is? */
8007+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8008+
dece6358 8009+ /* do not revalidate, no si lock */
1facf9fc 8010+ finfo = au_fi(file);
dece6358
AM
8011+ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
8012+ AuDebugOn(!h_file || !au_test_mmapped(file));
8013+
8014+ fi_write_lock(file);
8015+ vma->vm_file = h_file;
8016+ err = finfo->fi_h_vm_ops->fault(vma, vmf);
8017+ /* todo: necessary? */
8018+ /* file->f_ra = h_file->f_ra; */
8019+ au_reset_file(vma, file);
1facf9fc 8020+ fi_write_unlock(file);
dece6358
AM
8021+#if 0 /* def CONFIG_SMP */
8022+ /* wake_up_nr(&wq, online_cpu - 1); */
8023+ wake_up_all(&wq);
8024+#else
8025+ wake_up(&wq);
8026+#endif
8027+
8028+ return err;
1facf9fc 8029+}
8030+
dece6358 8031+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 8032+{
dece6358
AM
8033+ int err;
8034+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8035+ struct file *file, *h_file;
1facf9fc 8036+ struct au_finfo *finfo;
1facf9fc 8037+
dece6358 8038+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8039+
dece6358
AM
8040+ finfo = au_fi(file);
8041+ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
8042+ AuDebugOn(!h_file || !au_test_mmapped(file));
1facf9fc 8043+
dece6358
AM
8044+ fi_write_lock(file);
8045+ vma->vm_file = h_file;
8046+ err = finfo->fi_h_vm_ops->page_mkwrite(vma, vmf);
8047+ au_reset_file(vma, file);
8048+ fi_write_unlock(file);
8049+ wake_up(&wq);
1facf9fc 8050+
dece6358 8051+ return err;
1facf9fc 8052+}
8053+
dece6358 8054+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 8055+{
dece6358
AM
8056+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8057+ struct file *file, *h_file;
8058+ struct au_finfo *finfo;
1facf9fc 8059+
dece6358 8060+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8061+
dece6358
AM
8062+ finfo = au_fi(file);
8063+ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
8064+ AuDebugOn(!h_file || !au_test_mmapped(file));
8065+
8066+ fi_write_lock(file);
8067+ vma->vm_file = h_file;
8068+ finfo->fi_h_vm_ops->close(vma);
8069+ au_reset_file(vma, file);
8070+ fi_write_unlock(file);
8071+ wake_up(&wq);
1facf9fc 8072+}
1facf9fc 8073+
dece6358
AM
8074+static struct vm_operations_struct aufs_vm_ops = {
8075+ /* .close and .page_mkwrite are not set by default */
8076+ .fault = aufs_fault,
8077+};
1facf9fc 8078+
dece6358 8079+/* ---------------------------------------------------------------------- */
1facf9fc 8080+
dece6358
AM
8081+static struct vm_operations_struct *au_vm_ops(struct file *h_file,
8082+ struct vm_area_struct *vma)
8083+{
8084+ struct vm_operations_struct *vm_ops;
8085+ int err;
1facf9fc 8086+
dece6358
AM
8087+ vm_ops = ERR_PTR(-ENODEV);
8088+ if (!h_file->f_op || !h_file->f_op->mmap)
8089+ goto out;
1facf9fc 8090+
dece6358
AM
8091+ err = h_file->f_op->mmap(h_file, vma);
8092+ vm_ops = ERR_PTR(err);
8093+ if (unlikely(err))
8094+ goto out;
1facf9fc 8095+
dece6358
AM
8096+ vm_ops = vma->vm_ops;
8097+ err = do_munmap(current->mm, vma->vm_start,
8098+ vma->vm_end - vma->vm_start);
8099+ if (unlikely(err)) {
8100+ AuIOErr("failed internal unmapping %.*s, %d\n",
8101+ AuDLNPair(h_file->f_dentry), err);
8102+ vm_ops = ERR_PTR(-EIO);
8103+ }
1facf9fc 8104+
dece6358
AM
8105+ out:
8106+ return vm_ops;
1facf9fc 8107+}
8108+
dece6358 8109+static int au_custom_vm_ops(struct au_finfo *finfo, struct vm_area_struct *vma)
1facf9fc 8110+{
dece6358
AM
8111+ int err;
8112+ struct vm_operations_struct *h_ops;
1facf9fc 8113+
dece6358
AM
8114+ err = 0;
8115+ h_ops = finfo->fi_h_vm_ops;
8116+ AuDebugOn(!h_ops);
8117+ if ((!h_ops->page_mkwrite && !h_ops->close)
8118+ || finfo->fi_vm_ops)
8119+ goto out;
1facf9fc 8120+
dece6358
AM
8121+ err = -ENOMEM;
8122+ finfo->fi_vm_ops = kmemdup(&aufs_vm_ops, sizeof(aufs_vm_ops), GFP_NOFS);
8123+ if (unlikely(!finfo->fi_vm_ops))
8124+ goto out;
1facf9fc 8125+
dece6358
AM
8126+ err = 0;
8127+ if (h_ops->page_mkwrite)
8128+ finfo->fi_vm_ops->page_mkwrite = aufs_page_mkwrite;
8129+ if (h_ops->close)
8130+ finfo->fi_vm_ops->close = aufs_vm_close;
1facf9fc 8131+
dece6358 8132+ vma->vm_ops = finfo->fi_vm_ops;
1facf9fc 8133+
dece6358
AM
8134+ out:
8135+ return err;
1facf9fc 8136+}
8137+
dece6358 8138+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
1facf9fc 8139+{
dece6358
AM
8140+ int err;
8141+ unsigned char wlock, mmapped;
8142+ struct dentry *dentry;
8143+ struct super_block *sb;
8144+ struct file *h_file;
8145+ struct vm_operations_struct *vm_ops;
1facf9fc 8146+
dece6358
AM
8147+ dentry = file->f_dentry;
8148+ mmapped = !!au_test_mmapped(file); /* can be harmless race condition */
8149+ wlock = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
8150+ sb = dentry->d_sb;
8151+ si_read_lock(sb, AuLock_FLUSH);
8152+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped);
8153+ if (unlikely(err))
8154+ goto out;
1facf9fc 8155+
dece6358
AM
8156+ if (wlock) {
8157+ struct au_pin pin;
1facf9fc 8158+
dece6358
AM
8159+ err = au_ready_to_write(file, -1, &pin);
8160+ di_downgrade_lock(dentry, AuLock_IR);
8161+ if (unlikely(err))
8162+ goto out_unlock;
8163+ au_unpin(&pin);
8164+ } else if (!mmapped)
8165+ di_downgrade_lock(dentry, AuLock_IR);
1facf9fc 8166+
dece6358
AM
8167+ h_file = au_h_fptr(file, au_fbstart(file));
8168+ if (au_test_fs_bad_mapping(h_file->f_dentry->d_sb)) {
8169+ /*
8170+ * by this assignment, f_mapping will differs from aufs inode
8171+ * i_mapping.
8172+ * if someone else mixes the use of f_dentry->d_inode and
8173+ * f_mapping->host, then a problem may arise.
8174+ */
8175+ file->f_mapping = h_file->f_mapping;
8176+ }
1facf9fc 8177+
dece6358
AM
8178+ vm_ops = NULL;
8179+ if (!mmapped) {
8180+ vm_ops = au_vm_ops(h_file, vma);
8181+ err = PTR_ERR(vm_ops);
8182+ if (IS_ERR(vm_ops))
8183+ goto out_unlock;
8184+ }
1facf9fc 8185+
dece6358
AM
8186+ /*
8187+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
8188+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
8189+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
8190+ * both of the aufs file and the lower file is deny_write_access()-ed.
8191+ * finally I hope we can skip handlling MAP_DENYWRITE here.
8192+ */
8193+ err = generic_file_mmap(file, vma);
8194+ if (unlikely(err))
8195+ goto out_unlock;
1facf9fc 8196+
dece6358
AM
8197+ vma->vm_ops = &aufs_vm_ops;
8198+ /* test again */
8199+ if (!au_test_mmapped(file))
8200+ au_fi(file)->fi_h_vm_ops = vm_ops;
1facf9fc 8201+
dece6358
AM
8202+ err = au_custom_vm_ops(au_fi(file), vma);
8203+ if (unlikely(err))
8204+ goto out_unlock;
1facf9fc 8205+
dece6358
AM
8206+ vfsub_file_accessed(h_file);
8207+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 8208+
dece6358
AM
8209+ out_unlock:
8210+ di_read_unlock(dentry, AuLock_IR);
8211+ if (!wlock && mmapped)
8212+ fi_read_unlock(file);
8213+ else
8214+ fi_write_unlock(file);
8215+ out:
8216+ si_read_unlock(sb);
8217+ return err;
1facf9fc 8218+}
8219+
dece6358 8220+/* ---------------------------------------------------------------------- */
1facf9fc 8221+
dece6358
AM
8222+static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
8223+ int datasync)
1facf9fc 8224+{
dece6358
AM
8225+ int err;
8226+ struct au_pin pin;
8227+ struct inode *inode;
8228+ struct file *h_file;
8229+ struct super_block *sb;
1facf9fc 8230+
dece6358
AM
8231+ inode = dentry->d_inode;
8232+ IMustLock(file->f_mapping->host);
8233+ if (inode != file->f_mapping->host) {
8234+ mutex_unlock(&file->f_mapping->host->i_mutex);
8235+ mutex_lock(&inode->i_mutex);
8236+ }
8237+ IMustLock(inode);
1facf9fc 8238+
dece6358
AM
8239+ sb = dentry->d_sb;
8240+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 8241+
dece6358
AM
8242+ err = 0; /* -EBADF; */ /* posix? */
8243+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
8244+ goto out;
8245+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8246+ if (unlikely(err))
8247+ goto out;
8248+
8249+ err = au_ready_to_write(file, -1, &pin);
8250+ di_downgrade_lock(dentry, AuLock_IR);
8251+ if (unlikely(err))
8252+ goto out_unlock;
8253+ au_unpin(&pin);
8254+
8255+ err = -EINVAL;
8256+ h_file = au_h_fptr(file, au_fbstart(file));
8257+ if (h_file->f_op && h_file->f_op->fsync) {
8258+ struct dentry *h_d;
8259+ struct mutex *h_mtx;
8260+
8261+ /*
8262+ * no filemap_fdatawrite() since aufs file has no its own
8263+ * mapping, but dir.
8264+ */
8265+ h_d = h_file->f_dentry;
8266+ h_mtx = &h_d->d_inode->i_mutex;
8267+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
8268+ err = h_file->f_op->fsync(h_file, h_d, datasync);
8269+ if (!err)
8270+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
8271+ /*ignore*/
8272+ au_cpup_attr_timesizes(inode);
8273+ mutex_unlock(h_mtx);
8274+ }
8275+
8276+ out_unlock:
8277+ di_read_unlock(dentry, AuLock_IR);
8278+ fi_write_unlock(file);
8279+ out:
8280+ si_read_unlock(sb);
8281+ if (inode != file->f_mapping->host) {
8282+ mutex_unlock(&inode->i_mutex);
8283+ mutex_lock(&file->f_mapping->host->i_mutex);
8284+ }
8285+ return err;
8286+}
8287+
8288+/* no one supports this operation, currently */
8289+#if 0
8290+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
1facf9fc 8291+{
dece6358
AM
8292+ int err;
8293+ struct au_pin pin;
8294+ struct dentry *dentry;
8295+ struct inode *inode;
8296+ struct file *file, *h_file;
8297+ struct super_block *sb;
8298+
8299+ file = kio->ki_filp;
8300+ dentry = file->f_dentry;
8301+ inode = dentry->d_inode;
8302+ mutex_lock(&inode->i_mutex);
8303+
8304+ sb = dentry->d_sb;
8305+ si_read_lock(sb, AuLock_FLUSH);
8306+
8307+ err = 0; /* -EBADF; */ /* posix? */
8308+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
8309+ goto out;
8310+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8311+ if (unlikely(err))
8312+ goto out;
8313+
8314+ err = au_ready_to_write(file, -1, &pin);
8315+ di_downgrade_lock(dentry, AuLock_IR);
8316+ if (unlikely(err))
8317+ goto out_unlock;
8318+ au_unpin(&pin);
8319+
8320+ err = -ENOSYS;
8321+ h_file = au_h_fptr(file, au_fbstart(file));
8322+ if (h_file->f_op && h_file->f_op->aio_fsync) {
8323+ struct dentry *h_d;
8324+ struct mutex *h_mtx;
8325+
8326+ h_d = h_file->f_dentry;
8327+ h_mtx = &h_d->d_inode->i_mutex;
8328+ if (!is_sync_kiocb(kio)) {
8329+ get_file(h_file);
8330+ fput(file);
8331+ }
8332+ kio->ki_filp = h_file;
8333+ err = h_file->f_op->aio_fsync(kio, datasync);
8334+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
8335+ if (!err)
8336+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
8337+ /*ignore*/
8338+ au_cpup_attr_timesizes(inode);
8339+ mutex_unlock(h_mtx);
8340+ }
8341+
8342+ out_unlock:
8343+ di_read_unlock(dentry, AuLock_IR);
8344+ fi_write_unlock(file);
8345+ out:
8346+ si_read_unlock(sb);
8347+ mutex_unlock(&inode->i_mutex);
8348+ return err;
8349+}
1facf9fc 8350+#endif
dece6358
AM
8351+
8352+static int aufs_fasync(int fd, struct file *file, int flag)
8353+{
8354+ int err;
8355+ struct file *h_file;
8356+ struct dentry *dentry;
8357+ struct super_block *sb;
8358+
8359+ dentry = file->f_dentry;
8360+ sb = dentry->d_sb;
8361+ si_read_lock(sb, AuLock_FLUSH);
8362+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
8363+ if (unlikely(err))
8364+ goto out;
8365+
8366+ h_file = au_h_fptr(file, au_fbstart(file));
8367+ if (h_file->f_op && h_file->f_op->fasync)
8368+ err = h_file->f_op->fasync(fd, h_file, flag);
8369+
8370+ di_read_unlock(dentry, AuLock_IR);
8371+ fi_read_unlock(file);
8372+
8373+ out:
8374+ si_read_unlock(sb);
8375+ return err;
1facf9fc 8376+}
8377+
dece6358
AM
8378+/* ---------------------------------------------------------------------- */
8379+
8380+/* no one supports this operation, currently */
8381+#if 0
8382+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
8383+ size_t len, loff_t *pos , int more)
1facf9fc 8384+{
1facf9fc 8385+}
dece6358 8386+#endif
1facf9fc 8387+
dece6358
AM
8388+/* ---------------------------------------------------------------------- */
8389+
8390+const struct file_operations aufs_file_fop = {
8391+ /*
8392+ * while generic_file_llseek/_unlocked() don't use BKL,
8393+ * don't use it since it operates file->f_mapping->host.
8394+ * in aufs, it may be a real file and may confuse users by UDBA.
8395+ */
8396+ /* .llseek = generic_file_llseek, */
8397+
8398+ .read = aufs_read,
8399+ .write = aufs_write,
8400+ .aio_read = aufs_aio_read,
8401+ .aio_write = aufs_aio_write,
8402+#ifdef CONFIG_AUFS_POLL
8403+ .poll = aufs_poll,
8404+#endif
8405+ .mmap = aufs_mmap,
8406+ .open = aufs_open_nondir,
8407+ .flush = aufs_flush,
8408+ .release = aufs_release_nondir,
8409+ .fsync = aufs_fsync_nondir,
8410+ /* .aio_fsync = aufs_aio_fsync_nondir, */
8411+ .fasync = aufs_fasync,
8412+ /* .sendpage = aufs_sendpage, */
8413+ .splice_write = aufs_splice_write,
8414+ .splice_read = aufs_splice_read,
8415+#if 0
8416+ .aio_splice_write = aufs_aio_splice_write,
8417+ .aio_splice_read = aufs_aio_splice_read
8418+#endif
8419+};
8420diff -urN linux-2.6.30.org/fs/aufs/fstype.h linux-2.6.30/fs/aufs/fstype.h
8421--- linux-2.6.30.org/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
8422+++ linux-2.6.30/fs/aufs/fstype.h 2009-07-21 08:54:19.000000000 +0200
8423@@ -0,0 +1,474 @@
8424+/*
8425+ * Copyright (C) 2005-2009 Junjiro R. Okajima
8426+ *
8427+ * This program, aufs is free software; you can redistribute it and/or modify
8428+ * it under the terms of the GNU General Public License as published by
8429+ * the Free Software Foundation; either version 2 of the License, or
8430+ * (at your option) any later version.
8431+ *
8432+ * This program is distributed in the hope that it will be useful,
8433+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8434+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8435+ * GNU General Public License for more details.
8436+ *
8437+ * You should have received a copy of the GNU General Public License
8438+ * along with this program; if not, write to the Free Software
8439+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8440+ */
8441+
8442+/*
8443+ * judging filesystem type
8444+ */
8445+
8446+#ifndef __AUFS_FSTYPE_H__
8447+#define __AUFS_FSTYPE_H__
8448+
8449+#ifdef __KERNEL__
8450+
8451+#include <linux/cramfs_fs.h>
8452+#include <linux/fs.h>
8453+#include <linux/magic.h>
8454+#include <linux/romfs_fs.h>
8455+#include <linux/aufs_type.h>
8456+
8457+static inline int au_test_aufs(struct super_block *sb)
1facf9fc 8458+{
dece6358 8459+ return sb->s_magic == AUFS_SUPER_MAGIC;
1facf9fc 8460+}
8461+
dece6358 8462+static inline const char *au_sbtype(struct super_block *sb)
1facf9fc 8463+{
dece6358
AM
8464+ return sb->s_type->name;
8465+}
8466+
8467+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
8468+{
8469+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
8470+ return sb->s_magic == ROMFS_MAGIC;
1facf9fc 8471+#else
8472+ return 0;
8473+#endif
8474+}
8475+
dece6358 8476+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
1facf9fc 8477+{
dece6358
AM
8478+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
8479+ return sb->s_magic == ISOFS_SUPER_MAGIC;
1facf9fc 8480+#else
8481+ return 0;
8482+#endif
8483+}
8484+
dece6358 8485+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
1facf9fc 8486+{
dece6358
AM
8487+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
8488+ return sb->s_magic == CRAMFS_MAGIC;
8489+#endif
8490+ return 0;
8491+}
8492+
8493+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
8494+{
8495+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
8496+ return sb->s_magic == NFS_SUPER_MAGIC;
1facf9fc 8497+#else
8498+ return 0;
8499+#endif
8500+}
8501+
dece6358 8502+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
1facf9fc 8503+{
dece6358
AM
8504+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
8505+ return sb->s_magic == FUSE_SUPER_MAGIC;
1facf9fc 8506+#else
8507+ return 0;
8508+#endif
8509+}
8510+
dece6358 8511+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
1facf9fc 8512+{
dece6358
AM
8513+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
8514+ return sb->s_magic == XFS_SB_MAGIC;
1facf9fc 8515+#else
8516+ return 0;
8517+#endif
8518+}
8519+
dece6358 8520+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
1facf9fc 8521+{
dece6358
AM
8522+#ifdef CONFIG_TMPFS
8523+ return sb->s_magic == TMPFS_MAGIC;
8524+#else
8525+ return 0;
1facf9fc 8526+#endif
1facf9fc 8527+}
8528+
dece6358
AM
8529+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
8530+{
8531+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
8532+ return !strcmp(au_sbtype(sb), "ecryptfs");
8533+#else
8534+ return 0;
8535+#endif
8536+}
8537+
8538+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
8539+{
8540+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
8541+ return sb->s_magic == SMB_SUPER_MAGIC;
8542+#else
8543+ return 0;
8544+#endif
8545+}
8546+
8547+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
8548+{
8549+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
8550+ return sb->s_magic == OCFS2_SUPER_MAGIC;
8551+#else
8552+ return 0;
8553+#endif
8554+}
8555+
8556+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
8557+{
8558+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
8559+ return sb->s_magic == DLMFS_MAGIC;
8560+#else
8561+ return 0;
8562+#endif
8563+}
8564+
8565+static inline int au_test_coda(struct super_block *sb __maybe_unused)
8566+{
8567+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
8568+ return sb->s_magic == CODA_SUPER_MAGIC;
8569+#else
8570+ return 0;
8571+#endif
8572+}
8573+
8574+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
8575+{
8576+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
8577+ return sb->s_magic == V9FS_MAGIC;
8578+#else
8579+ return 0;
8580+#endif
8581+}
8582+
8583+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
8584+{
8585+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
8586+ return sb->s_magic == EXT4_SUPER_MAGIC;
8587+#else
8588+ return 0;
8589+#endif
8590+}
8591+
8592+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
8593+{
8594+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
8595+ return !strcmp(au_sbtype(sb), "sysv");
8596+#else
8597+ return 0;
8598+#endif
8599+}
8600+
8601+static inline int au_test_ramfs(struct super_block *sb)
8602+{
8603+ return sb->s_magic == RAMFS_MAGIC;
8604+}
8605+
8606+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
8607+{
8608+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
8609+ return sb->s_magic == UBIFS_SUPER_MAGIC;
8610+#else
8611+ return 0;
8612+#endif
8613+}
8614+
8615+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
8616+{
8617+#ifdef CONFIG_PROC_FS
8618+ return sb->s_magic == PROC_SUPER_MAGIC;
8619+#else
8620+ return 0;
8621+#endif
8622+}
8623+
8624+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
8625+{
8626+#ifdef CONFIG_SYSFS
8627+ return sb->s_magic == SYSFS_MAGIC;
8628+#else
8629+ return 0;
8630+#endif
8631+}
8632+
8633+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
8634+{
8635+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
8636+ return sb->s_magic == CONFIGFS_MAGIC;
8637+#else
8638+ return 0;
8639+#endif
8640+}
8641+
8642+static inline int au_test_minix(struct super_block *sb __maybe_unused)
8643+{
8644+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
8645+ return sb->s_magic == MINIX3_SUPER_MAGIC
8646+ || sb->s_magic == MINIX2_SUPER_MAGIC
8647+ || sb->s_magic == MINIX2_SUPER_MAGIC2
8648+ || sb->s_magic == MINIX_SUPER_MAGIC
8649+ || sb->s_magic == MINIX_SUPER_MAGIC2;
8650+#else
8651+ return 0;
8652+#endif
8653+}
8654+
8655+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
8656+{
8657+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
8658+ return sb->s_magic == CIFS_MAGIC_NUMBER;
8659+#else
8660+ return 0;
8661+#endif
8662+}
8663+
8664+static inline int au_test_fat(struct super_block *sb __maybe_unused)
8665+{
8666+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
8667+ return sb->s_magic == MSDOS_SUPER_MAGIC;
8668+#else
8669+ return 0;
8670+#endif
8671+}
8672+
8673+static inline int au_test_msdos(struct super_block *sb)
8674+{
8675+ return au_test_fat(sb);
8676+}
8677+
8678+static inline int au_test_vfat(struct super_block *sb)
8679+{
8680+ return au_test_fat(sb);
8681+}
8682+
8683+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
8684+{
8685+#ifdef CONFIG_SECURITYFS
8686+ return sb->s_magic == SECURITYFS_MAGIC;
8687+#else
8688+ return 0;
8689+#endif
8690+}
8691+
8692+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
8693+{
8694+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
8695+ return sb->s_magic == SQUASHFS_MAGIC;
8696+#else
8697+ return 0;
8698+#endif
8699+}
8700+
8701+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
8702+{
8703+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
8704+ return sb->s_magic == BTRFS_SUPER_MAGIC;
8705+#else
8706+ return 0;
8707+#endif
8708+}
8709+
8710+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
8711+{
8712+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
8713+ return sb->s_magic == XENFS_SUPER_MAGIC;
8714+#else
8715+ return 0;
8716+#endif
8717+}
8718+
8719+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
8720+{
8721+#ifdef CONFIG_DEBUG_FS
8722+ return sb->s_magic == DEBUGFS_MAGIC;
8723+#else
8724+ return 0;
8725+#endif
8726+}
8727+
8728+/* ---------------------------------------------------------------------- */
8729+/*
8730+ * they can't be an aufs branch.
8731+ */
8732+static inline int au_test_fs_unsuppoted(struct super_block *sb)
8733+{
8734+ return
8735+#ifndef CONFIG_AUFS_BR_RAMFS
8736+ au_test_ramfs(sb) ||
8737+#endif
8738+ au_test_procfs(sb)
8739+ || au_test_sysfs(sb)
8740+ || au_test_configfs(sb)
8741+ || au_test_debugfs(sb)
8742+ || au_test_securityfs(sb)
8743+ || au_test_xenfs(sb)
8744+ /* || !strcmp(au_sbtype(sb), "unionfs") */
8745+ || au_test_aufs(sb); /* will be supported in next version */
8746+}
8747+
8748+/*
8749+ * If the filesystem supports NFS-export, then it has to support NULL as
8750+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
8751+ * We can apply this principle when we handle a lower filesystem.
1facf9fc 8752+ */
8753+static inline int au_test_fs_null_nd(struct super_block *sb)
8754+{
8755+ return !!sb->s_export_op;
8756+}
8757+
8758+static inline int au_test_fs_remote(struct super_block *sb)
8759+{
8760+ return !au_test_tmpfs(sb)
8761+#ifdef CONFIG_AUFS_BR_RAMFS
8762+ && !au_test_ramfs(sb)
8763+#endif
8764+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
8765+}
8766+
8767+/* ---------------------------------------------------------------------- */
8768+
8769+/*
8770+ * Note: these functions (below) are created after reading ->getattr() in all
8771+ * filesystems under linux/fs. it means we have to do so in every update...
8772+ */
8773+
8774+/*
8775+ * some filesystems require getattr to refresh the inode attributes before
8776+ * referencing.
8777+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
8778+ * and leave the work for d_revalidate()
8779+ */
8780+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
8781+{
8782+ return au_test_nfs(sb)
8783+ || au_test_fuse(sb)
8784+ /* || au_test_smbfs(sb) */ /* untested */
8785+ /* || au_test_ocfs2(sb) */ /* untested */
8786+ /* || au_test_btrfs(sb) */ /* untested */
8787+ /* || au_test_coda(sb) */ /* untested */
8788+ /* || au_test_v9fs(sb) */ /* untested */
8789+ ;
8790+}
8791+
8792+/*
8793+ * filesystems which don't maintain i_size or i_blocks.
8794+ */
8795+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
8796+{
8797+ return au_test_xfs(sb)
8798+ /* || au_test_ext4(sb) */ /* untested */
8799+ /* || au_test_ocfs2(sb) */ /* untested */
8800+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
8801+ /* || au_test_sysv(sb) */ /* untested */
8802+ /* || au_test_ubifs(sb) */ /* untested */
8803+ /* || au_test_minix(sb) */ /* untested */
8804+ ;
8805+}
8806+
8807+/*
8808+ * filesystems which don't store the correct value in some of their inode
8809+ * attributes.
8810+ */
8811+static inline int au_test_fs_bad_iattr(struct super_block *sb)
8812+{
8813+ return au_test_fs_bad_iattr_size(sb)
8814+ /* || au_test_cifs(sb) */ /* untested */
8815+ || au_test_fat(sb)
8816+ || au_test_msdos(sb)
8817+ || au_test_vfat(sb);
8818+}
8819+
8820+/* they don't check i_nlink in link(2) */
8821+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
8822+{
8823+ return au_test_tmpfs(sb)
8824+#ifdef CONFIG_AUFS_BR_RAMFS
8825+ || au_test_ramfs(sb)
8826+#endif
dece6358 8827+ || au_test_ubifs(sb);
1facf9fc 8828+}
8829+
8830+/*
8831+ * filesystems which sets S_NOATIME and S_NOCMTIME.
8832+ */
8833+static inline int au_test_fs_notime(struct super_block *sb)
8834+{
8835+ return au_test_nfs(sb)
8836+ || au_test_fuse(sb)
dece6358 8837+ || au_test_ubifs(sb)
1facf9fc 8838+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 8839+ ;
8840+}
8841+
8842+/*
8843+ * filesystems which requires replacing i_mapping.
8844+ */
8845+static inline int au_test_fs_bad_mapping(struct super_block *sb)
8846+{
dece6358
AM
8847+ return au_test_fuse(sb)
8848+ || au_test_ubifs(sb);
1facf9fc 8849+}
8850+
8851+/* temporary support for i#1 in cramfs */
8852+static inline int au_test_fs_unique_ino(struct inode *inode)
8853+{
8854+ if (au_test_cramfs(inode->i_sb))
8855+ return inode->i_ino != 1;
8856+ return 1;
8857+}
8858+
8859+/* ---------------------------------------------------------------------- */
8860+
8861+/*
8862+ * the filesystem where the xino files placed must support i/o after unlink and
8863+ * maintain i_size and i_blocks.
8864+ */
8865+static inline int au_test_fs_bad_xino(struct super_block *sb)
8866+{
8867+ return au_test_fs_remote(sb)
8868+ || au_test_fs_bad_iattr_size(sb)
8869+#ifdef CONFIG_AUFS_BR_RAMFS
8870+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
8871+#else
8872+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
8873+#endif
8874+ /* don't want unnecessary work for xino */
8875+ || au_test_aufs(sb)
8876+ || au_test_ecryptfs(sb);
8877+}
8878+
8879+static inline int au_test_fs_trunc_xino(struct super_block *sb)
8880+{
8881+ return au_test_tmpfs(sb)
8882+ || au_test_ramfs(sb);
8883+}
8884+
8885+/*
8886+ * test if the @sb is real-readonly.
8887+ */
8888+static inline int au_test_fs_rr(struct super_block *sb)
8889+{
8890+ return au_test_squashfs(sb)
8891+ || au_test_iso9660(sb)
8892+ || au_test_cramfs(sb)
8893+ || au_test_romfs(sb);
8894+}
8895+
8896+#endif /* __KERNEL__ */
8897+#endif /* __AUFS_FSTYPE_H__ */
dece6358
AM
8898diff -urN linux-2.6.30.org/fs/aufs/hinotify.c linux-2.6.30/fs/aufs/hinotify.c
8899--- linux-2.6.30.org/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
8900+++ linux-2.6.30/fs/aufs/hinotify.c 2009-07-21 08:54:19.000000000 +0200
8901@@ -0,0 +1,755 @@
1facf9fc 8902+/*
8903+ * Copyright (C) 2005-2009 Junjiro R. Okajima
8904+ *
8905+ * This program, aufs is free software; you can redistribute it and/or modify
8906+ * it under the terms of the GNU General Public License as published by
8907+ * the Free Software Foundation; either version 2 of the License, or
8908+ * (at your option) any later version.
dece6358
AM
8909+ *
8910+ * This program is distributed in the hope that it will be useful,
8911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8913+ * GNU General Public License for more details.
8914+ *
8915+ * You should have received a copy of the GNU General Public License
8916+ * along with this program; if not, write to the Free Software
8917+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8918+ */
8919+
8920+/*
8921+ * inotify for the lower directories
8922+ */
8923+
8924+#include "aufs.h"
8925+
8926+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
8927+static struct inotify_handle *au_hin_handle;
8928+
8929+AuCacheFuncs(hinotify, HINOTIFY);
8930+
8931+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
8932+ struct inode *h_inode)
8933+{
8934+ int err;
8935+ struct au_hinotify *hin;
8936+ s32 wd;
8937+
8938+ err = -ENOMEM;
8939+ hin = au_cache_alloc_hinotify();
8940+ if (hin) {
8941+ AuDebugOn(hinode->hi_notify);
8942+ hinode->hi_notify = hin;
8943+ hin->hin_aufs_inode = inode;
8944+
8945+ inotify_init_watch(&hin->hin_watch);
8946+ wd = inotify_add_watch(au_hin_handle, &hin->hin_watch, h_inode,
8947+ AuHinMask);
8948+ if (wd >= 0)
8949+ return 0; /* success */
8950+
8951+ err = wd;
8952+ put_inotify_watch(&hin->hin_watch);
8953+ au_cache_free_hinotify(hin);
8954+ hinode->hi_notify = NULL;
8955+ }
8956+
8957+ return err;
8958+}
8959+
8960+void au_hin_free(struct au_hinode *hinode)
8961+{
8962+ int err;
8963+ struct au_hinotify *hin;
8964+
8965+ hin = hinode->hi_notify;
8966+ if (hin) {
8967+ err = 0;
8968+ if (atomic_read(&hin->hin_watch.count))
8969+ err = inotify_rm_watch(au_hin_handle, &hin->hin_watch);
8970+ if (unlikely(err))
8971+ /* it means the watch is already removed */
8972+ AuWarn("failed inotify_rm_watch() %d\n", err);
8973+ au_cache_free_hinotify(hin);
8974+ hinode->hi_notify = NULL;
8975+ }
8976+}
8977+
8978+/* ---------------------------------------------------------------------- */
8979+
8980+void au_hin_ctl(struct au_hinode *hinode, int do_set)
8981+{
8982+ struct inode *h_inode;
8983+ struct inotify_watch *watch;
8984+
8985+ if (!hinode->hi_notify)
8986+ return;
8987+
8988+ h_inode = hinode->hi_inode;
8989+ IMustLock(h_inode);
8990+
8991+ /* todo: try inotify_find_update_watch()? */
8992+ watch = &hinode->hi_notify->hin_watch;
8993+ mutex_lock(&h_inode->inotify_mutex);
8994+ /* mutex_lock(&watch->ih->mutex); */
8995+ if (do_set) {
8996+ AuDebugOn(watch->mask & AuHinMask);
8997+ watch->mask |= AuHinMask;
8998+ } else {
8999+ AuDebugOn(!(watch->mask & AuHinMask));
9000+ watch->mask &= ~AuHinMask;
9001+ }
9002+ /* mutex_unlock(&watch->ih->mutex); */
9003+ mutex_unlock(&h_inode->inotify_mutex);
9004+}
9005+
9006+void au_reset_hinotify(struct inode *inode, unsigned int flags)
9007+{
9008+ aufs_bindex_t bindex, bend;
9009+ struct inode *hi;
9010+ struct dentry *iwhdentry;
9011+
9012+ bend = au_ibend(inode);
9013+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
9014+ hi = au_h_iptr(inode, bindex);
9015+ if (!hi)
9016+ continue;
9017+
9018+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
9019+ iwhdentry = au_hi_wh(inode, bindex);
9020+ if (iwhdentry)
9021+ dget(iwhdentry);
9022+ au_igrab(hi);
9023+ au_set_h_iptr(inode, bindex, NULL, 0);
9024+ au_set_h_iptr(inode, bindex, au_igrab(hi),
9025+ flags & ~AuHi_XINO);
9026+ iput(hi);
9027+ dput(iwhdentry);
9028+ /* mutex_unlock(&hi->i_mutex); */
9029+ }
9030+}
9031+
9032+/* ---------------------------------------------------------------------- */
9033+
9034+static int hin_xino(struct inode *inode, struct inode *h_inode)
9035+{
9036+ int err;
9037+ aufs_bindex_t bindex, bend, bfound, bstart;
9038+ struct inode *h_i;
9039+
9040+ err = 0;
9041+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
9042+ AuWarn("branch root dir was changed\n");
9043+ goto out;
9044+ }
9045+
9046+ bfound = -1;
9047+ bend = au_ibend(inode);
9048+ bstart = au_ibstart(inode);
9049+#if 0 /* reserved for future use */
9050+ if (bindex == bend) {
9051+ /* keep this ino in rename case */
9052+ goto out;
9053+ }
9054+#endif
9055+ for (bindex = bstart; bindex <= bend; bindex++) {
9056+ if (au_h_iptr(inode, bindex) == h_inode) {
9057+ bfound = bindex;
9058+ break;
9059+ }
9060+ }
9061+ if (bfound < 0)
9062+ goto out;
9063+
9064+ for (bindex = bstart; bindex <= bend; bindex++) {
9065+ h_i = au_h_iptr(inode, bindex);
9066+ if (!h_i)
9067+ continue;
9068+
9069+ err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino, 0);
9070+ /* ignore this error */
9071+ /* bad action? */
9072+ }
9073+
9074+ /* children inode number will be broken */
9075+
9076+ out:
9077+ AuTraceErr(err);
9078+ return err;
9079+}
9080+
9081+static int hin_gen_tree(struct dentry *dentry)
9082+{
9083+ int err, i, j, ndentry;
9084+ struct au_dcsub_pages dpages;
9085+ struct au_dpage *dpage;
9086+ struct dentry **dentries;
9087+
9088+ err = au_dpages_init(&dpages, GFP_NOFS);
9089+ if (unlikely(err))
9090+ goto out;
9091+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
9092+ if (unlikely(err))
9093+ goto out_dpages;
9094+
9095+ for (i = 0; i < dpages.ndpage; i++) {
9096+ dpage = dpages.dpages + i;
9097+ dentries = dpage->dentries;
9098+ ndentry = dpage->ndentry;
9099+ for (j = 0; j < ndentry; j++) {
9100+ struct dentry *d;
9101+
9102+ d = dentries[j];
9103+ if (IS_ROOT(d))
9104+ continue;
9105+
9106+ d_drop(d);
9107+ au_digen_dec(d);
9108+ if (d->d_inode)
9109+ /* todo: reset children xino?
9110+ cached children only? */
9111+ au_iigen_dec(d->d_inode);
9112+ }
9113+ }
9114+
9115+ out_dpages:
9116+ au_dpages_free(&dpages);
9117+
9118+ /* discard children */
9119+ dentry_unhash(dentry);
9120+ dput(dentry);
9121+ out:
9122+ return err;
9123+}
9124+
9125+/*
9126+ * return 0 if processed.
9127+ */
9128+static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
9129+ const unsigned int isdir)
9130+{
9131+ int err;
9132+ struct dentry *d;
9133+ struct qstr *dname;
9134+
9135+ err = 1;
9136+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
9137+ AuWarn("branch root dir was changed\n");
9138+ err = 0;
9139+ goto out;
9140+ }
9141+
9142+ if (!isdir) {
9143+ AuDebugOn(!name);
9144+ au_iigen_dec(inode);
9145+ spin_lock(&dcache_lock);
9146+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
9147+ dname = &d->d_name;
9148+ if (dname->len != nlen
9149+ && memcmp(dname->name, name, nlen))
9150+ continue;
9151+ err = 0;
9152+ spin_lock(&d->d_lock);
9153+ __d_drop(d);
9154+ au_digen_dec(d);
9155+ spin_unlock(&d->d_lock);
9156+ break;
9157+ }
9158+ spin_unlock(&dcache_lock);
9159+ } else {
9160+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
9161+ d = d_find_alias(inode);
9162+ if (!d) {
9163+ au_iigen_dec(inode);
9164+ goto out;
9165+ }
9166+
9167+ dname = &d->d_name;
9168+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
9169+ err = hin_gen_tree(d);
9170+ dput(d);
9171+ }
9172+
9173+ out:
9174+ AuTraceErr(err);
9175+ return err;
9176+}
9177+
9178+static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
9179+{
9180+ int err;
9181+ struct inode *inode;
9182+
9183+ inode = dentry->d_inode;
9184+ if (IS_ROOT(dentry)
9185+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
9186+ ) {
9187+ AuWarn("branch root dir was changed\n");
9188+ return 0;
9189+ }
9190+
9191+ err = 0;
9192+ if (!isdir) {
9193+ d_drop(dentry);
9194+ au_digen_dec(dentry);
9195+ if (inode)
9196+ au_iigen_dec(inode);
9197+ } else {
9198+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
9199+ if (inode)
9200+ err = hin_gen_tree(dentry);
9201+ }
9202+
9203+ AuTraceErr(err);
9204+ return err;
9205+}
9206+
9207+/* ---------------------------------------------------------------------- */
9208+
9209+/* hinotify job flags */
9210+#define AuHinJob_XINO0 1
9211+#define AuHinJob_GEN (1 << 1)
9212+#define AuHinJob_DIRENT (1 << 2)
9213+#define AuHinJob_ISDIR (1 << 3)
9214+#define AuHinJob_TRYXINO0 (1 << 4)
9215+#define AuHinJob_MNTPNT (1 << 5)
9216+#define au_ftest_hinjob(flags, name) ((flags) & AuHinJob_##name)
9217+#define au_fset_hinjob(flags, name) { (flags) |= AuHinJob_##name; }
9218+#define au_fclr_hinjob(flags, name) { (flags) &= ~AuHinJob_##name; }
9219+
9220+struct hin_job_args {
9221+ unsigned int flags;
9222+ struct inode *inode, *h_inode, *dir, *h_dir;
9223+ struct dentry *dentry;
9224+ char *h_name;
9225+ int h_nlen;
9226+};
9227+
9228+static int hin_job(struct hin_job_args *a)
9229+{
9230+ const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
9231+
9232+ /* reset xino */
9233+ if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
9234+ hin_xino(a->inode, a->h_inode); /* ignore this error */
9235+
9236+ if (au_ftest_hinjob(a->flags, TRYXINO0)
9237+ && a->inode
9238+ && a->h_inode) {
9239+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
9240+ if (!a->h_inode->i_nlink)
9241+ hin_xino(a->inode, a->h_inode); /* ignore this error */
9242+ mutex_unlock(&a->h_inode->i_mutex);
9243+ }
9244+
9245+ /* make the generation obsolete */
9246+ if (au_ftest_hinjob(a->flags, GEN)) {
9247+ int err = -1;
9248+ if (a->inode)
9249+ err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
9250+ isdir);
9251+ if (err && a->dentry)
9252+ hin_gen_by_name(a->dentry, isdir);
9253+ /* ignore this error */
9254+ }
9255+
9256+ /* make dir entries obsolete */
9257+ if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
9258+ struct au_vdir *vdir;
9259+
9260+ vdir = au_ivdir(a->inode);
9261+ if (vdir)
9262+ vdir->vd_jiffy = 0;
9263+ /* IMustLock(a->inode); */
9264+ /* a->inode->i_version++; */
9265+ }
9266+
9267+ /* can do nothing but warn */
9268+ if (au_ftest_hinjob(a->flags, MNTPNT)
9269+ && a->dentry
9270+ && d_mountpoint(a->dentry))
9271+ AuWarn("mount-point %.*s is removed or renamed\n",
9272+ AuDLNPair(a->dentry));
9273+
9274+ return 0;
9275+}
9276+
9277+/* ---------------------------------------------------------------------- */
9278+
9279+static char *in_name(u32 mask)
9280+{
9281+#ifdef CONFIG_AUFS_DEBUG
9282+#define test_ret(flag) if (mask & flag) \
9283+ return #flag;
9284+ test_ret(IN_ACCESS);
9285+ test_ret(IN_MODIFY);
9286+ test_ret(IN_ATTRIB);
9287+ test_ret(IN_CLOSE_WRITE);
9288+ test_ret(IN_CLOSE_NOWRITE);
9289+ test_ret(IN_OPEN);
9290+ test_ret(IN_MOVED_FROM);
9291+ test_ret(IN_MOVED_TO);
9292+ test_ret(IN_CREATE);
9293+ test_ret(IN_DELETE);
9294+ test_ret(IN_DELETE_SELF);
9295+ test_ret(IN_MOVE_SELF);
9296+ test_ret(IN_UNMOUNT);
9297+ test_ret(IN_Q_OVERFLOW);
9298+ test_ret(IN_IGNORED);
9299+ return "";
9300+#undef test_ret
9301+#else
9302+ return "??";
9303+#endif
9304+}
9305+
9306+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
9307+ struct inode *dir)
9308+{
9309+ struct dentry *dentry, *d, *parent;
9310+ struct qstr *dname;
9311+
9312+ parent = d_find_alias(dir);
9313+ if (!parent)
9314+ return NULL;
9315+
9316+ dentry = NULL;
9317+ spin_lock(&dcache_lock);
9318+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
9319+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
9320+ dname = &d->d_name;
9321+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
9322+ continue;
9323+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
9324+ spin_lock(&d->d_lock);
9325+ __d_drop(d);
9326+ spin_unlock(&d->d_lock);
9327+ continue;
9328+ }
9329+
9330+ dentry = dget(d);
9331+ break;
9332+ }
9333+ spin_unlock(&dcache_lock);
9334+ dput(parent);
9335+
9336+ if (dentry)
9337+ di_write_lock_child(dentry);
9338+
9339+ return dentry;
9340+}
9341+
9342+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
9343+ aufs_bindex_t bindex, ino_t h_ino)
9344+{
9345+ struct inode *inode;
9346+ ino_t ino;
9347+ int err;
9348+
9349+ inode = NULL;
9350+ err = au_xino_read(sb, bindex, h_ino, &ino);
9351+ if (!err && ino)
9352+ inode = ilookup(sb, ino);
9353+ if (!inode)
9354+ goto out;
9355+
9356+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
9357+ AuWarn("wrong root branch\n");
9358+ iput(inode);
9359+ inode = NULL;
9360+ goto out;
9361+ }
9362+
9363+ ii_write_lock_child(inode);
9364+
9365+ out:
9366+ return inode;
9367+}
9368+
9369+enum { CHILD, PARENT };
9370+struct postproc_args {
9371+ struct inode *h_dir, *dir, *h_child_inode;
9372+ u32 mask;
9373+ unsigned int flags[2];
9374+ unsigned int h_child_nlen;
9375+ char h_child_name[];
9376+};
9377+
9378+static void postproc(void *_args)
9379+{
9380+ struct postproc_args *a = _args;
9381+ struct super_block *sb;
9382+ aufs_bindex_t bindex, bend, bfound;
9383+ unsigned char xino, try_iput;
9384+ int err;
9385+ struct inode *inode;
9386+ ino_t h_ino;
9387+ struct hin_job_args args;
9388+ struct dentry *dentry;
9389+ struct au_sbinfo *sbinfo;
9390+
9391+ AuDebugOn(!_args);
9392+ AuDebugOn(!a->h_dir);
9393+ AuDebugOn(!a->dir);
9394+ AuDebugOn(!a->mask);
9395+ AuDbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
9396+ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
9397+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
9398+
9399+ inode = NULL;
9400+ dentry = NULL;
9401+ /*
9402+ * do not lock a->dir->i_mutex here
9403+ * because of d_revalidate() may cause a deadlock.
9404+ */
9405+ sb = a->dir->i_sb;
9406+ AuDebugOn(!sb);
9407+ sbinfo = au_sbi(sb);
9408+ AuDebugOn(!sbinfo);
9409+ /* big aufs lock */
9410+ si_noflush_write_lock(sb);
9411+
9412+ ii_read_lock_parent(a->dir);
9413+ bfound = -1;
9414+ bend = au_ibend(a->dir);
9415+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
9416+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
9417+ bfound = bindex;
9418+ break;
9419+ }
9420+ ii_read_unlock(a->dir);
9421+ if (unlikely(bfound < 0))
9422+ goto out;
9423+
9424+ xino = !!au_opt_test(au_mntflags(sb), XINO);
9425+ h_ino = 0;
9426+ if (a->h_child_inode)
9427+ h_ino = a->h_child_inode->i_ino;
9428+
9429+ if (a->h_child_nlen
9430+ && (au_ftest_hinjob(a->flags[CHILD], GEN)
9431+ || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
9432+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
9433+ a->dir);
9434+ try_iput = 0;
9435+ if (dentry)
9436+ inode = dentry->d_inode;
9437+ if (xino && !inode && h_ino
9438+ && (au_ftest_hinjob(a->flags[CHILD], XINO0)
9439+ || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
9440+ || au_ftest_hinjob(a->flags[CHILD], GEN))) {
9441+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
9442+ try_iput = 1;
9443+ }
9444+
9445+ args.flags = a->flags[CHILD];
9446+ args.dentry = dentry;
9447+ args.inode = inode;
9448+ args.h_inode = a->h_child_inode;
9449+ args.dir = a->dir;
9450+ args.h_dir = a->h_dir;
9451+ args.h_name = a->h_child_name;
9452+ args.h_nlen = a->h_child_nlen;
9453+ err = hin_job(&args);
9454+ if (dentry) {
9455+ if (dentry->d_fsdata)
9456+ di_write_unlock(dentry);
9457+ dput(dentry);
9458+ }
9459+ if (inode && try_iput) {
9460+ ii_write_unlock(inode);
9461+ iput(inode);
9462+ }
9463+
9464+ ii_write_lock_parent(a->dir);
9465+ args.flags = a->flags[PARENT];
9466+ args.dentry = NULL;
9467+ args.inode = a->dir;
9468+ args.h_inode = a->h_dir;
9469+ args.dir = NULL;
9470+ args.h_dir = NULL;
9471+ args.h_name = NULL;
9472+ args.h_nlen = 0;
9473+ err = hin_job(&args);
9474+ ii_write_unlock(a->dir);
9475+
9476+ out:
9477+ au_nwt_done(&sbinfo->si_nowait);
9478+ si_write_unlock(sb);
9479+
9480+ iput(a->h_child_inode);
9481+ iput(a->h_dir);
9482+ iput(a->dir);
9483+ kfree(a);
9484+}
9485+
9486+/* ---------------------------------------------------------------------- */
9487+
9488+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
9489+ u32 mask, u32 cookie __maybe_unused,
9490+ const char *h_child_name, struct inode *h_child_inode)
9491+{
9492+ struct au_hinotify *hinotify;
9493+ struct postproc_args *args;
9494+ int len, wkq_err;
9495+ unsigned char isdir, isroot, wh;
9496+ char *p;
9497+ struct inode *dir;
9498+ unsigned int flags[2];
9499+
9500+ /* if IN_UNMOUNT happens, there must be another bug */
9501+ AuDebugOn(mask & IN_UNMOUNT);
9502+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
9503+ put_inotify_watch(watch);
9504+ return;
9505+ }
9506+#ifdef AuDbgHinotify
9507+ au_debug(1);
9508+ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
9509+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
9510+ " hi%lu\n",
9511+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
9512+ h_child_name ? h_child_name : "",
9513+ h_child_inode ? h_child_inode->i_ino : 0);
9514+ WARN_ON(1);
9515+ }
9516+ au_debug(0);
9517+#endif
9518+
9519+ hinotify = container_of(watch, struct au_hinotify, hin_watch);
9520+ AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
9521+ dir = igrab(hinotify->hin_aufs_inode);
9522+ if (!dir)
9523+ return;
9524+
9525+ isroot = (dir->i_ino == AUFS_ROOT_INO);
9526+ len = 0;
9527+ wh = 0;
9528+ if (h_child_name) {
9529+ len = strlen(h_child_name);
9530+ if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
9531+ h_child_name += AUFS_WH_PFX_LEN;
9532+ len -= AUFS_WH_PFX_LEN;
9533+ wh = 1;
9534+ }
9535+ }
9536+
9537+ isdir = 0;
9538+ if (h_child_inode)
9539+ isdir = !!S_ISDIR(h_child_inode->i_mode);
9540+ flags[PARENT] = AuHinJob_ISDIR;
9541+ flags[CHILD] = 0;
9542+ if (isdir)
9543+ flags[CHILD] = AuHinJob_ISDIR;
9544+ switch (mask & IN_ALL_EVENTS) {
9545+ case IN_MOVED_FROM:
9546+ case IN_MOVED_TO:
9547+ AuDebugOn(!h_child_name || !h_child_inode);
9548+ au_fset_hinjob(flags[CHILD], GEN);
9549+ au_fset_hinjob(flags[CHILD], XINO0);
9550+ au_fset_hinjob(flags[CHILD], MNTPNT);
9551+ au_fset_hinjob(flags[PARENT], DIRENT);
9552+ break;
9553+
9554+ case IN_CREATE:
9555+ AuDebugOn(!h_child_name || !h_child_inode);
9556+ au_fset_hinjob(flags[PARENT], DIRENT);
9557+ au_fset_hinjob(flags[CHILD], GEN);
9558+ break;
9559+
9560+ case IN_DELETE:
9561+ /*
9562+ * aufs never be able to get this child inode.
9563+ * revalidation should be in d_revalidate()
9564+ * by checking i_nlink, i_generation or d_unhashed().
9565+ */
9566+ AuDebugOn(!h_child_name);
9567+ au_fset_hinjob(flags[PARENT], DIRENT);
9568+ au_fset_hinjob(flags[CHILD], GEN);
9569+ au_fset_hinjob(flags[CHILD], TRYXINO0);
9570+ au_fset_hinjob(flags[CHILD], MNTPNT);
9571+ break;
9572+
9573+ default:
9574+ AuDebugOn(1);
9575+ }
9576+
9577+ if (wh)
9578+ h_child_inode = NULL;
9579+
9580+ /* iput() and kfree() will be called in postproc() */
9581+ /*
9582+ * inotify_mutex is already acquired and kmalloc/prune_icache may lock
9583+ * iprune_mutex. strange.
9584+ */
9585+ lockdep_off();
9586+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
9587+ lockdep_on();
9588+ if (unlikely(!args)) {
9589+ AuErr1("no memory\n");
9590+ iput(dir);
9591+ return;
9592+ }
9593+ args->flags[PARENT] = flags[PARENT];
9594+ args->flags[CHILD] = flags[CHILD];
9595+ args->mask = mask;
9596+ args->dir = dir;
9597+ args->h_dir = igrab(watch->inode);
9598+ if (h_child_inode)
9599+ h_child_inode = igrab(h_child_inode); /* can be NULL */
9600+ args->h_child_inode = h_child_inode;
9601+ args->h_child_nlen = len;
9602+ if (len) {
9603+ p = (void *)args;
9604+ p += sizeof(*args);
9605+ memcpy(p, h_child_name, len + 1);
9606+ }
9607+
9608+ lockdep_off();
9609+ wkq_err = au_wkq_nowait(postproc, args, dir->i_sb);
9610+ lockdep_on();
9611+ if (unlikely(wkq_err))
9612+ AuErr("wkq %d\n", wkq_err);
9613+}
9614+
9615+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
9616+{
9617+ return;
9618+}
9619+
9620+static struct inotify_operations aufs_inotify_ops = {
9621+ .handle_event = aufs_inotify,
9622+ .destroy_watch = aufs_inotify_destroy
9623+};
9624+
9625+/* ---------------------------------------------------------------------- */
9626+
9627+static void au_hin_destroy_cache(void)
9628+{
9629+ kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
9630+ au_cachep[AuCache_HINOTIFY] = NULL;
9631+}
9632+
9633+int __init au_hinotify_init(void)
9634+{
9635+ int err;
9636+
9637+ err = -ENOMEM;
9638+ au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
9639+ if (au_cachep[AuCache_HINOTIFY]) {
9640+ err = 0;
9641+ au_hin_handle = inotify_init(&aufs_inotify_ops);
9642+ if (IS_ERR(au_hin_handle)) {
9643+ err = PTR_ERR(au_hin_handle);
9644+ au_hin_destroy_cache();
9645+ }
9646+ }
9647+ AuTraceErr(err);
9648+ return err;
9649+}
9650+
9651+void au_hinotify_fin(void)
9652+{
9653+ inotify_destroy(au_hin_handle);
9654+ if (au_cachep[AuCache_HINOTIFY])
9655+ au_hin_destroy_cache();
9656+}
dece6358
AM
9657diff -urN linux-2.6.30.org/fs/aufs/iinfo.c linux-2.6.30/fs/aufs/iinfo.c
9658--- linux-2.6.30.org/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
9659+++ linux-2.6.30/fs/aufs/iinfo.c 2009-07-21 08:54:19.000000000 +0200
9660@@ -0,0 +1,271 @@
1facf9fc 9661+/*
9662+ * Copyright (C) 2005-2009 Junjiro R. Okajima
9663+ *
9664+ * This program, aufs is free software; you can redistribute it and/or modify
9665+ * it under the terms of the GNU General Public License as published by
9666+ * the Free Software Foundation; either version 2 of the License, or
9667+ * (at your option) any later version.
dece6358
AM
9668+ *
9669+ * This program is distributed in the hope that it will be useful,
9670+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9671+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9672+ * GNU General Public License for more details.
9673+ *
9674+ * You should have received a copy of the GNU General Public License
9675+ * along with this program; if not, write to the Free Software
9676+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 9677+ */
9678+
9679+/*
dece6358 9680+ * inode private data
1facf9fc 9681+ */
9682+
1facf9fc 9683+#include "aufs.h"
9684+
dece6358 9685+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1facf9fc 9686+{
dece6358 9687+ struct inode *h_inode;
1facf9fc 9688+
dece6358
AM
9689+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
9690+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
9691+ return h_inode;
9692+}
1facf9fc 9693+
dece6358
AM
9694+/* todo: hard/soft set? */
9695+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
9696+{
9697+ struct au_iinfo *iinfo = au_ii(inode);
9698+ struct inode *h_inode;
1facf9fc 9699+
dece6358
AM
9700+ iinfo->ii_bstart = bindex;
9701+ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
9702+ if (h_inode)
9703+ au_cpup_igen(inode, h_inode);
9704+}
1facf9fc 9705+
dece6358
AM
9706+void au_hiput(struct au_hinode *hinode)
9707+{
9708+ au_hin_free(hinode);
9709+ dput(hinode->hi_whdentry);
9710+ iput(hinode->hi_inode);
1facf9fc 9711+}
9712+
dece6358 9713+unsigned int au_hi_flags(struct inode *inode, int isdir)
1facf9fc 9714+{
dece6358
AM
9715+ unsigned int flags;
9716+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 9717+
dece6358
AM
9718+ flags = 0;
9719+ if (au_opt_test(mnt_flags, XINO))
9720+ au_fset_hi(flags, XINO);
9721+ if (isdir && au_opt_test(mnt_flags, UDBA_HINOTIFY))
9722+ au_fset_hi(flags, HINOTIFY);
9723+ return flags;
9724+}
1facf9fc 9725+
dece6358
AM
9726+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
9727+ struct inode *h_inode, unsigned int flags)
9728+{
9729+ struct au_hinode *hinode;
9730+ struct inode *hi;
9731+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 9732+
dece6358
AM
9733+ hinode = iinfo->ii_hinode + bindex;
9734+ hi = hinode->hi_inode;
9735+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
9736+ AuDebugOn(h_inode && hi);
9737+
9738+ if (hi)
9739+ au_hiput(hinode);
9740+ hinode->hi_inode = h_inode;
9741+ if (h_inode) {
9742+ int err;
9743+ struct super_block *sb = inode->i_sb;
9744+ struct au_branch *br;
9745+
9746+ if (bindex == iinfo->ii_bstart)
9747+ au_cpup_igen(inode, h_inode);
9748+ br = au_sbr(sb, bindex);
9749+ hinode->hi_id = br->br_id;
9750+ if (au_ftest_hi(flags, XINO)) {
9751+ err = au_xino_write(sb, bindex, h_inode->i_ino,
9752+ inode->i_ino);
9753+ if (unlikely(err))
9754+ AuIOErr1("failed au_xino_write() %d\n", err);
1facf9fc 9755+ }
1facf9fc 9756+
dece6358
AM
9757+ if (au_ftest_hi(flags, HINOTIFY)
9758+ && au_br_hinotifyable(br->br_perm)) {
9759+ err = au_hin_alloc(hinode, inode, h_inode);
9760+ if (unlikely(err))
9761+ AuIOErr1("au_hin_alloc() %d\n", err);
1facf9fc 9762+ }
9763+ }
dece6358 9764+}
1facf9fc 9765+
dece6358
AM
9766+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
9767+ struct dentry *h_wh)
9768+{
9769+ struct au_hinode *hinode;
9770+
9771+ hinode = au_ii(inode)->ii_hinode + bindex;
9772+ AuDebugOn(hinode->hi_whdentry);
9773+ hinode->hi_whdentry = h_wh;
1facf9fc 9774+}
9775+
dece6358
AM
9776+void au_update_iigen(struct inode *inode)
9777+{
9778+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
9779+ /* smp_mb(); */ /* atomic_set */
9780+}
1facf9fc 9781+
dece6358
AM
9782+/* it may be called at remount time, too */
9783+void au_update_brange(struct inode *inode, int do_put_zero)
1facf9fc 9784+{
dece6358 9785+ struct au_iinfo *iinfo;
1facf9fc 9786+
dece6358
AM
9787+ iinfo = au_ii(inode);
9788+ if (!iinfo || iinfo->ii_bstart < 0)
9789+ return;
1facf9fc 9790+
dece6358
AM
9791+ if (do_put_zero) {
9792+ aufs_bindex_t bindex;
1facf9fc 9793+
dece6358
AM
9794+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
9795+ bindex++) {
9796+ struct inode *h_i;
1facf9fc 9797+
dece6358
AM
9798+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
9799+ if (h_i && !h_i->i_nlink)
9800+ au_set_h_iptr(inode, bindex, NULL, 0);
9801+ }
1facf9fc 9802+ }
1facf9fc 9803+
dece6358
AM
9804+ iinfo->ii_bstart = -1;
9805+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
9806+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
9807+ break;
9808+ if (iinfo->ii_bstart > iinfo->ii_bend) {
9809+ iinfo->ii_bstart = -1;
9810+ iinfo->ii_bend = -1;
9811+ return;
9812+ }
1facf9fc 9813+
dece6358
AM
9814+ iinfo->ii_bend++;
9815+ while (0 <= --iinfo->ii_bend)
9816+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
9817+ break;
9818+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1facf9fc 9819+}
9820+
9821+/* ---------------------------------------------------------------------- */
9822+
dece6358 9823+int au_iinfo_init(struct inode *inode)
1facf9fc 9824+{
dece6358
AM
9825+ struct au_iinfo *iinfo;
9826+ struct super_block *sb;
9827+ int nbr, i;
1facf9fc 9828+
dece6358
AM
9829+ sb = inode->i_sb;
9830+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
9831+ nbr = au_sbend(sb) + 1;
9832+ if (unlikely(nbr <= 0))
9833+ nbr = 1;
9834+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
9835+ if (iinfo->ii_hinode) {
9836+ for (i = 0; i < nbr; i++)
9837+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 9838+
dece6358
AM
9839+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
9840+ /* smp_mb(); */ /* atomic_set */
9841+ au_rw_init(&iinfo->ii_rwsem);
9842+ iinfo->ii_bstart = -1;
9843+ iinfo->ii_bend = -1;
9844+ iinfo->ii_vdir = NULL;
9845+ return 0;
1facf9fc 9846+ }
dece6358
AM
9847+ return -ENOMEM;
9848+}
1facf9fc 9849+
dece6358
AM
9850+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
9851+{
9852+ int err, sz;
9853+ struct au_hinode *hip;
9854+
9855+ err = -ENOMEM;
9856+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
9857+ if (!sz)
9858+ sz = sizeof(*hip);
9859+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
9860+ if (hip) {
9861+ iinfo->ii_hinode = hip;
9862+ err = 0;
9863+ }
1facf9fc 9864+
9865+ return err;
9866+}
9867+
dece6358
AM
9868+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
9869+ ino_t ino)
1facf9fc 9870+{
9871+ int err;
dece6358
AM
9872+ aufs_bindex_t bindex;
9873+ unsigned char locked;
9874+
9875+ err = 0;
9876+ locked = !!si_noflush_read_trylock(sb);
9877+ bindex = au_br_index(sb, hinode->hi_id);
9878+ if (bindex >= 0)
9879+ err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
9880+ /* error action? */
9881+ if (locked)
9882+ si_read_unlock(sb);
9883+ return err;
9884+}
9885+
9886+void au_iinfo_fin(struct inode *inode)
9887+{
9888+ ino_t ino;
9889+ aufs_bindex_t bend;
9890+ unsigned char unlinked = !inode->i_nlink;
9891+ struct au_iinfo *iinfo;
9892+ struct au_hinode *hi;
1facf9fc 9893+ struct super_block *sb;
1facf9fc 9894+
dece6358
AM
9895+ if (unlinked) {
9896+ int err = au_xigen_inc(inode);
9897+ if (unlikely(err))
9898+ AuWarn1("failed resetting i_generation, %d\n", err);
9899+ }
1facf9fc 9900+
dece6358
AM
9901+ iinfo = au_ii(inode);
9902+ /* bad_inode case */
9903+ if (!iinfo)
9904+ return;
9905+
9906+ if (iinfo->ii_vdir)
9907+ au_vdir_free(iinfo->ii_vdir);
9908+
9909+ if (iinfo->ii_bstart >= 0) {
9910+ sb = inode->i_sb;
9911+ ino = 0;
9912+ if (unlinked)
9913+ ino = inode->i_ino;
9914+ hi = iinfo->ii_hinode + iinfo->ii_bstart;
9915+ bend = iinfo->ii_bend;
9916+ while (iinfo->ii_bstart++ <= bend) {
9917+ if (hi->hi_inode) {
9918+ if (unlinked || !hi->hi_inode->i_nlink) {
9919+ au_iinfo_write0(sb, hi, ino);
9920+ /* ignore this error */
9921+ ino = 0;
9922+ }
9923+ au_hiput(hi);
1facf9fc 9924+ }
dece6358 9925+ hi++;
1facf9fc 9926+ }
1facf9fc 9927+ }
1facf9fc 9928+
dece6358
AM
9929+ kfree(iinfo->ii_hinode);
9930+ AuRwDestroy(&iinfo->ii_rwsem);
1facf9fc 9931+}
dece6358
AM
9932diff -urN linux-2.6.30.org/fs/aufs/inode.c linux-2.6.30/fs/aufs/inode.c
9933--- linux-2.6.30.org/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
9934+++ linux-2.6.30/fs/aufs/inode.c 2009-07-21 08:54:19.000000000 +0200
9935@@ -0,0 +1,376 @@
9936+/*
9937+ * Copyright (C) 2005-2009 Junjiro R. Okajima
9938+ *
9939+ * This program, aufs is free software; you can redistribute it and/or modify
9940+ * it under the terms of the GNU General Public License as published by
9941+ * the Free Software Foundation; either version 2 of the License, or
9942+ * (at your option) any later version.
9943+ *
9944+ * This program is distributed in the hope that it will be useful,
9945+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9946+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9947+ * GNU General Public License for more details.
9948+ *
9949+ * You should have received a copy of the GNU General Public License
9950+ * along with this program; if not, write to the Free Software
9951+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9952+ */
1facf9fc 9953+
dece6358
AM
9954+/*
9955+ * inode functions
9956+ */
1facf9fc 9957+
dece6358
AM
9958+#include "aufs.h"
9959+
9960+struct inode *au_igrab(struct inode *inode)
1facf9fc 9961+{
dece6358
AM
9962+ if (inode) {
9963+ AuDebugOn(!atomic_read(&inode->i_count));
9964+ atomic_inc_return(&inode->i_count);
9965+ }
9966+ return inode;
1facf9fc 9967+}
9968+
dece6358 9969+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
1facf9fc 9970+{
dece6358
AM
9971+ au_cpup_attr_all(inode, /*force*/0);
9972+ au_update_iigen(inode);
9973+ if (do_version)
9974+ inode->i_version++;
1facf9fc 9975+}
9976+
dece6358 9977+int au_refresh_hinode_self(struct inode *inode, int do_attr)
1facf9fc 9978+{
9979+ int err;
dece6358
AM
9980+ aufs_bindex_t bindex, new_bindex;
9981+ unsigned char update;
9982+ struct inode *first;
9983+ struct au_hinode *p, *q, tmp;
1facf9fc 9984+ struct super_block *sb;
dece6358 9985+ struct au_iinfo *iinfo;
1facf9fc 9986+
dece6358
AM
9987+ update = 0;
9988+ sb = inode->i_sb;
9989+ iinfo = au_ii(inode);
9990+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
9991+ if (unlikely(err))
1facf9fc 9992+ goto out;
1facf9fc 9993+
dece6358
AM
9994+ p = iinfo->ii_hinode + iinfo->ii_bstart;
9995+ first = p->hi_inode;
9996+ err = 0;
9997+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
9998+ bindex++, p++) {
9999+ if (!p->hi_inode)
10000+ continue;
1facf9fc 10001+
dece6358
AM
10002+ new_bindex = au_br_index(sb, p->hi_id);
10003+ if (new_bindex == bindex)
10004+ continue;
1facf9fc 10005+
dece6358
AM
10006+ if (new_bindex < 0) {
10007+ update++;
10008+ au_hiput(p);
10009+ p->hi_inode = NULL;
10010+ continue;
1facf9fc 10011+ }
1facf9fc 10012+
dece6358
AM
10013+ if (new_bindex < iinfo->ii_bstart)
10014+ iinfo->ii_bstart = new_bindex;
10015+ if (iinfo->ii_bend < new_bindex)
10016+ iinfo->ii_bend = new_bindex;
10017+ /* swap two lower inode, and loop again */
10018+ q = iinfo->ii_hinode + new_bindex;
10019+ tmp = *q;
10020+ *q = *p;
10021+ *p = tmp;
10022+ if (tmp.hi_inode) {
10023+ bindex--;
10024+ p--;
1facf9fc 10025+ }
10026+ }
dece6358
AM
10027+ au_update_brange(inode, /*do_put_zero*/0);
10028+ if (do_attr)
10029+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 10030+
1facf9fc 10031+ out:
10032+ return err;
10033+}
10034+
dece6358 10035+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
1facf9fc 10036+{
dece6358
AM
10037+ int err, update;
10038+ unsigned int flags;
10039+ aufs_bindex_t bindex, bend;
10040+ unsigned char isdir;
10041+ struct inode *first;
10042+ struct au_hinode *p;
10043+ struct au_iinfo *iinfo;
1facf9fc 10044+
dece6358
AM
10045+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
10046+ if (unlikely(err))
10047+ goto out;
1facf9fc 10048+
dece6358
AM
10049+ update = 0;
10050+ iinfo = au_ii(inode);
10051+ p = iinfo->ii_hinode + iinfo->ii_bstart;
10052+ first = p->hi_inode;
10053+ isdir = S_ISDIR(inode->i_mode);
10054+ flags = au_hi_flags(inode, isdir);
10055+ bend = au_dbend(dentry);
10056+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
10057+ struct inode *h_i;
10058+ struct dentry *h_d;
1facf9fc 10059+
dece6358
AM
10060+ h_d = au_h_dptr(dentry, bindex);
10061+ if (!h_d || !h_d->d_inode)
10062+ continue;
1facf9fc 10063+
dece6358
AM
10064+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
10065+ h_i = au_h_iptr(inode, bindex);
10066+ if (h_i) {
10067+ if (h_i == h_d->d_inode)
10068+ continue;
10069+ err = -EIO;
10070+ break;
10071+ }
10072+ }
10073+ if (bindex < iinfo->ii_bstart)
10074+ iinfo->ii_bstart = bindex;
10075+ if (iinfo->ii_bend < bindex)
10076+ iinfo->ii_bend = bindex;
10077+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
10078+ update = 1;
10079+ }
10080+ au_update_brange(inode, /*do_put_zero*/0);
1facf9fc 10081+
dece6358
AM
10082+ if (unlikely(err))
10083+ goto out;
1facf9fc 10084+
dece6358
AM
10085+ au_refresh_hinode_attr(inode, update && isdir);
10086+
10087+ out:
10088+ return err;
10089+}
10090+
10091+static int set_inode(struct inode *inode, struct dentry *dentry)
1facf9fc 10092+{
10093+ int err;
dece6358
AM
10094+ unsigned int flags;
10095+ umode_t mode;
10096+ aufs_bindex_t bindex, bstart, btail;
10097+ unsigned char isdir;
10098+ struct dentry *h_dentry;
10099+ struct inode *h_inode;
10100+ struct au_iinfo *iinfo;
1facf9fc 10101+
10102+ err = 0;
dece6358
AM
10103+ isdir = 0;
10104+ bstart = au_dbstart(dentry);
10105+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
10106+ mode = h_inode->i_mode;
10107+ switch (mode & S_IFMT) {
10108+ case S_IFREG:
10109+ btail = au_dbtail(dentry);
10110+ inode->i_op = &aufs_iop;
10111+ inode->i_fop = &aufs_file_fop;
10112+ inode->i_mapping->a_ops = &aufs_aop;
10113+ break;
10114+ case S_IFDIR:
10115+ isdir = 1;
10116+ btail = au_dbtaildir(dentry);
10117+ inode->i_op = &aufs_dir_iop;
10118+ inode->i_fop = &aufs_dir_fop;
10119+ break;
10120+ case S_IFLNK:
10121+ btail = au_dbtail(dentry);
10122+ inode->i_op = &aufs_symlink_iop;
10123+ break;
10124+ case S_IFBLK:
10125+ case S_IFCHR:
10126+ case S_IFIFO:
10127+ case S_IFSOCK:
10128+ btail = au_dbtail(dentry);
10129+ inode->i_op = &aufs_iop;
10130+ init_special_inode(inode, mode, h_inode->i_rdev);
10131+ break;
10132+ default:
10133+ AuIOErr("Unknown file type 0%o\n", mode);
10134+ err = -EIO;
10135+ goto out;
1facf9fc 10136+ }
1facf9fc 10137+
dece6358
AM
10138+ /* do not set inotify for whiteouted dirs (SHWH mode) */
10139+ flags = au_hi_flags(inode, isdir);
10140+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
10141+ && au_ftest_hi(flags, HINOTIFY)
10142+ && dentry->d_name.len > AUFS_WH_PFX_LEN
10143+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
10144+ au_fclr_hi(flags, HINOTIFY);
10145+ iinfo = au_ii(inode);
10146+ iinfo->ii_bstart = bstart;
10147+ iinfo->ii_bend = btail;
10148+ for (bindex = bstart; bindex <= btail; bindex++) {
10149+ h_dentry = au_h_dptr(dentry, bindex);
10150+ if (h_dentry)
10151+ au_set_h_iptr(inode, bindex,
10152+ au_igrab(h_dentry->d_inode), flags);
1facf9fc 10153+ }
dece6358 10154+ au_cpup_attr_all(inode, /*force*/1);
1facf9fc 10155+
1facf9fc 10156+ out:
10157+ return err;
10158+}
10159+
dece6358
AM
10160+/* successful returns with iinfo write_locked */
10161+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
1facf9fc 10162+{
10163+ int err;
dece6358
AM
10164+ aufs_bindex_t bindex, bend;
10165+ struct inode *h_inode, *h_dinode;
1facf9fc 10166+
dece6358 10167+ *matched = 0;
1facf9fc 10168+
dece6358
AM
10169+ /*
10170+ * before this function, if aufs got any iinfo lock, it must be only
10171+ * one, the parent dir.
10172+ * it can happen by UDBA and the obsoleted inode number.
10173+ */
10174+ err = -EIO;
10175+ if (unlikely(inode->i_ino == parent_ino(dentry)))
10176+ goto out;
1facf9fc 10177+
dece6358
AM
10178+ err = 0;
10179+ ii_write_lock_new_child(inode);
10180+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
10181+ bend = au_ibend(inode);
10182+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
10183+ h_inode = au_h_iptr(inode, bindex);
10184+ if (h_inode && h_inode == h_dinode) {
10185+ *matched = 1;
10186+ err = 0;
10187+ if (au_iigen(inode) != au_digen(dentry))
10188+ err = au_refresh_hinode(inode, dentry);
10189+ break;
10190+ }
1facf9fc 10191+ }
10192+
dece6358
AM
10193+ if (unlikely(err))
10194+ ii_write_unlock(inode);
10195+ out:
10196+ return err;
10197+}
1facf9fc 10198+
dece6358
AM
10199+/* successful returns with iinfo write_locked */
10200+/* todo: return with unlocked? */
10201+struct inode *au_new_inode(struct dentry *dentry, int must_new)
10202+{
10203+ struct inode *inode;
10204+ struct dentry *h_dentry;
10205+ struct super_block *sb;
10206+ ino_t h_ino, ino;
10207+ int err, match;
10208+ aufs_bindex_t bstart;
10209+
10210+ sb = dentry->d_sb;
10211+ bstart = au_dbstart(dentry);
10212+ h_dentry = au_h_dptr(dentry, bstart);
10213+ h_ino = h_dentry->d_inode->i_ino;
10214+ err = au_xino_read(sb, bstart, h_ino, &ino);
10215+ inode = ERR_PTR(err);
10216+ if (unlikely(err))
10217+ goto out;
10218+ new_ino:
10219+ if (!ino) {
10220+ ino = au_xino_new_ino(sb);
10221+ if (unlikely(!ino)) {
10222+ inode = ERR_PTR(-EIO);
10223+ goto out;
10224+ }
1facf9fc 10225+ }
10226+
dece6358
AM
10227+ AuDbg("i%lu\n", (unsigned long)ino);
10228+ inode = au_iget_locked(sb, ino);
10229+ err = PTR_ERR(inode);
10230+ if (IS_ERR(inode))
10231+ goto out;
1facf9fc 10232+
dece6358
AM
10233+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
10234+ if (inode->i_state & I_NEW) {
10235+ ii_write_lock_new_child(inode);
10236+ err = set_inode(inode, dentry);
10237+ unlock_new_inode(inode);
10238+ if (!err)
10239+ goto out; /* success */
1facf9fc 10240+
dece6358
AM
10241+ iget_failed(inode);
10242+ ii_write_unlock(inode);
10243+ goto out_iput;
10244+ } else if (!must_new) {
10245+ err = reval_inode(inode, dentry, &match);
10246+ if (!err)
10247+ goto out; /* success */
10248+ else if (match)
10249+ goto out_iput;
10250+ }
1facf9fc 10251+
dece6358
AM
10252+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
10253+ AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
10254+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
10255+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
10256+ (unsigned long)h_ino, (unsigned long)ino);
10257+ ino = 0;
10258+ err = au_xino_write0(sb, bstart, h_ino, 0);
10259+ if (!err) {
10260+ iput(inode);
10261+ goto new_ino;
1facf9fc 10262+ }
dece6358
AM
10263+
10264+ out_iput:
10265+ iput(inode);
10266+ inode = ERR_PTR(err);
1facf9fc 10267+ out:
dece6358 10268+ return inode;
1facf9fc 10269+}
10270+
dece6358
AM
10271+/* ---------------------------------------------------------------------- */
10272+
10273+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
10274+ struct inode *inode)
1facf9fc 10275+{
10276+ int err;
1facf9fc 10277+
dece6358
AM
10278+ err = au_br_rdonly(au_sbr(sb, bindex));
10279+
10280+ /* pseudo-link after flushed may happen out of bounds */
10281+ if (!err
10282+ && inode
10283+ && au_ibstart(inode) <= bindex
10284+ && bindex <= au_ibend(inode)) {
10285+ /*
10286+ * permission check is unnecessary since vfsub routine
10287+ * will be called later
10288+ */
10289+ struct inode *hi = au_h_iptr(inode, bindex);
10290+ if (hi)
10291+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 10292+ }
1facf9fc 10293+
10294+ return err;
10295+}
10296+
dece6358 10297+int au_test_h_perm(struct inode *h_inode, int mask)
1facf9fc 10298+{
dece6358
AM
10299+ if (!current_fsuid())
10300+ return 0;
10301+ return inode_permission(h_inode, mask);
1facf9fc 10302+}
10303+
dece6358 10304+int au_test_h_perm_sio(struct inode *h_inode, int mask)
1facf9fc 10305+{
dece6358
AM
10306+ if (au_test_nfs(h_inode->i_sb)
10307+ && (mask & MAY_WRITE)
10308+ && S_ISDIR(h_inode->i_mode))
10309+ mask |= MAY_READ; /* force permission check */
10310+ return au_test_h_perm(h_inode, mask);
10311+}
10312diff -urN linux-2.6.30.org/fs/aufs/inode.h linux-2.6.30/fs/aufs/inode.h
10313--- linux-2.6.30.org/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
10314+++ linux-2.6.30/fs/aufs/inode.h 2009-07-21 08:54:19.000000000 +0200
10315@@ -0,0 +1,475 @@
10316+/*
10317+ * Copyright (C) 2005-2009 Junjiro R. Okajima
10318+ *
10319+ * This program, aufs is free software; you can redistribute it and/or modify
10320+ * it under the terms of the GNU General Public License as published by
10321+ * the Free Software Foundation; either version 2 of the License, or
10322+ * (at your option) any later version.
10323+ *
10324+ * This program is distributed in the hope that it will be useful,
10325+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10326+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10327+ * GNU General Public License for more details.
10328+ *
10329+ * You should have received a copy of the GNU General Public License
10330+ * along with this program; if not, write to the Free Software
10331+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10332+ */
1facf9fc 10333+
dece6358
AM
10334+/*
10335+ * inode operations
10336+ */
1facf9fc 10337+
dece6358
AM
10338+#ifndef __AUFS_INODE_H__
10339+#define __AUFS_INODE_H__
1facf9fc 10340+
dece6358 10341+#ifdef __KERNEL__
1facf9fc 10342+
dece6358
AM
10343+#include <linux/fs.h>
10344+#include <linux/inotify.h>
10345+#include <linux/aufs_type.h>
10346+#include "rwsem.h"
1facf9fc 10347+
dece6358 10348+struct vfsmount;
1facf9fc 10349+
dece6358
AM
10350+struct au_hinotify {
10351+#ifdef CONFIG_AUFS_HINOTIFY
10352+ struct inotify_watch hin_watch;
10353+ struct inode *hin_aufs_inode; /* no get/put */
10354+#endif
10355+};
1facf9fc 10356+
dece6358
AM
10357+struct au_hinode {
10358+ struct inode *hi_inode;
10359+ aufs_bindex_t hi_id;
10360+#ifdef CONFIG_AUFS_HINOTIFY
10361+ struct au_hinotify *hi_notify;
10362+#endif
1facf9fc 10363+
dece6358
AM
10364+ /* reference to the copied-up whiteout with get/put */
10365+ struct dentry *hi_whdentry;
10366+};
1facf9fc 10367+
dece6358
AM
10368+struct au_vdir;
10369+struct au_iinfo {
10370+ atomic_t ii_generation;
10371+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 10372+
dece6358
AM
10373+ struct au_rwsem ii_rwsem;
10374+ aufs_bindex_t ii_bstart, ii_bend;
10375+ __u32 ii_higen;
10376+ struct au_hinode *ii_hinode;
10377+ struct au_vdir *ii_vdir;
10378+};
1facf9fc 10379+
dece6358
AM
10380+struct au_icntnr {
10381+ struct au_iinfo iinfo;
10382+ struct inode vfs_inode;
10383+};
1facf9fc 10384+
dece6358
AM
10385+/* au_pin flags */
10386+#define AuPin_DI_LOCKED 1
10387+#define AuPin_MNT_WRITE (1 << 1)
10388+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
10389+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
10390+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
1facf9fc 10391+
dece6358
AM
10392+struct au_pin {
10393+ /* input */
10394+ struct dentry *dentry;
10395+ unsigned int udba;
10396+ unsigned char lsc_di, lsc_hi, flags;
10397+ aufs_bindex_t bindex;
1facf9fc 10398+
dece6358
AM
10399+ /* output */
10400+ struct dentry *parent;
10401+ struct au_hinode *hdir;
10402+ struct vfsmount *h_mnt;
10403+};
1facf9fc 10404+
10405+/* ---------------------------------------------------------------------- */
10406+
dece6358 10407+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 10408+{
dece6358
AM
10409+ struct au_iinfo *iinfo;
10410+
10411+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
10412+ if (iinfo->ii_hinode)
10413+ return iinfo;
10414+ return NULL; /* debugging bad_inode case */
1facf9fc 10415+}
10416+
10417+/* ---------------------------------------------------------------------- */
10418+
dece6358
AM
10419+/* inode.c */
10420+struct inode *au_igrab(struct inode *inode);
10421+int au_refresh_hinode_self(struct inode *inode, int do_attr);
10422+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
10423+struct inode *au_new_inode(struct dentry *dentry, int must_new);
10424+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
10425+ struct inode *inode);
10426+int au_test_h_perm(struct inode *h_inode, int mask);
10427+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 10428+
dece6358
AM
10429+/* i_op.c */
10430+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1facf9fc 10431+
dece6358
AM
10432+/* au_wr_dir flags */
10433+#define AuWrDir_ADD_ENTRY 1
10434+#define AuWrDir_ISDIR (1 << 1)
10435+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
10436+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
10437+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
1facf9fc 10438+
dece6358
AM
10439+struct au_wr_dir_args {
10440+ aufs_bindex_t force_btgt;
10441+ unsigned char flags;
1facf9fc 10442+};
dece6358
AM
10443+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
10444+ struct au_wr_dir_args *args);
1facf9fc 10445+
dece6358
AM
10446+struct dentry *au_pinned_h_parent(struct au_pin *pin);
10447+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
10448+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
10449+ unsigned int udba, unsigned char flags);
10450+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
10451+ unsigned int udba, unsigned char flags) __must_check;
10452+int au_do_pin(struct au_pin *pin) __must_check;
10453+void au_unpin(struct au_pin *pin);
1facf9fc 10454+
dece6358
AM
10455+/* i_op_add.c */
10456+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
10457+ struct dentry *h_parent, int isdir);
10458+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
10459+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
10460+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
10461+ struct nameidata *nd);
10462+int aufs_link(struct dentry *src_dentry, struct inode *dir,
10463+ struct dentry *dentry);
10464+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 10465+
dece6358
AM
10466+/* i_op_del.c */
10467+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
10468+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
10469+ struct dentry *h_parent, int isdir);
10470+int aufs_unlink(struct inode *dir, struct dentry *dentry);
10471+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1facf9fc 10472+
dece6358
AM
10473+/* i_op_ren.c */
10474+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
10475+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
10476+ struct inode *dir, struct dentry *dentry);
1facf9fc 10477+
dece6358
AM
10478+/* iinfo.c */
10479+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
10480+void au_hiput(struct au_hinode *hinode);
10481+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
10482+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
10483+ struct dentry *h_wh);
10484+unsigned int au_hi_flags(struct inode *inode, int isdir);
1facf9fc 10485+
dece6358
AM
10486+/* hinode flags */
10487+#define AuHi_XINO 1
10488+#define AuHi_HINOTIFY (1 << 1)
10489+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
10490+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
10491+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
1facf9fc 10492+
dece6358
AM
10493+#ifndef CONFIG_AUFS_HINOTIFY
10494+#undef AuHi_HINOTIFY
10495+#define AuHi_HINOTIFY 0
10496+#endif
1facf9fc 10497+
dece6358
AM
10498+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
10499+ struct inode *h_inode, unsigned int flags);
10500+
10501+void au_update_iigen(struct inode *inode);
10502+void au_update_brange(struct inode *inode, int do_put_zero);
10503+
10504+int au_iinfo_init(struct inode *inode);
10505+void au_iinfo_fin(struct inode *inode);
10506+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
10507+
10508+/* plink.c */
10509+void au_plink_block_maintain(struct super_block *sb);
10510+#ifdef CONFIG_AUFS_DEBUG
10511+void au_plink_list(struct super_block *sb);
10512+#else
10513+static inline void au_plink_list(struct super_block *sb)
10514+{
10515+ /* nothing */
1facf9fc 10516+}
dece6358
AM
10517+#endif
10518+int au_plink_test(struct inode *inode);
10519+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
10520+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
10521+ struct dentry *h_dentry);
10522+void au_plink_put(struct super_block *sb);
10523+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
10524+
10525+/* ---------------------------------------------------------------------- */
10526+
10527+/* lock subclass for iinfo */
10528+enum {
10529+ AuLsc_II_CHILD, /* child first */
10530+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
10531+ AuLsc_II_CHILD3, /* copyup dirs */
10532+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
10533+ AuLsc_II_PARENT2,
10534+ AuLsc_II_PARENT3, /* copyup dirs */
10535+ AuLsc_II_NEW_CHILD
10536+};
1facf9fc 10537+
10538+/*
dece6358
AM
10539+ * ii_read_lock_child, ii_write_lock_child,
10540+ * ii_read_lock_child2, ii_write_lock_child2,
10541+ * ii_read_lock_child3, ii_write_lock_child3,
10542+ * ii_read_lock_parent, ii_write_lock_parent,
10543+ * ii_read_lock_parent2, ii_write_lock_parent2,
10544+ * ii_read_lock_parent3, ii_write_lock_parent3,
10545+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 10546+ */
dece6358
AM
10547+#define AuReadLockFunc(name, lsc) \
10548+static inline void ii_read_lock_##name(struct inode *i) \
10549+{ \
10550+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
10551+}
1facf9fc 10552+
dece6358
AM
10553+#define AuWriteLockFunc(name, lsc) \
10554+static inline void ii_write_lock_##name(struct inode *i) \
10555+{ \
10556+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
10557+}
1facf9fc 10558+
dece6358
AM
10559+#define AuRWLockFuncs(name, lsc) \
10560+ AuReadLockFunc(name, lsc) \
10561+ AuWriteLockFunc(name, lsc)
1facf9fc 10562+
dece6358
AM
10563+AuRWLockFuncs(child, CHILD);
10564+AuRWLockFuncs(child2, CHILD2);
10565+AuRWLockFuncs(child3, CHILD3);
10566+AuRWLockFuncs(parent, PARENT);
10567+AuRWLockFuncs(parent2, PARENT2);
10568+AuRWLockFuncs(parent3, PARENT3);
10569+AuRWLockFuncs(new_child, NEW_CHILD);
1facf9fc 10570+
dece6358
AM
10571+#undef AuReadLockFunc
10572+#undef AuWriteLockFunc
10573+#undef AuRWLockFuncs
1facf9fc 10574+
10575+/*
dece6358 10576+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 10577+ */
dece6358 10578+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 10579+
dece6358
AM
10580+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
10581+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
10582+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 10583+
dece6358 10584+/* ---------------------------------------------------------------------- */
1facf9fc 10585+
dece6358
AM
10586+static inline unsigned int au_iigen(struct inode *inode)
10587+{
10588+ return atomic_read(&au_ii(inode)->ii_generation);
10589+}
1facf9fc 10590+
dece6358
AM
10591+/* tiny test for inode number */
10592+/* tmpfs generation is too rough */
10593+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
10594+{
10595+ struct au_iinfo *iinfo;
1facf9fc 10596+
dece6358
AM
10597+ iinfo = au_ii(inode);
10598+ return !(iinfo->ii_hsb1 == h_inode->i_sb
10599+ && iinfo->ii_higen == h_inode->i_generation);
1facf9fc 10600+}
10601+
10602+/* ---------------------------------------------------------------------- */
10603+
dece6358
AM
10604+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
10605+ aufs_bindex_t bindex)
1facf9fc 10606+{
dece6358
AM
10607+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
10608+}
1facf9fc 10609+
dece6358
AM
10610+static inline aufs_bindex_t au_ibstart(struct inode *inode)
10611+{
10612+ return au_ii(inode)->ii_bstart;
10613+}
1facf9fc 10614+
dece6358
AM
10615+static inline aufs_bindex_t au_ibend(struct inode *inode)
10616+{
10617+ return au_ii(inode)->ii_bend;
10618+}
1facf9fc 10619+
dece6358
AM
10620+static inline struct au_vdir *au_ivdir(struct inode *inode)
10621+{
10622+ return au_ii(inode)->ii_vdir;
10623+}
1facf9fc 10624+
dece6358
AM
10625+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
10626+{
10627+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
1facf9fc 10628+}
10629+
dece6358 10630+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
1facf9fc 10631+{
dece6358 10632+ au_ii(inode)->ii_bend = bindex;
1facf9fc 10633+}
10634+
dece6358 10635+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
1facf9fc 10636+{
dece6358 10637+ au_ii(inode)->ii_vdir = vdir;
1facf9fc 10638+}
10639+
dece6358 10640+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1facf9fc 10641+{
dece6358 10642+ return au_ii(inode)->ii_hinode + bindex;
1facf9fc 10643+}
10644+
10645+/* ---------------------------------------------------------------------- */
10646+
dece6358 10647+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
1facf9fc 10648+{
dece6358
AM
10649+ if (pin)
10650+ return pin->parent;
10651+ return NULL;
1facf9fc 10652+}
10653+
dece6358 10654+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 10655+{
dece6358
AM
10656+ if (pin && pin->hdir)
10657+ return pin->hdir->hi_inode;
10658+ return NULL;
10659+}
1facf9fc 10660+
dece6358
AM
10661+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
10662+{
10663+ if (pin)
10664+ return pin->hdir;
10665+ return NULL;
10666+}
1facf9fc 10667+
dece6358
AM
10668+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
10669+{
10670+ if (pin)
10671+ pin->dentry = dentry;
10672+}
1facf9fc 10673+
dece6358
AM
10674+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
10675+ unsigned char lflag)
10676+{
10677+ if (pin) {
10678+ /* dirty macros require brackets */
10679+ if (lflag) {
10680+ au_fset_pin(pin->flags, DI_LOCKED);
1facf9fc 10681+ } else {
dece6358 10682+ au_fclr_pin(pin->flags, DI_LOCKED);
1facf9fc 10683+ }
10684+ }
1facf9fc 10685+}
10686+
dece6358 10687+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
1facf9fc 10688+{
dece6358
AM
10689+ if (pin) {
10690+ dput(pin->parent);
10691+ pin->parent = dget(parent);
10692+ }
10693+}
1facf9fc 10694+
dece6358 10695+/* ---------------------------------------------------------------------- */
1facf9fc 10696+
dece6358
AM
10697+#ifdef CONFIG_AUFS_HINOTIFY
10698+/* hinotify.c */
10699+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10700+ struct inode *h_inode);
10701+void au_hin_free(struct au_hinode *hinode);
10702+void au_hin_ctl(struct au_hinode *hinode, int do_set);
10703+void au_reset_hinotify(struct inode *inode, unsigned int flags);
1facf9fc 10704+
dece6358
AM
10705+int __init au_hinotify_init(void);
10706+void au_hinotify_fin(void);
1facf9fc 10707+
dece6358
AM
10708+static inline
10709+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
10710+{
10711+ hinode->hi_notify = val;
10712+}
1facf9fc 10713+
dece6358
AM
10714+static inline void au_iigen_dec(struct inode *inode)
10715+{
10716+ atomic_dec_return(&au_ii(inode)->ii_generation);
10717+}
1facf9fc 10718+
dece6358
AM
10719+#else
10720+static inline
10721+int au_hin_alloc(struct au_hinode *hinode __maybe_unused,
10722+ struct inode *inode __maybe_unused,
10723+ struct inode *h_inode __maybe_unused)
10724+{
10725+ return -EOPNOTSUPP;
10726+}
1facf9fc 10727+
dece6358
AM
10728+static inline void au_hin_free(struct au_hinode *hinode __maybe_unused)
10729+{
10730+ /* nothing */
1facf9fc 10731+}
10732+
dece6358
AM
10733+static inline void au_hin_ctl(struct au_hinode *hinode __maybe_unused,
10734+ int do_set __maybe_unused)
1facf9fc 10735+{
dece6358
AM
10736+ /* nothing */
10737+}
1facf9fc 10738+
dece6358
AM
10739+static inline void au_reset_hinotify(struct inode *inode __maybe_unused,
10740+ unsigned int flags __maybe_unused)
10741+{
10742+ /* nothing */
10743+}
1facf9fc 10744+
dece6358
AM
10745+static inline int au_hinotify_init(void)
10746+{
10747+ return 0;
10748+}
1facf9fc 10749+
dece6358 10750+#define au_hinotify_fin() do {} while (0)
1facf9fc 10751+
dece6358
AM
10752+static inline
10753+void au_hin_init(struct au_hinode *hinode __maybe_unused,
10754+ struct au_hinotify *val __maybe_unused)
10755+{
10756+ /* empty */
10757+}
10758+#endif /* CONFIG_AUFS_HINOTIFY */
1facf9fc 10759+
dece6358
AM
10760+static inline void au_hin_suspend(struct au_hinode *hdir)
10761+{
10762+ au_hin_ctl(hdir, /*do_set*/0);
10763+}
1facf9fc 10764+
dece6358
AM
10765+static inline void au_hin_resume(struct au_hinode *hdir)
10766+{
10767+ au_hin_ctl(hdir, /*do_set*/1);
10768+}
1facf9fc 10769+
dece6358
AM
10770+static inline void au_hin_imtx_lock(struct au_hinode *hdir)
10771+{
10772+ mutex_lock(&hdir->hi_inode->i_mutex);
10773+ au_hin_suspend(hdir);
10774+}
10775+
10776+static inline void au_hin_imtx_lock_nested(struct au_hinode *hdir,
10777+ unsigned int sc __maybe_unused)
10778+{
10779+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
10780+ au_hin_suspend(hdir);
10781+}
10782+
10783+static inline void au_hin_imtx_unlock(struct au_hinode *hdir)
10784+{
10785+ au_hin_resume(hdir);
10786+ mutex_unlock(&hdir->hi_inode->i_mutex);
10787+}
10788+
10789+#endif /* __KERNEL__ */
10790+#endif /* __AUFS_INODE_H__ */
10791diff -urN linux-2.6.30.org/fs/aufs/ioctl.c linux-2.6.30/fs/aufs/ioctl.c
10792--- linux-2.6.30.org/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
10793+++ linux-2.6.30/fs/aufs/ioctl.c 2009-07-21 08:54:19.000000000 +0200
10794@@ -0,0 +1,67 @@
10795+/*
10796+ * Copyright (C) 2005-2009 Junjiro R. Okajima
10797+ *
10798+ * This program, aufs is free software; you can redistribute it and/or modify
10799+ * it under the terms of the GNU General Public License as published by
10800+ * the Free Software Foundation; either version 2 of the License, or
10801+ * (at your option) any later version.
10802+ *
10803+ * This program is distributed in the hope that it will be useful,
10804+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10805+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10806+ * GNU General Public License for more details.
10807+ *
10808+ * You should have received a copy of the GNU General Public License
10809+ * along with this program; if not, write to the Free Software
10810+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10811+ */
10812+
10813+/*
10814+ * ioctl
10815+ * currently plink-management only.
10816+ */
10817+
10818+#include <linux/uaccess.h>
10819+#include "aufs.h"
10820+
10821+long aufs_ioctl_dir(struct file *file, unsigned int cmd,
10822+ unsigned long arg __maybe_unused)
10823+{
10824+ long err;
10825+ struct super_block *sb;
10826+ struct au_sbinfo *sbinfo;
10827+
10828+ err = -EACCES;
10829+ if (!capable(CAP_SYS_ADMIN))
10830+ goto out;
10831+
10832+ err = 0;
10833+ sb = file->f_dentry->d_sb;
10834+ sbinfo = au_sbi(sb);
10835+ switch (cmd) {
10836+ case AUFS_CTL_PLINK_MAINT:
10837+ /*
10838+ * pseudo-link maintenance mode,
10839+ * cleared by aufs_release_dir()
10840+ */
10841+ si_write_lock(sb);
10842+ if (!au_ftest_si(sbinfo, MAINTAIN_PLINK)) {
10843+ au_fset_si(sbinfo, MAINTAIN_PLINK);
10844+ au_fi(file)->fi_maintain_plink = 1;
10845+ } else
10846+ err = -EBUSY;
10847+ si_write_unlock(sb);
10848+ break;
10849+ case AUFS_CTL_PLINK_CLEAN:
10850+ aufs_write_lock(sb->s_root);
10851+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
10852+ au_plink_put(sb);
10853+ aufs_write_unlock(sb->s_root);
10854+ break;
10855+ default:
10856+ err = -EINVAL;
1facf9fc 10857+ }
dece6358 10858+
1facf9fc 10859+ out:
1facf9fc 10860+ return err;
10861+}
dece6358
AM
10862diff -urN linux-2.6.30.org/fs/aufs/i_op_add.c linux-2.6.30/fs/aufs/i_op_add.c
10863--- linux-2.6.30.org/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
10864+++ linux-2.6.30/fs/aufs/i_op_add.c 2009-07-21 08:54:19.000000000 +0200
10865@@ -0,0 +1,638 @@
1facf9fc 10866+/*
10867+ * Copyright (C) 2005-2009 Junjiro R. Okajima
10868+ *
10869+ * This program, aufs is free software; you can redistribute it and/or modify
10870+ * it under the terms of the GNU General Public License as published by
10871+ * the Free Software Foundation; either version 2 of the License, or
10872+ * (at your option) any later version.
dece6358
AM
10873+ *
10874+ * This program is distributed in the hope that it will be useful,
10875+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10876+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10877+ * GNU General Public License for more details.
10878+ *
10879+ * You should have received a copy of the GNU General Public License
10880+ * along with this program; if not, write to the Free Software
10881+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10882+ */
10883+
10884+/*
dece6358 10885+ * inode operations (add entry)
1facf9fc 10886+ */
10887+
10888+#include "aufs.h"
10889+
10890+/*
dece6358
AM
10891+ * final procedure of adding a new entry, except link(2).
10892+ * remove whiteout, instantiate, copyup the parent dir's times and size
10893+ * and update version.
10894+ * if it failed, re-create the removed whiteout.
1facf9fc 10895+ */
dece6358
AM
10896+static int epilog(struct inode *dir, aufs_bindex_t bindex,
10897+ struct dentry *wh_dentry, struct dentry *dentry)
1facf9fc 10898+{
dece6358
AM
10899+ int err, rerr;
10900+ aufs_bindex_t bwh;
10901+ struct path h_path;
10902+ struct inode *inode, *h_dir;
10903+ struct dentry *wh;
1facf9fc 10904+
dece6358
AM
10905+ bwh = -1;
10906+ if (wh_dentry) {
10907+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
10908+ IMustLock(h_dir);
10909+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
10910+ bwh = au_dbwh(dentry);
10911+ h_path.dentry = wh_dentry;
10912+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
10913+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
10914+ dentry);
1facf9fc 10915+ if (unlikely(err))
10916+ goto out;
dece6358 10917+ }
1facf9fc 10918+
dece6358
AM
10919+ inode = au_new_inode(dentry, /*must_new*/1);
10920+ if (!IS_ERR(inode)) {
10921+ d_instantiate(dentry, inode);
10922+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
10923+ IMustLock(dir);
10924+ if (au_ibstart(dir) == au_dbstart(dentry))
10925+ au_cpup_attr_timesizes(dir);
10926+ dir->i_version++;
10927+ return 0; /* success */
1facf9fc 10928+ }
dece6358
AM
10929+
10930+ err = PTR_ERR(inode);
10931+ if (!wh_dentry)
10932+ goto out;
10933+
10934+ /* revert */
10935+ /* dir inode is locked */
10936+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
10937+ rerr = PTR_ERR(wh);
10938+ if (IS_ERR(wh)) {
10939+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
10940+ AuDLNPair(dentry), err, rerr);
10941+ err = -EIO;
10942+ } else
10943+ dput(wh);
1facf9fc 10944+
10945+ out:
10946+ return err;
10947+}
10948+
10949+/*
dece6358 10950+ * simple tests for the adding inode operations.
1facf9fc 10951+ * following the checks in vfs, plus the parent-child relationship.
10952+ */
dece6358 10953+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
1facf9fc 10954+ struct dentry *h_parent, int isdir)
10955+{
10956+ int err;
10957+ umode_t h_mode;
dece6358 10958+ struct dentry *h_dentry;
1facf9fc 10959+ struct inode *h_inode;
10960+
10961+ h_dentry = au_h_dptr(dentry, bindex);
10962+ h_inode = h_dentry->d_inode;
dece6358
AM
10963+ if (!dentry->d_inode) {
10964+ err = -EEXIST;
10965+ if (unlikely(h_inode))
10966+ goto out;
10967+ } else {
10968+ /* rename(2) case */
10969+ err = -EIO;
1facf9fc 10970+ if (unlikely(!h_inode || !h_inode->i_nlink))
10971+ goto out;
10972+
10973+ h_mode = h_inode->i_mode;
10974+ if (!isdir) {
10975+ err = -EISDIR;
10976+ if (unlikely(S_ISDIR(h_mode)))
dece6358
AM
10977+ goto out;
10978+ } else if (unlikely(!S_ISDIR(h_mode))) {
10979+ err = -ENOTDIR;
10980+ goto out;
10981+ }
10982+ }
1facf9fc 10983+
1facf9fc 10984+ err = -EIO;
dece6358
AM
10985+ /* expected parent dir is locked */
10986+ if (unlikely(h_parent != h_dentry->d_parent))
1facf9fc 10987+ goto out;
dece6358 10988+ err = 0;
1facf9fc 10989+
10990+ out:
10991+ return err;
10992+}
10993+
10994+/*
dece6358
AM
10995+ * initial procedure of adding a new entry.
10996+ * prepare writable branch and the parent dir, lock it,
10997+ * and lookup whiteout for the new entry.
1facf9fc 10998+ */
10999+static struct dentry*
dece6358
AM
11000+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
11001+ struct dentry *src_dentry, struct au_pin *pin,
11002+ struct au_wr_dir_args *wr_dir_args)
1facf9fc 11003+{
dece6358 11004+ struct dentry *wh_dentry, *h_parent;
1facf9fc 11005+ struct super_block *sb;
dece6358
AM
11006+ struct au_branch *br;
11007+ int err;
1facf9fc 11008+ unsigned int udba;
11009+ aufs_bindex_t bcpup;
11010+
dece6358
AM
11011+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
11012+ bcpup = err;
11013+ wh_dentry = ERR_PTR(err);
11014+ if (unlikely(err < 0))
1facf9fc 11015+ goto out;
11016+
11017+ sb = dentry->d_sb;
11018+ udba = au_opt_udba(sb);
1facf9fc 11019+ err = au_pin(pin, dentry, bcpup, udba,
11020+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
11021+ wh_dentry = ERR_PTR(err);
11022+ if (unlikely(err))
11023+ goto out;
11024+
dece6358 11025+ h_parent = au_pinned_h_parent(pin);
1facf9fc 11026+ if (udba != AuOpt_UDBA_NONE
11027+ && au_dbstart(dentry) == bcpup) {
dece6358
AM
11028+ err = au_may_add(dentry, bcpup, h_parent,
11029+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
1facf9fc 11030+ wh_dentry = ERR_PTR(err);
11031+ if (unlikely(err))
11032+ goto out_unpin;
11033+ }
11034+
dece6358
AM
11035+ br = au_sbr(sb, bcpup);
11036+ if (dt) {
11037+ struct path tmp = {
11038+ .dentry = h_parent,
11039+ .mnt = br->br_mnt
11040+ };
11041+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
11042+ }
1facf9fc 11043+
dece6358
AM
11044+ wh_dentry = NULL;
11045+ if (bcpup != au_dbwh(dentry))
1facf9fc 11046+ goto out; /* success */
dece6358
AM
11047+
11048+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
1facf9fc 11049+
11050+ out_unpin:
dece6358
AM
11051+ if (IS_ERR(wh_dentry))
11052+ au_unpin(pin);
1facf9fc 11053+ out:
11054+ return wh_dentry;
11055+}
11056+
dece6358
AM
11057+/* ---------------------------------------------------------------------- */
11058+
11059+enum { Mknod, Symlink, Creat };
11060+struct simple_arg {
11061+ int type;
11062+ union {
11063+ struct {
11064+ int mode;
11065+ struct nameidata *nd;
11066+ } c;
11067+ struct {
11068+ const char *symname;
11069+ } s;
11070+ struct {
11071+ int mode;
11072+ dev_t dev;
11073+ } m;
11074+ } u;
11075+};
11076+
11077+static int add_simple(struct inode *dir, struct dentry *dentry,
11078+ struct simple_arg *arg)
1facf9fc 11079+{
dece6358
AM
11080+ int err;
11081+ aufs_bindex_t bstart;
11082+ unsigned char created;
11083+ struct au_dtime dt;
11084+ struct au_pin pin;
11085+ struct path h_path;
11086+ struct dentry *wh_dentry, *parent;
11087+ struct inode *h_dir;
11088+ struct au_wr_dir_args wr_dir_args = {
11089+ .force_btgt = -1,
11090+ .flags = AuWrDir_ADD_ENTRY
11091+ };
1facf9fc 11092+
dece6358 11093+ IMustLock(dir);
1facf9fc 11094+
dece6358
AM
11095+ parent = dentry->d_parent; /* dir inode is locked */
11096+ aufs_read_lock(dentry, AuLock_DW);
11097+ di_write_lock_parent(parent);
11098+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
11099+ &wr_dir_args);
11100+ err = PTR_ERR(wh_dentry);
11101+ if (IS_ERR(wh_dentry))
11102+ goto out;
1facf9fc 11103+
dece6358
AM
11104+ bstart = au_dbstart(dentry);
11105+ h_path.dentry = au_h_dptr(dentry, bstart);
11106+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
11107+ h_dir = au_pinned_h_dir(&pin);
11108+ switch (arg->type) {
11109+ case Creat:
11110+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
11111+ break;
11112+ case Symlink:
11113+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
11114+ break;
11115+ case Mknod:
11116+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
11117+ break;
11118+ default:
11119+ BUG();
1facf9fc 11120+ }
dece6358
AM
11121+ created = !err;
11122+ if (!err)
11123+ err = epilog(dir, bstart, wh_dentry, dentry);
1facf9fc 11124+
dece6358
AM
11125+ /* revert */
11126+ if (unlikely(created && err && h_path.dentry->d_inode)) {
11127+ int rerr;
11128+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
11129+ if (rerr) {
11130+ AuIOErr("%.*s revert failure(%d, %d)\n",
11131+ AuDLNPair(dentry), err, rerr);
11132+ err = -EIO;
11133+ }
11134+ au_dtime_revert(&dt);
11135+ d_drop(dentry);
1facf9fc 11136+ }
11137+
dece6358
AM
11138+ au_unpin(&pin);
11139+ dput(wh_dentry);
11140+
1facf9fc 11141+ out:
dece6358
AM
11142+ if (unlikely(err)) {
11143+ au_update_dbstart(dentry);
11144+ d_drop(dentry);
11145+ }
11146+ di_write_unlock(parent);
11147+ aufs_read_unlock(dentry, AuLock_DW);
1facf9fc 11148+ return err;
11149+}
11150+
dece6358 11151+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
1facf9fc 11152+{
dece6358
AM
11153+ struct simple_arg arg = {
11154+ .type = Mknod,
11155+ .u.m = {
11156+ .mode = mode,
11157+ .dev = dev
11158+ }
11159+ };
11160+ return add_simple(dir, dentry, &arg);
11161+}
1facf9fc 11162+
dece6358
AM
11163+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
11164+{
11165+ struct simple_arg arg = {
11166+ .type = Symlink,
11167+ .u.s.symname = symname
11168+ };
11169+ return add_simple(dir, dentry, &arg);
11170+}
11171+
11172+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
11173+ struct nameidata *nd)
11174+{
11175+ struct simple_arg arg = {
11176+ .type = Creat,
11177+ .u.c = {
11178+ .mode = mode,
11179+ .nd = nd
11180+ }
11181+ };
11182+ return add_simple(dir, dentry, &arg);
11183+}
11184+
11185+/* ---------------------------------------------------------------------- */
11186+
11187+struct au_link_args {
11188+ aufs_bindex_t bdst, bsrc;
11189+ struct au_pin pin;
11190+ struct path h_path;
11191+ struct dentry *src_parent, *parent;
11192+};
11193+
11194+static int au_cpup_before_link(struct dentry *src_dentry,
11195+ struct au_link_args *a)
11196+{
11197+ int err;
11198+ struct dentry *h_src_dentry;
11199+ struct mutex *h_mtx;
11200+
11201+ di_read_lock_parent(a->src_parent, AuLock_IR);
11202+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
11203+ if (unlikely(err))
11204+ goto out;
11205+
11206+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
11207+ h_mtx = &h_src_dentry->d_inode->i_mutex;
11208+ err = au_pin(&a->pin, src_dentry, a->bdst,
11209+ au_opt_udba(src_dentry->d_sb),
11210+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
11211+ if (unlikely(err))
11212+ goto out;
11213+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11214+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
11215+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
11216+ mutex_unlock(h_mtx);
11217+ au_unpin(&a->pin);
1facf9fc 11218+
dece6358
AM
11219+ out:
11220+ di_read_unlock(a->src_parent, AuLock_IR);
11221+ return err;
1facf9fc 11222+}
11223+
dece6358 11224+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
1facf9fc 11225+{
dece6358
AM
11226+ int err;
11227+ unsigned char plink;
11228+ struct inode *h_inode, *inode;
11229+ struct dentry *h_src_dentry;
11230+ struct super_block *sb;
1facf9fc 11231+
dece6358
AM
11232+ plink = 0;
11233+ h_inode = NULL;
11234+ sb = src_dentry->d_sb;
11235+ inode = src_dentry->d_inode;
11236+ if (au_ibstart(inode) <= a->bdst)
11237+ h_inode = au_h_iptr(inode, a->bdst);
11238+ if (!h_inode || !h_inode->i_nlink) {
11239+ /* copyup src_dentry as the name of dentry. */
11240+ au_set_dbstart(src_dentry, a->bdst);
11241+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
11242+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
11243+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
11244+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
11245+ AuCpup_KEEPLINO, a->parent);
11246+ mutex_unlock(&h_inode->i_mutex);
11247+ au_set_h_dptr(src_dentry, a->bdst, NULL);
11248+ au_set_dbstart(src_dentry, a->bsrc);
11249+ } else {
11250+ /* the inode of src_dentry already exists on a.bdst branch */
11251+ h_src_dentry = d_find_alias(h_inode);
11252+ if (!h_src_dentry && au_plink_test(inode)) {
11253+ plink = 1;
11254+ h_src_dentry = au_plink_lkup(inode, a->bdst);
11255+ err = PTR_ERR(h_src_dentry);
11256+ if (IS_ERR(h_src_dentry))
11257+ goto out;
11258+
11259+ if (unlikely(!h_src_dentry->d_inode)) {
11260+ dput(h_src_dentry);
11261+ h_src_dentry = NULL;
11262+ }
11263+
11264+ }
11265+ if (h_src_dentry) {
11266+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
11267+ &a->h_path);
11268+ dput(h_src_dentry);
11269+ } else {
11270+ AuIOErr("no dentry found for hi%lu on b%d\n",
11271+ h_inode->i_ino, a->bdst);
11272+ err = -EIO;
11273+ }
1facf9fc 11274+ }
11275+
dece6358
AM
11276+ if (!err && !plink)
11277+ au_plink_append(inode, a->bdst, a->h_path.dentry);
1facf9fc 11278+
dece6358
AM
11279+out:
11280+ return err;
11281+}
1facf9fc 11282+
dece6358
AM
11283+int aufs_link(struct dentry *src_dentry, struct inode *dir,
11284+ struct dentry *dentry)
1facf9fc 11285+{
dece6358 11286+ int err, rerr;
1facf9fc 11287+ struct au_dtime dt;
dece6358
AM
11288+ struct au_link_args *a;
11289+ struct dentry *wh_dentry, *h_src_dentry;
11290+ struct inode *inode;
11291+ struct super_block *sb;
11292+ struct au_wr_dir_args wr_dir_args = {
11293+ /* .force_btgt = -1, */
11294+ .flags = AuWrDir_ADD_ENTRY
11295+ };
1facf9fc 11296+
11297+ IMustLock(dir);
dece6358 11298+ inode = src_dentry->d_inode;
1facf9fc 11299+ IMustLock(inode);
11300+
dece6358
AM
11301+ err = -ENOENT;
11302+ if (unlikely(!inode->i_nlink))
11303+ goto out;
1facf9fc 11304+
dece6358
AM
11305+ err = -ENOMEM;
11306+ a = kzalloc(sizeof(*a), GFP_NOFS);
11307+ if (unlikely(!a))
1facf9fc 11308+ goto out;
11309+
dece6358
AM
11310+ a->parent = dentry->d_parent; /* dir inode is locked */
11311+ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
11312+ a->src_parent = dget_parent(src_dentry);
11313+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
1facf9fc 11314+
dece6358
AM
11315+ di_write_lock_parent(a->parent);
11316+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
11317+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
11318+ &wr_dir_args);
11319+ err = PTR_ERR(wh_dentry);
11320+ if (IS_ERR(wh_dentry))
11321+ goto out_unlock;
1facf9fc 11322+
dece6358
AM
11323+ err = 0;
11324+ sb = dentry->d_sb;
11325+ a->bdst = au_dbstart(dentry);
11326+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
11327+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
11328+ a->bsrc = au_dbstart(src_dentry);
11329+ if (au_opt_test(au_mntflags(sb), PLINK)) {
11330+ if (a->bdst < a->bsrc
11331+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
11332+ err = au_cpup_or_link(src_dentry, a);
11333+ else {
11334+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
11335+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
11336+ &a->h_path);
11337+ }
11338+ } else {
11339+ /*
11340+ * copyup src_dentry to the branch we process,
11341+ * and then link(2) to it.
11342+ */
11343+ if (a->bdst < a->bsrc
11344+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
11345+ au_unpin(&a->pin);
11346+ di_write_unlock(a->parent);
11347+ err = au_cpup_before_link(src_dentry, a);
11348+ if (!err) {
11349+ di_write_lock_parent(a->parent);
11350+ err = au_pin(&a->pin, dentry, a->bdst,
11351+ au_opt_udba(sb),
11352+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
11353+ if (unlikely(err))
11354+ goto out_wh;
11355+ }
11356+ }
11357+ if (!err) {
11358+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
11359+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
11360+ &a->h_path);
11361+ }
1facf9fc 11362+ }
dece6358
AM
11363+ if (unlikely(err))
11364+ goto out_unpin;
1facf9fc 11365+
1facf9fc 11366+ if (wh_dentry) {
dece6358
AM
11367+ a->h_path.dentry = wh_dentry;
11368+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
11369+ dentry);
11370+ if (unlikely(err))
11371+ goto out_revert;
1facf9fc 11372+ }
11373+
dece6358
AM
11374+ dir->i_version++;
11375+ if (au_ibstart(dir) == au_dbstart(dentry))
11376+ au_cpup_attr_timesizes(dir);
11377+ inc_nlink(inode);
11378+ inode->i_ctime = dir->i_ctime;
11379+ if (!d_unhashed(a->h_path.dentry))
11380+ d_instantiate(dentry, au_igrab(inode));
11381+ else
11382+ /* some filesystem calls d_drop() */
11383+ d_drop(dentry);
11384+ goto out_unpin; /* success */
11385+
11386+ out_revert:
11387+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
11388+ if (!rerr)
11389+ goto out_dt;
11390+ AuIOErr("%.*s reverting failed(%d, %d)\n",
11391+ AuDLNPair(dentry), err, rerr);
11392+ err = -EIO;
11393+ out_dt:
11394+ d_drop(dentry);
11395+ au_dtime_revert(&dt);
11396+ out_unpin:
11397+ au_unpin(&a->pin);
11398+ out_wh:
1facf9fc 11399+ dput(wh_dentry);
dece6358
AM
11400+ out_unlock:
11401+ if (unlikely(err)) {
11402+ au_update_dbstart(dentry);
11403+ d_drop(dentry);
11404+ }
11405+ di_write_unlock(a->parent);
11406+ dput(a->src_parent);
11407+ aufs_read_and_write_unlock2(dentry, src_dentry);
11408+ kfree(a);
1facf9fc 11409+ out:
1facf9fc 11410+ return err;
11411+}
11412+
dece6358
AM
11413+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
11414+{
11415+ int err, rerr;
11416+ aufs_bindex_t bindex;
11417+ unsigned char diropq;
1facf9fc 11418+ struct au_pin pin;
dece6358
AM
11419+ struct path h_path;
11420+ struct dentry *wh_dentry, *parent, *opq_dentry;
11421+ struct mutex *h_mtx;
11422+ struct super_block *sb;
11423+ struct au_dtime dt;
11424+ struct au_wr_dir_args wr_dir_args = {
11425+ .force_btgt = -1,
11426+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
11427+ };
1facf9fc 11428+
11429+ IMustLock(dir);
1facf9fc 11430+
dece6358 11431+ aufs_read_lock(dentry, AuLock_DW);
1facf9fc 11432+ parent = dentry->d_parent; /* dir inode is locked */
11433+ di_write_lock_parent(parent);
dece6358
AM
11434+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
11435+ &wr_dir_args);
1facf9fc 11436+ err = PTR_ERR(wh_dentry);
11437+ if (IS_ERR(wh_dentry))
dece6358 11438+ goto out;
1facf9fc 11439+
dece6358
AM
11440+ sb = dentry->d_sb;
11441+ bindex = au_dbstart(dentry);
11442+ h_path.dentry = au_h_dptr(dentry, bindex);
11443+ h_path.mnt = au_sbr_mnt(sb, bindex);
11444+ err = vfsub_mkdir(au_pinned_h_dir(&pin), &h_path, mode);
11445+ if (unlikely(err))
11446+ goto out_unlock;
1facf9fc 11447+
dece6358
AM
11448+ /* make the dir opaque */
11449+ diropq = 0;
11450+ h_mtx = &h_path.dentry->d_inode->i_mutex;
11451+ if (wh_dentry
11452+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
11453+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11454+ opq_dentry = au_diropq_create(dentry, bindex);
11455+ mutex_unlock(h_mtx);
11456+ err = PTR_ERR(opq_dentry);
11457+ if (IS_ERR(opq_dentry))
11458+ goto out_dir;
11459+ dput(opq_dentry);
11460+ diropq = 1;
1facf9fc 11461+ }
11462+
dece6358 11463+ err = epilog(dir, bindex, wh_dentry, dentry);
1facf9fc 11464+ if (!err) {
dece6358 11465+ inc_nlink(dir);
1facf9fc 11466+ goto out_unlock; /* success */
11467+ }
11468+
11469+ /* revert */
dece6358
AM
11470+ if (diropq) {
11471+ AuLabel(revert opq);
11472+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11473+ rerr = au_diropq_remove(dentry, bindex);
11474+ mutex_unlock(h_mtx);
11475+ if (rerr) {
11476+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
11477+ AuDLNPair(dentry), err, rerr);
11478+ err = -EIO;
11479+ }
1facf9fc 11480+ }
11481+
dece6358
AM
11482+ out_dir:
11483+ AuLabel(revert dir);
11484+ rerr = vfsub_rmdir(au_pinned_h_dir(&pin), &h_path);
11485+ if (rerr) {
11486+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
11487+ AuDLNPair(dentry), err, rerr);
11488+ err = -EIO;
11489+ }
11490+ d_drop(dentry);
11491+ au_dtime_revert(&dt);
1facf9fc 11492+ out_unlock:
11493+ au_unpin(&pin);
11494+ dput(wh_dentry);
dece6358
AM
11495+ out:
11496+ if (unlikely(err)) {
11497+ au_update_dbstart(dentry);
11498+ d_drop(dentry);
11499+ }
1facf9fc 11500+ di_write_unlock(parent);
11501+ aufs_read_unlock(dentry, AuLock_DW);
1facf9fc 11502+ return err;
11503+}
dece6358
AM
11504diff -urN linux-2.6.30.org/fs/aufs/i_op.c linux-2.6.30/fs/aufs/i_op.c
11505--- linux-2.6.30.org/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
11506+++ linux-2.6.30/fs/aufs/i_op.c 2009-07-21 08:54:19.000000000 +0200
11507@@ -0,0 +1,877 @@
1facf9fc 11508+/*
11509+ * Copyright (C) 2005-2009 Junjiro R. Okajima
11510+ *
11511+ * This program, aufs is free software; you can redistribute it and/or modify
11512+ * it under the terms of the GNU General Public License as published by
11513+ * the Free Software Foundation; either version 2 of the License, or
11514+ * (at your option) any later version.
dece6358
AM
11515+ *
11516+ * This program is distributed in the hope that it will be useful,
11517+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11518+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11519+ * GNU General Public License for more details.
11520+ *
11521+ * You should have received a copy of the GNU General Public License
11522+ * along with this program; if not, write to the Free Software
11523+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 11524+ */
11525+
11526+/*
dece6358 11527+ * inode operations (except add/del/rename)
1facf9fc 11528+ */
11529+
dece6358
AM
11530+#include <linux/device_cgroup.h>
11531+#include <linux/fs_stack.h>
11532+#include <linux/mm.h>
11533+#include <linux/namei.h>
11534+#include <linux/security.h>
11535+#include <linux/uaccess.h>
11536+#include "aufs.h"
1facf9fc 11537+
dece6358
AM
11538+static int h_permission(struct inode *h_inode, int mask,
11539+ struct vfsmount *h_mnt, int brperm)
1facf9fc 11540+{
dece6358
AM
11541+ int err;
11542+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 11543+
dece6358
AM
11544+ err = -EACCES;
11545+ if ((write_mask && IS_IMMUTABLE(h_inode))
11546+ || ((mask & MAY_EXEC)
11547+ && S_ISREG(h_inode->i_mode)
11548+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
11549+ || !(h_inode->i_mode & S_IXUGO))))
11550+ goto out;
11551+
11552+ /*
11553+ * - skip the lower fs test in the case of write to ro branch.
11554+ * - nfs dir permission write check is optimized, but a policy for
11555+ * link/rename requires a real check.
11556+ */
11557+ if ((write_mask && !au_br_writable(brperm))
11558+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
11559+ && write_mask && !(mask & MAY_READ))
11560+ || !h_inode->i_op->permission) {
11561+ /* AuLabel(generic_permission); */
11562+ err = generic_permission(h_inode, mask, NULL);
11563+ } else {
11564+ /* AuLabel(h_inode->permission); */
11565+ err = h_inode->i_op->permission(h_inode, mask);
11566+ AuTraceErr(err);
1facf9fc 11567+ }
11568+
dece6358
AM
11569+ if (!err)
11570+ err = devcgroup_inode_permission(h_inode, mask);
11571+ if (!err)
11572+ err = security_inode_permission
11573+ (h_inode, mask & (MAY_READ | MAY_WRITE | MAY_EXEC
11574+ | MAY_APPEND));
11575+
11576+ out:
11577+ return err;
1facf9fc 11578+}
11579+
dece6358 11580+static int aufs_permission(struct inode *inode, int mask)
1facf9fc 11581+{
dece6358
AM
11582+ int err;
11583+ aufs_bindex_t bindex, bend;
11584+ const unsigned char isdir = !!S_ISDIR(inode->i_mode);
11585+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
11586+ struct inode *h_inode;
11587+ struct super_block *sb;
11588+ struct au_branch *br;
1facf9fc 11589+
dece6358
AM
11590+ sb = inode->i_sb;
11591+ si_read_lock(sb, AuLock_FLUSH);
11592+ ii_read_lock_child(inode);
1facf9fc 11593+
dece6358
AM
11594+ if (!isdir || write_mask) {
11595+ h_inode = au_h_iptr(inode, au_ibstart(inode));
11596+ AuDebugOn(!h_inode
11597+ || ((h_inode->i_mode & S_IFMT)
11598+ != (inode->i_mode & S_IFMT)));
11599+ err = 0;
11600+ bindex = au_ibstart(inode);
11601+ br = au_sbr(sb, bindex);
11602+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
1facf9fc 11603+
dece6358
AM
11604+ if (write_mask && !err) {
11605+ /* test whether the upper writable branch exists */
11606+ err = -EROFS;
11607+ for (; bindex >= 0; bindex--)
11608+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
11609+ err = 0;
11610+ break;
11611+ }
1facf9fc 11612+ }
dece6358 11613+ goto out;
1facf9fc 11614+ }
11615+
dece6358
AM
11616+ /* non-write to dir */
11617+ err = 0;
11618+ bend = au_ibend(inode);
11619+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
11620+ h_inode = au_h_iptr(inode, bindex);
11621+ if (h_inode) {
11622+ AuDebugOn(!S_ISDIR(h_inode->i_mode));
11623+ br = au_sbr(sb, bindex);
11624+ err = h_permission(h_inode, mask, br->br_mnt,
11625+ br->br_perm);
11626+ }
11627+ }
11628+
11629+ out:
11630+ ii_read_unlock(inode);
11631+ si_read_unlock(sb);
11632+ return err;
1facf9fc 11633+}
1facf9fc 11634+
11635+/* ---------------------------------------------------------------------- */
11636+
dece6358
AM
11637+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
11638+ struct nameidata *nd)
1facf9fc 11639+{
dece6358
AM
11640+ struct dentry *ret, *parent;
11641+ struct inode *inode, *h_inode;
11642+ struct mutex *mtx;
11643+ struct super_block *sb;
11644+ int err, npositive;
11645+ aufs_bindex_t bstart;
1facf9fc 11646+
dece6358
AM
11647+ /* temporary workaround for a bug in NFSD readdir */
11648+ if (!au_test_nfsd(current))
11649+ IMustLock(dir);
11650+ else
11651+ WARN_ONCE(!mutex_is_locked(&dir->i_mutex),
11652+ "a known problem of NFSD readdir since 2.6.28\n");
1facf9fc 11653+
dece6358
AM
11654+ sb = dir->i_sb;
11655+ si_read_lock(sb, AuLock_FLUSH);
11656+ err = au_alloc_dinfo(dentry);
11657+ ret = ERR_PTR(err);
11658+ if (unlikely(err))
11659+ goto out;
11660+
11661+ parent = dentry->d_parent; /* dir inode is locked */
11662+ di_read_lock_parent(parent, AuLock_IR);
11663+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
11664+ di_read_unlock(parent, AuLock_IR);
11665+ err = npositive;
11666+ ret = ERR_PTR(err);
11667+ if (unlikely(err < 0))
11668+ goto out_unlock;
11669+
11670+ inode = NULL;
11671+ if (npositive) {
11672+ bstart = au_dbstart(dentry);
11673+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
11674+ if (!S_ISDIR(h_inode->i_mode)) {
11675+ /*
11676+ * stop 'race'-ing between hardlinks under different
11677+ * parents.
11678+ */
11679+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
11680+ mutex_lock(mtx);
11681+ inode = au_new_inode(dentry, /*must_new*/0);
11682+ mutex_unlock(mtx);
11683+ } else
11684+ inode = au_new_inode(dentry, /*must_new*/0);
11685+ ret = (void *)inode;
1facf9fc 11686+ }
dece6358
AM
11687+ if (IS_ERR(inode))
11688+ goto out_unlock;
1facf9fc 11689+
dece6358
AM
11690+ ret = d_splice_alias(inode, dentry);
11691+ if (unlikely(IS_ERR(ret) && inode))
11692+ ii_write_unlock(inode);
11693+ au_store_oflag(nd, inode);
11694+
11695+ out_unlock:
11696+ di_write_unlock(dentry);
11697+ out:
11698+ si_read_unlock(sb);
11699+ return ret;
1facf9fc 11700+}
11701+
dece6358
AM
11702+/* ---------------------------------------------------------------------- */
11703+
11704+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
11705+ const unsigned char add_entry, aufs_bindex_t bcpup,
11706+ aufs_bindex_t bstart)
1facf9fc 11707+{
11708+ int err;
dece6358
AM
11709+ struct dentry *h_parent;
11710+ struct inode *h_dir;
1facf9fc 11711+
dece6358
AM
11712+ if (add_entry) {
11713+ au_update_dbstart(dentry);
11714+ IMustLock(parent->d_inode);
11715+ } else
11716+ di_write_lock_parent(parent);
11717+
11718+ err = 0;
11719+ if (!au_h_dptr(parent, bcpup)) {
11720+ if (bstart < bcpup)
11721+ err = au_cpdown_dirs(dentry, bcpup);
11722+ else
11723+ err = au_cpup_dirs(dentry, bcpup);
11724+ }
11725+ if (!err && add_entry) {
11726+ h_parent = au_h_dptr(parent, bcpup);
11727+ h_dir = h_parent->d_inode;
11728+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
11729+ err = au_lkup_neg(dentry, bcpup);
11730+ /* todo: no unlock here */
11731+ mutex_unlock(&h_dir->i_mutex);
11732+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
11733+ au_set_dbstart(dentry, 0);
11734+ au_update_dbrange(dentry, /*do_put_zero*/0);
11735+ }
1facf9fc 11736+ }
11737+
dece6358
AM
11738+ if (!add_entry)
11739+ di_write_unlock(parent);
11740+ if (!err)
11741+ err = bcpup; /* success */
1facf9fc 11742+
11743+ return err;
11744+}
11745+
dece6358
AM
11746+/*
11747+ * decide the branch and the parent dir where we will create a new entry.
11748+ * returns new bindex or an error.
11749+ * copyup the parent dir if needed.
11750+ */
11751+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
11752+ struct au_wr_dir_args *args)
1facf9fc 11753+{
11754+ int err;
dece6358
AM
11755+ aufs_bindex_t bcpup, bstart, src_bstart;
11756+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
11757+ ADD_ENTRY);
11758+ struct super_block *sb;
11759+ struct dentry *parent;
11760+ struct au_sbinfo *sbinfo;
1facf9fc 11761+
dece6358
AM
11762+ sb = dentry->d_sb;
11763+ sbinfo = au_sbi(sb);
11764+ parent = dget_parent(dentry);
11765+ bstart = au_dbstart(dentry);
11766+ bcpup = bstart;
11767+ if (args->force_btgt < 0) {
11768+ if (src_dentry) {
11769+ src_bstart = au_dbstart(src_dentry);
11770+ if (src_bstart < bstart)
11771+ bcpup = src_bstart;
11772+ } else if (add_entry) {
11773+ err = AuWbrCreate(sbinfo, dentry,
11774+ au_ftest_wrdir(args->flags, ISDIR));
11775+ bcpup = err;
11776+ }
1facf9fc 11777+
dece6358
AM
11778+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
11779+ if (add_entry)
11780+ err = AuWbrCopyup(sbinfo, dentry);
11781+ else {
11782+ if (!IS_ROOT(dentry)) {
11783+ di_read_lock_parent(parent, !AuLock_IR);
11784+ err = AuWbrCopyup(sbinfo, dentry);
11785+ di_read_unlock(parent, !AuLock_IR);
11786+ } else
11787+ err = AuWbrCopyup(sbinfo, dentry);
11788+ }
11789+ bcpup = err;
11790+ if (unlikely(err < 0))
11791+ goto out;
11792+ }
11793+ } else {
11794+ bcpup = args->force_btgt;
11795+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1facf9fc 11796+ }
dece6358
AM
11797+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
11798+ if (bstart < bcpup)
11799+ au_update_dbrange(dentry, /*do_put_zero*/1);
1facf9fc 11800+
dece6358
AM
11801+ err = bcpup;
11802+ if (bcpup == bstart)
11803+ goto out; /* success */
1facf9fc 11804+
dece6358
AM
11805+ /* copyup the new parent into the branch we process */
11806+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
1facf9fc 11807+
dece6358
AM
11808+ out:
11809+ dput(parent);
11810+ return err;
11811+}
1facf9fc 11812+
dece6358 11813+/* ---------------------------------------------------------------------- */
1facf9fc 11814+
dece6358
AM
11815+struct dentry *au_pinned_h_parent(struct au_pin *pin)
11816+{
11817+ if (pin && pin->parent)
11818+ return au_h_dptr(pin->parent, pin->bindex);
11819+ return NULL;
11820+}
1facf9fc 11821+
dece6358
AM
11822+void au_unpin(struct au_pin *p)
11823+{
11824+ if (au_ftest_pin(p->flags, MNT_WRITE))
11825+ mnt_drop_write(p->h_mnt);
11826+ if (!p->hdir)
11827+ return;
1facf9fc 11828+
dece6358
AM
11829+ au_hin_imtx_unlock(p->hdir);
11830+ if (!au_ftest_pin(p->flags, DI_LOCKED))
11831+ di_read_unlock(p->parent, AuLock_IR);
11832+ iput(p->hdir->hi_inode);
11833+ dput(p->parent);
11834+ p->parent = NULL;
11835+ p->hdir = NULL;
11836+ p->h_mnt = NULL;
11837+}
1facf9fc 11838+
dece6358
AM
11839+int au_do_pin(struct au_pin *p)
11840+{
11841+ int err;
11842+ struct super_block *sb;
11843+ struct dentry *h_dentry, *h_parent;
11844+ struct au_branch *br;
11845+ struct inode *h_dir;
1facf9fc 11846+
dece6358
AM
11847+ err = 0;
11848+ sb = p->dentry->d_sb;
11849+ br = au_sbr(sb, p->bindex);
11850+ if (IS_ROOT(p->dentry)) {
11851+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
11852+ p->h_mnt = br->br_mnt;
11853+ err = mnt_want_write(p->h_mnt);
11854+ if (unlikely(err)) {
11855+ au_fclr_pin(p->flags, MNT_WRITE);
11856+ goto out_err;
11857+ }
11858+ }
11859+ goto out;
1facf9fc 11860+ }
11861+
dece6358
AM
11862+ h_dentry = NULL;
11863+ if (p->bindex <= au_dbend(p->dentry))
11864+ h_dentry = au_h_dptr(p->dentry, p->bindex);
1facf9fc 11865+
dece6358
AM
11866+ p->parent = dget_parent(p->dentry);
11867+ if (!au_ftest_pin(p->flags, DI_LOCKED))
11868+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
1facf9fc 11869+
dece6358
AM
11870+ h_dir = NULL;
11871+ h_parent = au_h_dptr(p->parent, p->bindex);
11872+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
11873+ if (p->hdir)
11874+ h_dir = p->hdir->hi_inode;
11875+
11876+ /* udba case */
11877+ if (unlikely(!p->hdir || !h_dir)) {
11878+ if (!au_ftest_pin(p->flags, DI_LOCKED))
11879+ di_read_unlock(p->parent, AuLock_IR);
11880+ dput(p->parent);
11881+ p->parent = NULL;
11882+ goto out_err;
11883+ }
11884+
11885+ au_igrab(h_dir);
11886+ au_hin_imtx_lock_nested(p->hdir, p->lsc_hi);
11887+
11888+ if (h_dentry) {
11889+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
11890+ if (unlikely(err)) {
11891+ au_fclr_pin(p->flags, MNT_WRITE);
11892+ goto out_unpin;
11893+ }
1facf9fc 11894+ }
dece6358
AM
11895+
11896+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
11897+ p->h_mnt = br->br_mnt;
11898+ err = mnt_want_write(p->h_mnt);
11899+ if (unlikely(err)) {
11900+ au_fclr_pin(p->flags, MNT_WRITE);
11901+ goto out_unpin;
11902+ }
11903+ }
11904+ goto out; /* success */
11905+
11906+ out_unpin:
11907+ au_unpin(p);
11908+ out_err:
11909+ AuErr("err %d\n", err);
11910+ err = au_busy_or_stale();
1facf9fc 11911+ out:
11912+ return err;
11913+}
11914+
dece6358
AM
11915+void au_pin_init(struct au_pin *p, struct dentry *dentry,
11916+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
11917+ unsigned int udba, unsigned char flags)
11918+{
11919+ p->dentry = dentry;
11920+ p->udba = udba;
11921+ p->lsc_di = lsc_di;
11922+ p->lsc_hi = lsc_hi;
11923+ p->flags = flags;
11924+ p->bindex = bindex;
1facf9fc 11925+
dece6358
AM
11926+ p->parent = NULL;
11927+ p->hdir = NULL;
11928+ p->h_mnt = NULL;
11929+}
11930+
11931+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
11932+ unsigned int udba, unsigned char flags)
1facf9fc 11933+{
dece6358
AM
11934+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
11935+ udba, flags);
11936+ return au_do_pin(pin);
1facf9fc 11937+}
11938+
dece6358
AM
11939+/* ---------------------------------------------------------------------- */
11940+
11941+#define AuIcpup_DID_CPUP 1
11942+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
11943+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
11944+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
11945+
11946+struct au_icpup_args {
11947+ unsigned char flags;
11948+ unsigned char pin_flags;
11949+ aufs_bindex_t btgt;
11950+ struct au_pin pin;
11951+ struct path h_path;
11952+ struct inode *h_inode;
11953+};
11954+
11955+static int au_lock_and_icpup(struct dentry *dentry, struct iattr *ia,
11956+ struct au_icpup_args *a)
1facf9fc 11957+{
11958+ int err;
dece6358
AM
11959+ unsigned int udba;
11960+ loff_t sz;
1facf9fc 11961+ aufs_bindex_t bstart;
dece6358
AM
11962+ struct dentry *hi_wh, *parent;
11963+ struct inode *inode;
11964+ struct au_wr_dir_args wr_dir_args = {
11965+ .force_btgt = -1,
11966+ .flags = 0
11967+ };
1facf9fc 11968+
dece6358 11969+ di_write_lock_child(dentry);
1facf9fc 11970+ bstart = au_dbstart(dentry);
dece6358
AM
11971+ inode = dentry->d_inode;
11972+ if (S_ISDIR(inode->i_mode))
11973+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
11974+ /* plink or hi_wh() case */
11975+ if (bstart != au_ibstart(inode))
11976+ wr_dir_args.force_btgt = au_ibstart(inode);
11977+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
11978+ if (unlikely(err < 0))
11979+ goto out_dentry;
11980+ a->btgt = err;
11981+ if (err != bstart)
11982+ au_fset_icpup(a->flags, DID_CPUP);
1facf9fc 11983+
dece6358
AM
11984+ err = 0;
11985+ a->pin_flags = AuPin_MNT_WRITE;
11986+ parent = NULL;
11987+ if (!IS_ROOT(dentry)) {
11988+ au_fset_pin(a->pin_flags, DI_LOCKED);
11989+ parent = dget_parent(dentry);
11990+ di_write_lock_parent(parent);
1facf9fc 11991+ }
11992+
dece6358
AM
11993+ udba = au_opt_udba(dentry->d_sb);
11994+ if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
11995+ udba = AuOpt_UDBA_NONE;
11996+ err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
11997+ if (unlikely(err)) {
11998+ if (parent) {
11999+ di_write_unlock(parent);
12000+ dput(parent);
12001+ }
12002+ goto out_dentry;
12003+ }
12004+ a->h_path.dentry = au_h_dptr(dentry, bstart);
12005+ a->h_inode = a->h_path.dentry->d_inode;
12006+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
12007+ sz = -1;
12008+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
12009+ sz = ia->ia_size;
1facf9fc 12010+
dece6358
AM
12011+ hi_wh = NULL;
12012+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
12013+ hi_wh = au_hi_wh(inode, a->btgt);
12014+ if (!hi_wh) {
12015+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
12016+ if (unlikely(err))
12017+ goto out_unlock;
12018+ hi_wh = au_hi_wh(inode, a->btgt);
12019+ /* todo: revalidate hi_wh? */
12020+ }
12021+ }
1facf9fc 12022+
dece6358
AM
12023+ if (parent) {
12024+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
12025+ di_downgrade_lock(parent, AuLock_IR);
12026+ dput(parent);
12027+ }
12028+ if (!au_ftest_icpup(a->flags, DID_CPUP))
12029+ goto out; /* success */
12030+
12031+ if (!d_unhashed(dentry)) {
12032+ err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
12033+ if (!err)
12034+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
12035+ } else if (!hi_wh)
12036+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
12037+ else
12038+ a->h_path.dentry = hi_wh; /* do not dget here */
12039+
12040+ out_unlock:
12041+ mutex_unlock(&a->h_inode->i_mutex);
12042+ a->h_inode = a->h_path.dentry->d_inode;
12043+ if (!err) {
12044+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
12045+ goto out; /* success */
1facf9fc 12046+ }
dece6358
AM
12047+
12048+ au_unpin(&a->pin);
12049+
12050+ out_dentry:
12051+ di_write_unlock(dentry);
12052+ out:
1facf9fc 12053+ return err;
12054+}
12055+
dece6358 12056+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 12057+{
12058+ int err;
dece6358
AM
12059+ struct inode *inode;
12060+ struct super_block *sb;
12061+ struct file *file;
12062+ struct au_icpup_args *a;
1facf9fc 12063+
12064+ err = -ENOMEM;
dece6358
AM
12065+ a = kzalloc(sizeof(*a), GFP_NOFS);
12066+ if (unlikely(!a))
1facf9fc 12067+ goto out;
12068+
dece6358
AM
12069+ inode = dentry->d_inode;
12070+ IMustLock(inode);
12071+ sb = dentry->d_sb;
12072+ si_read_lock(sb, AuLock_FLUSH);
12073+
12074+ file = NULL;
12075+ if (ia->ia_valid & ATTR_FILE) {
12076+ /* currently ftruncate(2) only */
12077+ file = ia->ia_file;
12078+ fi_write_lock(file);
12079+ ia->ia_file = au_h_fptr(file, au_fbstart(file));
1facf9fc 12080+ }
1facf9fc 12081+
dece6358
AM
12082+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
12083+ ia->ia_valid &= ~ATTR_MODE;
12084+
12085+ err = au_lock_and_icpup(dentry, ia, a);
12086+ if (unlikely(err < 0))
12087+ goto out_si;
12088+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
12089+ ia->ia_file = NULL;
12090+ ia->ia_valid &= ~ATTR_FILE;
12091+ }
12092+
12093+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
12094+ if (ia->ia_valid & ATTR_SIZE) {
12095+ struct file *f;
12096+
12097+ if (ia->ia_size < i_size_read(inode)) {
12098+ /* unmap only */
12099+ err = vmtruncate(inode, ia->ia_size);
12100+ if (unlikely(err))
12101+ goto out_unlock;
1facf9fc 12102+ }
dece6358
AM
12103+
12104+ f = NULL;
12105+ if (ia->ia_valid & ATTR_FILE)
12106+ f = ia->ia_file;
12107+ mutex_unlock(&a->h_inode->i_mutex);
12108+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
12109+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
12110+ } else
12111+ err = vfsub_notify_change(&a->h_path, ia);
12112+ if (!err)
12113+ au_cpup_attr_changeable(inode);
12114+
12115+ out_unlock:
12116+ mutex_unlock(&a->h_inode->i_mutex);
12117+ au_unpin(&a->pin);
12118+ di_write_unlock(dentry);
12119+ out_si:
12120+ if (file) {
12121+ fi_write_unlock(file);
12122+ ia->ia_file = file;
12123+ ia->ia_valid |= ATTR_FILE;
1facf9fc 12124+ }
dece6358
AM
12125+ si_read_unlock(sb);
12126+ kfree(a);
1facf9fc 12127+ out:
12128+ return err;
12129+}
12130+
dece6358 12131+static int au_getattr_lock_reval(struct dentry *dentry, unsigned int sigen)
1facf9fc 12132+{
dece6358
AM
12133+ int err;
12134+ struct inode *inode;
12135+ struct dentry *parent;
1facf9fc 12136+
12137+ err = 0;
dece6358
AM
12138+ inode = dentry->d_inode;
12139+ di_write_lock_child(dentry);
12140+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
12141+ parent = dget_parent(dentry);
12142+ di_read_lock_parent(parent, AuLock_IR);
12143+ /* returns a number of positive dentries */
12144+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
12145+ if (err > 0)
12146+ err = au_refresh_hinode(inode, dentry);
12147+ di_read_unlock(parent, AuLock_IR);
12148+ dput(parent);
12149+ if (unlikely(!err))
12150+ err = -EIO;
1facf9fc 12151+ }
dece6358
AM
12152+ di_downgrade_lock(dentry, AuLock_IR);
12153+ if (unlikely(err))
12154+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 12155+
1facf9fc 12156+ return err;
12157+}
12158+
dece6358
AM
12159+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
12160+ unsigned int nlink)
1facf9fc 12161+{
dece6358
AM
12162+ inode->i_mode = st->mode;
12163+ inode->i_uid = st->uid;
12164+ inode->i_gid = st->gid;
12165+ inode->i_atime = st->atime;
12166+ inode->i_mtime = st->mtime;
12167+ inode->i_ctime = st->ctime;
1facf9fc 12168+
dece6358
AM
12169+ au_cpup_attr_nlink(inode, /*force*/0);
12170+ if (S_ISDIR(inode->i_mode)) {
12171+ inode->i_nlink -= nlink;
12172+ inode->i_nlink += st->nlink;
12173+ }
12174+
12175+ spin_lock(&inode->i_lock);
12176+ inode->i_blocks = st->blocks;
12177+ i_size_write(inode, st->size);
12178+ spin_unlock(&inode->i_lock);
1facf9fc 12179+}
12180+
dece6358
AM
12181+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
12182+ struct dentry *dentry, struct kstat *st)
1facf9fc 12183+{
12184+ int err;
dece6358
AM
12185+ unsigned int mnt_flags;
12186+ aufs_bindex_t bindex;
12187+ unsigned char udba_none, positive, did_lock;
12188+ struct super_block *sb, *h_sb;
12189+ struct inode *inode;
12190+ struct vfsmount *h_mnt;
12191+ struct dentry *h_dentry;
1facf9fc 12192+
12193+ err = 0;
dece6358
AM
12194+ did_lock = 0;
12195+ sb = dentry->d_sb;
12196+ inode = dentry->d_inode;
12197+ si_read_lock(sb, AuLock_FLUSH);
12198+ if (IS_ROOT(dentry)) {
12199+ /* lock free root dinfo */
12200+ h_dentry = dget(au_di(dentry)->di_hdentry->hd_dentry);
12201+ h_mnt = au_sbr_mnt(sb, 0);
12202+ goto getattr;
1facf9fc 12203+ }
12204+
dece6358
AM
12205+ mnt_flags = au_mntflags(sb);
12206+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 12207+
dece6358
AM
12208+ /* support fstat(2) */
12209+ if (!d_unhashed(dentry) && !udba_none) {
12210+ unsigned int sigen = au_sigen(sb);
12211+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
12212+ di_read_lock_child(dentry, AuLock_IR);
12213+ else {
12214+ err = au_getattr_lock_reval(dentry, sigen);
12215+ if (unlikely(err))
12216+ goto out;
1facf9fc 12217+ }
dece6358
AM
12218+ } else
12219+ di_read_lock_child(dentry, AuLock_IR);
12220+ did_lock = 1;
1facf9fc 12221+
dece6358
AM
12222+ bindex = au_ibstart(inode);
12223+ h_mnt = au_sbr_mnt(sb, bindex);
12224+ h_sb = h_mnt->mnt_sb;
12225+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
12226+ goto out_fill; /* success */
1facf9fc 12227+
dece6358
AM
12228+ h_dentry = NULL;
12229+ if (au_dbstart(dentry) == bindex)
12230+ h_dentry = dget(au_h_dptr(dentry, bindex));
12231+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
12232+ h_dentry = au_plink_lkup(inode, bindex);
12233+ if (IS_ERR(h_dentry))
12234+ goto out_fill; /* pretending success */
1facf9fc 12235+ }
dece6358
AM
12236+ /* illegally overlapped or something */
12237+ if (unlikely(!h_dentry))
12238+ goto out_fill; /* pretending success */
1facf9fc 12239+
dece6358
AM
12240+ getattr:
12241+ positive = !!h_dentry->d_inode;
12242+ if (positive)
12243+ err = vfs_getattr(h_mnt, h_dentry, st);
12244+ dput(h_dentry);
12245+ if (!err) {
12246+ if (positive)
12247+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
12248+ goto out_fill; /* success */
1facf9fc 12249+ }
dece6358
AM
12250+ goto out;
12251+
12252+ out_fill:
12253+ generic_fillattr(inode, st);
12254+ out:
12255+ if (did_lock)
12256+ di_read_unlock(dentry, AuLock_IR);
12257+ si_read_unlock(sb);
12258+ return err;
1facf9fc 12259+}
12260+
12261+/* ---------------------------------------------------------------------- */
12262+
dece6358
AM
12263+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
12264+ int bufsiz)
1facf9fc 12265+{
12266+ int err;
dece6358
AM
12267+ struct super_block *sb;
12268+ struct dentry *h_dentry;
1facf9fc 12269+
dece6358
AM
12270+ err = -EINVAL;
12271+ h_dentry = au_h_dptr(dentry, bindex);
12272+ if (unlikely(/* !h_dentry
12273+ || !h_dentry->d_inode
12274+ || !h_dentry->d_inode->i_op
12275+ || */ !h_dentry->d_inode->i_op->readlink))
12276+ goto out;
1facf9fc 12277+
dece6358
AM
12278+ err = security_inode_readlink(h_dentry);
12279+ if (unlikely(err))
12280+ goto out;
1facf9fc 12281+
dece6358
AM
12282+ sb = dentry->d_sb;
12283+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
12284+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
12285+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 12286+ }
dece6358 12287+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 12288+
dece6358
AM
12289+ out:
12290+ return err;
1facf9fc 12291+}
12292+
dece6358 12293+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
1facf9fc 12294+{
dece6358 12295+ int err;
1facf9fc 12296+
dece6358
AM
12297+ aufs_read_lock(dentry, AuLock_IR);
12298+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
12299+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 12300+
dece6358 12301+ return err;
1facf9fc 12302+}
12303+
dece6358 12304+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
1facf9fc 12305+{
12306+ int err;
dece6358
AM
12307+ char *buf;
12308+ mm_segment_t old_fs;
1facf9fc 12309+
12310+ err = -ENOMEM;
dece6358
AM
12311+ buf = __getname();
12312+ if (unlikely(!buf))
1facf9fc 12313+ goto out;
12314+
dece6358
AM
12315+ aufs_read_lock(dentry, AuLock_IR);
12316+ old_fs = get_fs();
12317+ set_fs(KERNEL_DS);
12318+ err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
12319+ PATH_MAX);
12320+ set_fs(old_fs);
12321+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 12322+
dece6358
AM
12323+ if (err >= 0) {
12324+ buf[err] = 0;
12325+ /* will be freed by put_link */
12326+ nd_set_link(nd, buf);
12327+ return NULL; /* success */
1facf9fc 12328+ }
dece6358 12329+ __putname(buf);
1facf9fc 12330+
dece6358
AM
12331+ out:
12332+ path_put(&nd->path);
12333+ AuTraceErr(err);
12334+ return ERR_PTR(err);
12335+}
1facf9fc 12336+
dece6358
AM
12337+static void aufs_put_link(struct dentry *dentry __maybe_unused,
12338+ struct nameidata *nd, void *cookie __maybe_unused)
12339+{
12340+ __putname(nd_get_link(nd));
12341+}
1facf9fc 12342+
dece6358 12343+/* ---------------------------------------------------------------------- */
1facf9fc 12344+
dece6358
AM
12345+static void aufs_truncate_range(struct inode *inode __maybe_unused,
12346+ loff_t start __maybe_unused,
12347+ loff_t end __maybe_unused)
12348+{
12349+ AuUnsupport();
12350+}
1facf9fc 12351+
dece6358 12352+/* ---------------------------------------------------------------------- */
1facf9fc 12353+
dece6358
AM
12354+struct inode_operations aufs_symlink_iop = {
12355+ .permission = aufs_permission,
12356+ .setattr = aufs_setattr,
12357+ .getattr = aufs_getattr,
12358+ .readlink = aufs_readlink,
12359+ .follow_link = aufs_follow_link,
12360+ .put_link = aufs_put_link
12361+};
1facf9fc 12362+
dece6358
AM
12363+struct inode_operations aufs_dir_iop = {
12364+ .create = aufs_create,
12365+ .lookup = aufs_lookup,
12366+ .link = aufs_link,
12367+ .unlink = aufs_unlink,
12368+ .symlink = aufs_symlink,
12369+ .mkdir = aufs_mkdir,
12370+ .rmdir = aufs_rmdir,
12371+ .mknod = aufs_mknod,
12372+ .rename = aufs_rename,
1facf9fc 12373+
dece6358
AM
12374+ .permission = aufs_permission,
12375+ .setattr = aufs_setattr,
12376+ .getattr = aufs_getattr
12377+};
1facf9fc 12378+
dece6358
AM
12379+struct inode_operations aufs_iop = {
12380+ .permission = aufs_permission,
12381+ .setattr = aufs_setattr,
12382+ .getattr = aufs_getattr,
12383+ .truncate_range = aufs_truncate_range
12384+};
12385diff -urN linux-2.6.30.org/fs/aufs/i_op_del.c linux-2.6.30/fs/aufs/i_op_del.c
12386--- linux-2.6.30.org/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
12387+++ linux-2.6.30/fs/aufs/i_op_del.c 2009-07-21 08:54:19.000000000 +0200
12388@@ -0,0 +1,468 @@
1facf9fc 12389+/*
12390+ * Copyright (C) 2005-2009 Junjiro R. Okajima
12391+ *
12392+ * This program, aufs is free software; you can redistribute it and/or modify
12393+ * it under the terms of the GNU General Public License as published by
12394+ * the Free Software Foundation; either version 2 of the License, or
12395+ * (at your option) any later version.
dece6358
AM
12396+ *
12397+ * This program is distributed in the hope that it will be useful,
12398+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12399+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12400+ * GNU General Public License for more details.
12401+ *
12402+ * You should have received a copy of the GNU General Public License
12403+ * along with this program; if not, write to the Free Software
12404+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 12405+ */
12406+
12407+/*
dece6358 12408+ * inode operations (del entry)
1facf9fc 12409+ */
12410+
12411+#include "aufs.h"
12412+
dece6358
AM
12413+/*
12414+ * decide if a new whiteout for @dentry is necessary or not.
12415+ * when it is necessary, prepare the parent dir for the upper branch whose
12416+ * branch index is @bcpup for creation. the actual creation of the whiteout will
12417+ * be done by caller.
12418+ * return value:
12419+ * 0: wh is unnecessary
12420+ * plus: wh is necessary
12421+ * minus: error
12422+ */
12423+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1facf9fc 12424+{
dece6358
AM
12425+ int need_wh, err;
12426+ aufs_bindex_t bstart;
12427+ struct super_block *sb;
1facf9fc 12428+
dece6358
AM
12429+ sb = dentry->d_sb;
12430+ bstart = au_dbstart(dentry);
12431+ if (*bcpup < 0) {
12432+ *bcpup = bstart;
12433+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
12434+ err = AuWbrCopyup(au_sbi(sb), dentry);
12435+ *bcpup = err;
12436+ if (unlikely(err < 0))
12437+ goto out;
12438+ }
12439+ } else
12440+ AuDebugOn(bstart < *bcpup
12441+ || au_test_ro(sb, *bcpup, dentry->d_inode));
12442+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
12443+
12444+ if (*bcpup != bstart) {
12445+ err = au_cpup_dirs(dentry, *bcpup);
12446+ if (unlikely(err))
12447+ goto out;
12448+ need_wh = 1;
12449+ } else {
12450+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
12451+
12452+ old_bend = au_dbend(dentry);
12453+ if (isdir) {
12454+ bdiropq = au_dbdiropq(dentry);
12455+ au_set_dbdiropq(dentry, -1);
12456+ }
12457+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
12458+ /*nd*/NULL);
12459+ err = need_wh;
12460+ if (isdir)
12461+ au_set_dbdiropq(dentry, bdiropq);
12462+ if (unlikely(err < 0))
12463+ goto out;
12464+ new_bend = au_dbend(dentry);
12465+ if (!need_wh && old_bend != new_bend) {
12466+ au_set_h_dptr(dentry, new_bend, NULL);
12467+ au_set_dbend(dentry, old_bend);
12468+ }
12469+ }
12470+ AuDbg("need_wh %d\n", need_wh);
12471+ err = need_wh;
12472+
12473+ out:
12474+ return err;
1facf9fc 12475+}
12476+
dece6358
AM
12477+/*
12478+ * simple tests for the del-entry operations.
12479+ * following the checks in vfs, plus the parent-child relationship.
12480+ */
12481+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12482+ struct dentry *h_parent, int isdir)
1facf9fc 12483+{
dece6358
AM
12484+ int err;
12485+ umode_t h_mode;
12486+ struct dentry *h_dentry, *h_latest;
1facf9fc 12487+ struct inode *h_inode;
12488+
dece6358
AM
12489+ h_dentry = au_h_dptr(dentry, bindex);
12490+ h_inode = h_dentry->d_inode;
12491+ if (dentry->d_inode) {
12492+ err = -ENOENT;
12493+ if (unlikely(!h_inode || !h_inode->i_nlink))
12494+ goto out;
1facf9fc 12495+
dece6358
AM
12496+ h_mode = h_inode->i_mode;
12497+ if (!isdir) {
12498+ err = -EISDIR;
12499+ if (unlikely(S_ISDIR(h_mode)))
12500+ goto out;
12501+ } else if (unlikely(!S_ISDIR(h_mode))) {
12502+ err = -ENOTDIR;
12503+ goto out;
12504+ }
12505+ } else {
12506+ /* rename(2) case */
12507+ err = -EIO;
12508+ if (unlikely(h_inode))
12509+ goto out;
12510+ }
12511+
12512+ err = -ENOENT;
12513+ /* expected parent dir is locked */
12514+ if (unlikely(h_parent != h_dentry->d_parent))
12515+ goto out;
12516+ err = 0;
12517+
12518+ /*
12519+ * rmdir a dir may break the consistency on some filesystem.
12520+ * let's try heavy test.
12521+ */
12522+ err = -EACCES;
12523+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
12524+ goto out;
12525+
12526+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
12527+ au_sbr(dentry->d_sb, bindex));
12528+ err = -EIO;
12529+ if (IS_ERR(h_latest))
12530+ goto out;
12531+ if (h_latest == h_dentry)
12532+ err = 0;
12533+ dput(h_latest);
12534+
12535+ out:
12536+ return err;
1facf9fc 12537+}
12538+
dece6358
AM
12539+/*
12540+ * decide the branch where we operate for @dentry. the branch index will be set
12541+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
12542+ * dir for reverting.
12543+ * when a new whiteout is necessary, create it.
12544+ */
12545+static struct dentry*
12546+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
12547+ struct au_dtime *dt, struct au_pin *pin)
1facf9fc 12548+{
dece6358
AM
12549+ struct dentry *wh_dentry;
12550+ struct super_block *sb;
12551+ struct path h_path;
12552+ int err, need_wh;
12553+ unsigned int udba;
12554+ aufs_bindex_t bcpup;
1facf9fc 12555+
dece6358
AM
12556+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
12557+ wh_dentry = ERR_PTR(need_wh);
12558+ if (unlikely(need_wh < 0))
12559+ goto out;
12560+
12561+ sb = dentry->d_sb;
12562+ udba = au_opt_udba(sb);
12563+ bcpup = *rbcpup;
12564+ err = au_pin(pin, dentry, bcpup, udba,
12565+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
12566+ wh_dentry = ERR_PTR(err);
12567+ if (unlikely(err))
12568+ goto out;
12569+
12570+ h_path.dentry = au_pinned_h_parent(pin);
12571+ if (udba != AuOpt_UDBA_NONE
12572+ && au_dbstart(dentry) == bcpup) {
12573+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
12574+ wh_dentry = ERR_PTR(err);
12575+ if (unlikely(err))
12576+ goto out_unpin;
12577+ }
12578+
12579+ h_path.mnt = au_sbr_mnt(sb, bcpup);
12580+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
12581+ wh_dentry = NULL;
12582+ if (!need_wh)
12583+ goto out; /* success, no need to create whiteout */
12584+
12585+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
12586+ if (!IS_ERR(wh_dentry))
12587+ goto out; /* success */
12588+ /* returns with the parent is locked and wh_dentry is dget-ed */
12589+
12590+ out_unpin:
12591+ au_unpin(pin);
12592+ out:
12593+ return wh_dentry;
1facf9fc 12594+}
12595+
dece6358
AM
12596+/*
12597+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
12598+ * in order to be revertible and save time for removing many child whiteouts
12599+ * under the dir.
12600+ * returns 1 when there are too many child whiteout and caller should remove
12601+ * them asynchronously. returns 0 when the number of children is enough small to
12602+ * remove now or the branch fs is a remote fs.
12603+ * otherwise return an error.
12604+ */
12605+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
12606+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 12607+{
dece6358
AM
12608+ int rmdir_later, err, dirwh;
12609+ struct dentry *h_dentry;
12610+ struct super_block *sb;
1facf9fc 12611+
dece6358
AM
12612+ sb = dentry->d_sb;
12613+ SiMustAnyLock(sb);
12614+ h_dentry = au_h_dptr(dentry, bindex);
12615+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
12616+ if (unlikely(err))
12617+ goto out;
1facf9fc 12618+
dece6358
AM
12619+ /* stop monitoring */
12620+ au_hin_free(au_hi(dentry->d_inode, bindex));
1facf9fc 12621+
dece6358
AM
12622+ if (!au_test_fs_remote(h_dentry->d_sb)) {
12623+ dirwh = au_sbi(sb)->si_dirwh;
12624+ rmdir_later = (dirwh <= 1);
12625+ if (!rmdir_later)
12626+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
12627+ dirwh);
12628+ if (rmdir_later)
12629+ return rmdir_later;
12630+ }
1facf9fc 12631+
dece6358
AM
12632+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
12633+ if (unlikely(err)) {
12634+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
12635+ AuDLNPair(h_dentry), bindex, err);
12636+ err = 0;
1facf9fc 12637+ }
dece6358
AM
12638+
12639+ out:
12640+ return err;
1facf9fc 12641+}
12642+
dece6358
AM
12643+/*
12644+ * final procedure for deleting a entry.
12645+ * maintain dentry and iattr.
12646+ */
12647+static void epilog(struct inode *dir, struct dentry *dentry,
12648+ aufs_bindex_t bindex)
1facf9fc 12649+{
dece6358 12650+ struct inode *inode;
1facf9fc 12651+
dece6358
AM
12652+ inode = dentry->d_inode;
12653+ d_drop(dentry);
12654+ inode->i_ctime = dir->i_ctime;
12655+
12656+ if (atomic_read(&dentry->d_count) == 1) {
12657+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
12658+ au_update_dbstart(dentry);
12659+ }
12660+ if (au_ibstart(dir) == bindex)
12661+ au_cpup_attr_timesizes(dir);
12662+ dir->i_version++;
1facf9fc 12663+}
12664+
dece6358
AM
12665+/*
12666+ * when an error happened, remove the created whiteout and revert everything.
12667+ */
12668+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
12669+ struct dentry *wh_dentry, struct dentry *dentry,
12670+ struct au_dtime *dt)
1facf9fc 12671+{
dece6358
AM
12672+ int rerr;
12673+ struct path h_path = {
12674+ .dentry = wh_dentry,
12675+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
12676+ };
12677+
12678+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
12679+ if (!rerr) {
12680+ au_set_dbwh(dentry, bwh);
12681+ au_dtime_revert(dt);
12682+ return 0;
12683+ }
12684+
12685+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
12686+ AuDLNPair(dentry), err, rerr);
12687+ return -EIO;
1facf9fc 12688+}
12689+
dece6358
AM
12690+/* ---------------------------------------------------------------------- */
12691+
12692+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1facf9fc 12693+{
dece6358
AM
12694+ int err;
12695+ aufs_bindex_t bwh, bindex, bstart;
12696+ struct au_dtime dt;
12697+ struct au_pin pin;
12698+ struct path h_path;
12699+ struct inode *inode, *h_dir;
12700+ struct dentry *parent, *wh_dentry;
1facf9fc 12701+
dece6358
AM
12702+ IMustLock(dir);
12703+ inode = dentry->d_inode;
12704+ if (unlikely(!inode))
12705+ return -ENOENT; /* possible? */
12706+ IMustLock(inode);
1facf9fc 12707+
dece6358
AM
12708+ aufs_read_lock(dentry, AuLock_DW);
12709+ parent = dentry->d_parent; /* dir inode is locked */
12710+ di_write_lock_parent(parent);
1facf9fc 12711+
dece6358
AM
12712+ bstart = au_dbstart(dentry);
12713+ bwh = au_dbwh(dentry);
12714+ bindex = -1;
12715+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
12716+ err = PTR_ERR(wh_dentry);
12717+ if (IS_ERR(wh_dentry))
12718+ goto out;
1facf9fc 12719+
dece6358
AM
12720+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
12721+ h_path.dentry = au_h_dptr(dentry, bstart);
12722+ dget(h_path.dentry);
12723+ if (bindex == bstart) {
12724+ h_dir = au_pinned_h_dir(&pin);
12725+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
12726+ } else {
12727+ /* dir inode is locked */
12728+ h_dir = wh_dentry->d_parent->d_inode;
12729+ IMustLock(h_dir);
12730+ err = 0;
1facf9fc 12731+ }
12732+
dece6358
AM
12733+ if (!err) {
12734+ drop_nlink(inode);
12735+ epilog(dir, dentry, bindex);
12736+
12737+ /* update target timestamps */
12738+ if (bindex == bstart) {
12739+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
12740+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
12741+ } else
12742+ /* todo: this timestamp may be reverted later */
12743+ inode->i_ctime = h_dir->i_ctime;
12744+ goto out_unlock; /* success */
1facf9fc 12745+ }
12746+
dece6358
AM
12747+ /* revert */
12748+ if (wh_dentry) {
12749+ int rerr;
1facf9fc 12750+
dece6358
AM
12751+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
12752+ if (rerr)
12753+ err = rerr;
12754+ }
1facf9fc 12755+
dece6358
AM
12756+ out_unlock:
12757+ au_unpin(&pin);
12758+ dput(wh_dentry);
12759+ dput(h_path.dentry);
12760+ out:
12761+ di_write_unlock(parent);
12762+ aufs_read_unlock(dentry, AuLock_DW);
12763+ return err;
12764+}
12765+
12766+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1facf9fc 12767+{
dece6358
AM
12768+ int err, rmdir_later;
12769+ aufs_bindex_t bwh, bindex, bstart;
12770+ struct au_dtime dt;
12771+ struct au_pin pin;
12772+ struct inode *inode;
12773+ struct dentry *parent, *wh_dentry, *h_dentry;
12774+ struct au_whtmp_rmdir *args;
1facf9fc 12775+
dece6358
AM
12776+ IMustLock(dir);
12777+ inode = dentry->d_inode;
12778+ err = -ENOENT; /* possible? */
12779+ if (unlikely(!inode))
12780+ goto out;
12781+ IMustLock(inode);
1facf9fc 12782+
dece6358
AM
12783+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
12784+ err = -ENOMEM;
12785+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
12786+ if (unlikely(!args))
12787+ goto out_unlock;
12788+
12789+ parent = dentry->d_parent; /* dir inode is locked */
12790+ di_write_lock_parent(parent);
12791+ err = au_test_empty(dentry, &args->whlist);
12792+ if (unlikely(err))
12793+ goto out_args;
12794+
12795+ bstart = au_dbstart(dentry);
12796+ bwh = au_dbwh(dentry);
12797+ bindex = -1;
12798+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
12799+ err = PTR_ERR(wh_dentry);
12800+ if (IS_ERR(wh_dentry))
12801+ goto out_args;
1facf9fc 12802+
dece6358
AM
12803+ h_dentry = au_h_dptr(dentry, bstart);
12804+ dget(h_dentry);
12805+ rmdir_later = 0;
12806+ if (bindex == bstart) {
12807+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
12808+ if (err > 0) {
12809+ rmdir_later = err;
12810+ err = 0;
12811+ }
12812+ } else {
12813+ /* stop monitoring */
12814+ au_hin_free(au_hi(inode, bstart));
1facf9fc 12815+
dece6358
AM
12816+ /* dir inode is locked */
12817+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 12818+ err = 0;
12819+ }
12820+
dece6358
AM
12821+ if (!err) {
12822+ clear_nlink(inode);
12823+ au_set_dbdiropq(dentry, -1);
12824+ epilog(dir, dentry, bindex);
1facf9fc 12825+
dece6358
AM
12826+ if (rmdir_later) {
12827+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
12828+ args = NULL;
12829+ }
1facf9fc 12830+
dece6358 12831+ goto out_unpin; /* success */
1facf9fc 12832+ }
12833+
dece6358
AM
12834+ /* revert */
12835+ AuLabel(revert);
12836+ if (wh_dentry) {
12837+ int rerr;
1facf9fc 12838+
dece6358
AM
12839+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
12840+ if (rerr)
12841+ err = rerr;
1facf9fc 12842+ }
12843+
dece6358
AM
12844+ out_unpin:
12845+ au_unpin(&pin);
12846+ dput(wh_dentry);
12847+ dput(h_dentry);
12848+ out_args:
12849+ di_write_unlock(parent);
12850+ if (args)
12851+ au_whtmp_rmdir_free(args);
12852+ out_unlock:
12853+ aufs_read_unlock(dentry, AuLock_DW);
12854+ out:
12855+ return err;
12856+}
12857diff -urN linux-2.6.30.org/fs/aufs/i_op_ren.c linux-2.6.30/fs/aufs/i_op_ren.c
12858--- linux-2.6.30.org/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
12859+++ linux-2.6.30/fs/aufs/i_op_ren.c 2009-07-21 08:54:19.000000000 +0200
12860@@ -0,0 +1,945 @@
1facf9fc 12861+/*
12862+ * Copyright (C) 2005-2009 Junjiro R. Okajima
12863+ *
12864+ * This program, aufs is free software; you can redistribute it and/or modify
12865+ * it under the terms of the GNU General Public License as published by
12866+ * the Free Software Foundation; either version 2 of the License, or
12867+ * (at your option) any later version.
dece6358
AM
12868+ *
12869+ * This program is distributed in the hope that it will be useful,
12870+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12871+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12872+ * GNU General Public License for more details.
12873+ *
12874+ * You should have received a copy of the GNU General Public License
12875+ * along with this program; if not, write to the Free Software
12876+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 12877+ */
12878+
12879+/*
dece6358
AM
12880+ * inode operation (rename entry)
12881+ * todo: this is crazy monster
1facf9fc 12882+ */
12883+
12884+#include "aufs.h"
12885+
dece6358
AM
12886+enum { AuSRC, AuDST, AuSrcDst };
12887+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 12888+
dece6358
AM
12889+#define AuRen_ISDIR 1
12890+#define AuRen_ISSAMEDIR (1 << 1)
12891+#define AuRen_WHSRC (1 << 2)
12892+#define AuRen_WHDST (1 << 3)
12893+#define AuRen_MNT_WRITE (1 << 4)
12894+#define AuRen_DT_DSTDIR (1 << 5)
12895+#define AuRen_DIROPQ (1 << 6)
12896+#define AuRen_CPUP (1 << 7)
12897+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
12898+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
12899+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
1facf9fc 12900+
dece6358
AM
12901+struct au_ren_args {
12902+ struct {
12903+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
12904+ *wh_dentry;
12905+ struct inode *dir, *inode;
12906+ struct au_hinode *hdir;
12907+ struct au_dtime dt[AuParentChild];
12908+ aufs_bindex_t bstart;
12909+ } sd[AuSrcDst];
1facf9fc 12910+
dece6358
AM
12911+#define src_dentry sd[AuSRC].dentry
12912+#define src_dir sd[AuSRC].dir
12913+#define src_inode sd[AuSRC].inode
12914+#define src_h_dentry sd[AuSRC].h_dentry
12915+#define src_parent sd[AuSRC].parent
12916+#define src_h_parent sd[AuSRC].h_parent
12917+#define src_wh_dentry sd[AuSRC].wh_dentry
12918+#define src_hdir sd[AuSRC].hdir
12919+#define src_h_dir sd[AuSRC].hdir->hi_inode
12920+#define src_dt sd[AuSRC].dt
12921+#define src_bstart sd[AuSRC].bstart
1facf9fc 12922+
dece6358
AM
12923+#define dst_dentry sd[AuDST].dentry
12924+#define dst_dir sd[AuDST].dir
12925+#define dst_inode sd[AuDST].inode
12926+#define dst_h_dentry sd[AuDST].h_dentry
12927+#define dst_parent sd[AuDST].parent
12928+#define dst_h_parent sd[AuDST].h_parent
12929+#define dst_wh_dentry sd[AuDST].wh_dentry
12930+#define dst_hdir sd[AuDST].hdir
12931+#define dst_h_dir sd[AuDST].hdir->hi_inode
12932+#define dst_dt sd[AuDST].dt
12933+#define dst_bstart sd[AuDST].bstart
1facf9fc 12934+
dece6358
AM
12935+ struct dentry *h_trap;
12936+ struct au_branch *br;
12937+ struct au_hinode *src_hinode;
12938+ struct path h_path;
12939+ struct au_nhash whlist;
12940+ aufs_bindex_t btgt;
1facf9fc 12941+
1facf9fc 12942+ unsigned int flags;
1facf9fc 12943+
dece6358
AM
12944+ struct au_whtmp_rmdir *thargs;
12945+ struct dentry *h_dst;
12946+};
1facf9fc 12947+
dece6358 12948+/* ---------------------------------------------------------------------- */
1facf9fc 12949+
dece6358
AM
12950+/*
12951+ * functions for reverting.
12952+ * when an error happened in a single rename systemcall, we should revert
12953+ * everything as if nothing happend.
12954+ * we don't need to revert the copied-up/down the parent dir since they are
12955+ * harmless.
12956+ */
1facf9fc 12957+
dece6358
AM
12958+#define RevertFailure(fmt, args...) do { \
12959+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
12960+ ##args, err, rerr); \
12961+ err = -EIO; \
12962+} while (0)
1facf9fc 12963+
dece6358
AM
12964+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
12965+{
12966+ int rerr;
12967+
12968+ au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
12969+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
12970+ au_hin_imtx_unlock(a->src_hinode);
12971+ if (rerr)
12972+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
1facf9fc 12973+}
12974+
1facf9fc 12975+
dece6358
AM
12976+static void au_ren_rev_rename(int err, struct au_ren_args *a)
12977+{
12978+ int rerr;
1facf9fc 12979+
dece6358
AM
12980+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
12981+ a->br, /*nd*/NULL);
12982+ rerr = PTR_ERR(a->h_path.dentry);
12983+ if (IS_ERR(a->h_path.dentry)) {
12984+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
12985+ return;
1facf9fc 12986+ }
1facf9fc 12987+
dece6358
AM
12988+ rerr = vfsub_rename(a->dst_h_dir,
12989+ au_h_dptr(a->src_dentry, a->btgt),
12990+ a->src_h_dir, &a->h_path);
12991+ d_drop(a->h_path.dentry);
12992+ dput(a->h_path.dentry);
12993+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
12994+ if (rerr)
12995+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 12996+}
12997+
dece6358 12998+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 12999+{
dece6358 13000+ int rerr;
1facf9fc 13001+
dece6358
AM
13002+ a->h_path.dentry = a->dst_h_dentry;
13003+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
13004+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
13005+ au_set_dbstart(a->src_dentry, a->src_bstart);
13006+ if (rerr)
13007+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
13008+}
1facf9fc 13009+
1facf9fc 13010+
dece6358
AM
13011+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
13012+{
13013+ int rerr;
1facf9fc 13014+
dece6358
AM
13015+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
13016+ a->br, /*nd*/NULL);
13017+ rerr = PTR_ERR(a->h_path.dentry);
13018+ if (IS_ERR(a->h_path.dentry)) {
13019+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
13020+ return;
13021+ }
13022+ if (a->h_path.dentry->d_inode) {
13023+ d_drop(a->h_path.dentry);
13024+ dput(a->h_path.dentry);
13025+ return;
1facf9fc 13026+ }
13027+
dece6358
AM
13028+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
13029+ d_drop(a->h_path.dentry);
13030+ dput(a->h_path.dentry);
13031+ if (!rerr) {
13032+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
13033+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
13034+ } else
13035+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
1facf9fc 13036+}
13037+
dece6358 13038+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
1facf9fc 13039+{
dece6358 13040+ int rerr;
1facf9fc 13041+
dece6358
AM
13042+ a->h_path.dentry = a->src_wh_dentry;
13043+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
13044+ if (rerr)
13045+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
13046+}
1facf9fc 13047+
dece6358
AM
13048+static void au_ren_rev_drop(struct au_ren_args *a)
13049+{
13050+ struct dentry *d, *h_d;
13051+ int i;
13052+ aufs_bindex_t bend, bindex;
1facf9fc 13053+
dece6358
AM
13054+ for (i = 0; i < AuSrcDst; i++) {
13055+ d = a->sd[i].dentry;
13056+ d_drop(d);
13057+ bend = au_dbend(d);
13058+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
13059+ h_d = au_h_dptr(d, bindex);
13060+ if (h_d)
13061+ d_drop(h_d);
13062+ }
1facf9fc 13063+ }
13064+
dece6358
AM
13065+ au_update_dbstart(a->dst_dentry);
13066+ if (a->thargs)
13067+ d_drop(a->h_dst);
1facf9fc 13068+}
dece6358 13069+#undef RevertFailure
1facf9fc 13070+
13071+/* ---------------------------------------------------------------------- */
13072+
dece6358
AM
13073+/*
13074+ * when we have to copyup the renaming entry, do it with the rename-target name
13075+ * in order to minimize the cost (the later actual rename is unnecessary).
13076+ * otherwise rename it on the target branch.
13077+ */
13078+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 13079+{
13080+ int err;
dece6358 13081+ struct dentry *d;
1facf9fc 13082+
dece6358
AM
13083+ d = a->src_dentry;
13084+ if (au_dbstart(d) == a->btgt) {
13085+ a->h_path.dentry = a->dst_h_dentry;
13086+ if (au_ftest_ren(a->flags, DIROPQ)
13087+ && au_dbdiropq(d) == a->btgt)
13088+ au_fclr_ren(a->flags, DIROPQ);
13089+ AuDebugOn(au_dbstart(d) != a->btgt);
13090+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
13091+ a->dst_h_dir, &a->h_path);
13092+ } else {
13093+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
1facf9fc 13094+
dece6358
AM
13095+ au_fset_ren(a->flags, CPUP);
13096+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13097+ au_set_dbstart(d, a->btgt);
13098+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
13099+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
13100+ !AuCpup_DTIME, a->dst_parent);
13101+ if (unlikely(err)) {
13102+ au_set_h_dptr(d, a->btgt, NULL);
13103+ au_set_dbstart(d, a->src_bstart);
13104+ }
13105+ mutex_unlock(h_mtx);
1facf9fc 13106+ }
13107+
13108+ return err;
13109+}
13110+
dece6358
AM
13111+/* cf. aufs_rmdir() */
13112+static int au_ren_del_whtmp(struct au_ren_args *a)
1facf9fc 13113+{
dece6358
AM
13114+ int err;
13115+ struct inode *dir;
13116+
13117+ dir = a->dst_dir;
13118+ SiMustAnyLock(dir->i_sb);
13119+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
13120+ au_sbi(dir->i_sb)->si_dirwh)
13121+ || au_test_fs_remote(a->h_dst->d_sb)) {
13122+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
13123+ if (unlikely(err))
13124+ AuWarn("failed removing whtmp dir %.*s (%d), "
13125+ "ignored.\n", AuDLNPair(a->h_dst), err);
13126+ } else {
13127+ au_nhash_wh_free(&a->thargs->whlist);
13128+ a->thargs->whlist = a->whlist;
13129+ a->whlist.nh_num = 0;
13130+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
13131+ dput(a->h_dst);
13132+ a->thargs = NULL;
13133+ }
13134+
13135+ return 0;
1facf9fc 13136+}
13137+
dece6358
AM
13138+/* make it 'opaque' dir. */
13139+static int au_ren_diropq(struct au_ren_args *a)
1facf9fc 13140+{
dece6358
AM
13141+ int err;
13142+ struct dentry *diropq;
1facf9fc 13143+
dece6358
AM
13144+ err = 0;
13145+ a->src_hinode = au_hi(a->src_inode, a->btgt);
13146+ au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
13147+ diropq = au_diropq_create(a->src_dentry, a->btgt);
13148+ au_hin_imtx_unlock(a->src_hinode);
13149+ if (IS_ERR(diropq))
13150+ err = PTR_ERR(diropq);
13151+ dput(diropq);
1facf9fc 13152+
dece6358
AM
13153+ return err;
13154+}
1facf9fc 13155+
dece6358
AM
13156+static int do_rename(struct au_ren_args *a)
13157+{
13158+ int err;
13159+ struct dentry *d, *h_d;
1facf9fc 13160+
dece6358
AM
13161+ /* prepare workqueue args for asynchronous rmdir */
13162+ h_d = a->dst_h_dentry;
13163+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
13164+ err = -ENOMEM;
13165+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
13166+ if (unlikely(!a->thargs))
13167+ goto out;
13168+ a->h_dst = dget(h_d);
13169+ }
1facf9fc 13170+
dece6358
AM
13171+ /* create whiteout for src_dentry */
13172+ if (au_ftest_ren(a->flags, WHSRC)) {
13173+ a->src_wh_dentry
13174+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
13175+ err = PTR_ERR(a->src_wh_dentry);
13176+ if (IS_ERR(a->src_wh_dentry))
13177+ goto out_thargs;
13178+ }
1facf9fc 13179+
dece6358
AM
13180+ /* lookup whiteout for dentry */
13181+ if (au_ftest_ren(a->flags, WHDST)) {
13182+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
13183+ a->br);
13184+ err = PTR_ERR(h_d);
13185+ if (IS_ERR(h_d))
13186+ goto out_whsrc;
13187+ if (!h_d->d_inode)
13188+ dput(h_d);
13189+ else
13190+ a->dst_wh_dentry = h_d;
13191+ }
1facf9fc 13192+
dece6358
AM
13193+ /* rename dentry to tmpwh */
13194+ if (a->thargs) {
13195+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
13196+ if (unlikely(err))
13197+ goto out_whdst;
1facf9fc 13198+
dece6358
AM
13199+ d = a->dst_dentry;
13200+ au_set_h_dptr(d, a->btgt, NULL);
13201+ err = au_lkup_neg(d, a->btgt);
13202+ if (unlikely(err))
13203+ goto out_whtmp;
13204+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
13205+ }
1facf9fc 13206+
dece6358
AM
13207+ /* cpup src */
13208+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
13209+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
1facf9fc 13210+
dece6358
AM
13211+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13212+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
13213+ !AuCpup_DTIME);
13214+ mutex_unlock(h_mtx);
13215+ if (unlikely(err))
13216+ goto out_whtmp;
13217+ }
1facf9fc 13218+
dece6358
AM
13219+ /* rename by vfs_rename or cpup */
13220+ d = a->dst_dentry;
13221+ if (au_ftest_ren(a->flags, ISDIR)
13222+ && (a->dst_wh_dentry
13223+ || au_dbdiropq(d) == a->btgt
13224+ /* hide the lower to keep xino */
13225+ || a->btgt < au_dbend(d)
13226+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
13227+ au_fset_ren(a->flags, DIROPQ);
13228+ err = au_ren_or_cpup(a);
13229+ if (unlikely(err))
13230+ /* leave the copied-up one */
13231+ goto out_whtmp;
1facf9fc 13232+
dece6358
AM
13233+ /* make dir opaque */
13234+ if (au_ftest_ren(a->flags, DIROPQ)) {
13235+ err = au_ren_diropq(a);
13236+ if (unlikely(err))
13237+ goto out_rename;
13238+ }
1facf9fc 13239+
dece6358
AM
13240+ /* update target timestamps */
13241+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
13242+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
13243+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
13244+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
13245+
13246+ /* remove whiteout for dentry */
13247+ if (a->dst_wh_dentry) {
13248+ a->h_path.dentry = a->dst_wh_dentry;
13249+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
13250+ a->dst_dentry);
13251+ if (unlikely(err))
13252+ goto out_diropq;
13253+ }
1facf9fc 13254+
dece6358
AM
13255+ /* remove whtmp */
13256+ if (a->thargs)
13257+ au_ren_del_whtmp(a); /* ignore this error */
1facf9fc 13258+
dece6358
AM
13259+ err = 0;
13260+ goto out_success;
1facf9fc 13261+
dece6358
AM
13262+ out_diropq:
13263+ if (au_ftest_ren(a->flags, DIROPQ))
13264+ au_ren_rev_diropq(err, a);
13265+ out_rename:
13266+ if (!au_ftest_ren(a->flags, CPUP))
13267+ au_ren_rev_rename(err, a);
13268+ else
13269+ au_ren_rev_cpup(err, a);
13270+ out_whtmp:
13271+ if (a->thargs)
13272+ au_ren_rev_whtmp(err, a);
13273+ out_whdst:
13274+ dput(a->dst_wh_dentry);
13275+ a->dst_wh_dentry = NULL;
13276+ out_whsrc:
13277+ if (a->src_wh_dentry)
13278+ au_ren_rev_whsrc(err, a);
13279+ au_ren_rev_drop(a);
13280+ out_success:
13281+ dput(a->src_wh_dentry);
13282+ dput(a->dst_wh_dentry);
13283+ out_thargs:
13284+ if (a->thargs) {
13285+ dput(a->h_dst);
13286+ au_whtmp_rmdir_free(a->thargs);
13287+ a->thargs = NULL;
13288+ }
13289+ out:
13290+ return err;
1facf9fc 13291+}
13292+
13293+/* ---------------------------------------------------------------------- */
13294+
dece6358
AM
13295+/*
13296+ * test if @dentry dir can be rename destination or not.
13297+ * success means, it is a logically empty dir.
13298+ */
13299+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
13300+{
13301+ return au_test_empty(dentry, whlist);
13302+}
1facf9fc 13303+
dece6358
AM
13304+/*
13305+ * test if @dentry dir can be rename source or not.
13306+ * if it can, return 0 and @children is filled.
13307+ * success means,
13308+ * - it is a logically empty dir.
13309+ * - or, it exists on writable branch and has no children including whiteouts
13310+ * on the lower branch.
13311+ */
13312+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
13313+{
13314+ int err;
13315+ aufs_bindex_t bstart;
1facf9fc 13316+
dece6358
AM
13317+ bstart = au_dbstart(dentry);
13318+ if (bstart != btgt) {
13319+ struct au_nhash whlist;
1facf9fc 13320+
dece6358
AM
13321+ SiMustAnyLock(dentry->d_sb);
13322+ err = au_nhash_alloc(&whlist, au_sbi(dentry->d_sb)->si_rdhash,
13323+ GFP_NOFS);
13324+ if (unlikely(err))
13325+ goto out;
13326+ err = au_test_empty(dentry, &whlist);
13327+ au_nhash_wh_free(&whlist);
13328+ goto out;
13329+ }
1facf9fc 13330+
dece6358
AM
13331+ if (bstart == au_dbtaildir(dentry))
13332+ return 0; /* success */
1facf9fc 13333+
dece6358 13334+ err = au_test_empty_lower(dentry);
1facf9fc 13335+
dece6358
AM
13336+ out:
13337+ if (err == -ENOTEMPTY) {
13338+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
13339+ " is not supported\n");
13340+ err = -EXDEV;
13341+ }
13342+ return err;
13343+}
1facf9fc 13344+
dece6358
AM
13345+/* side effect: sets whlist and h_dentry */
13346+static int au_ren_may_dir(struct au_ren_args *a)
13347+{
13348+ int err;
13349+ struct dentry *d;
1facf9fc 13350+
dece6358
AM
13351+ d = a->dst_dentry;
13352+ SiMustAnyLock(d->d_sb);
13353+ err = au_nhash_alloc(&a->whlist, au_sbi(d->d_sb)->si_rdhash, GFP_NOFS);
13354+ if (unlikely(err))
13355+ goto out;
1facf9fc 13356+
dece6358
AM
13357+ err = 0;
13358+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
13359+ au_set_dbstart(d, a->dst_bstart);
13360+ err = may_rename_dstdir(d, &a->whlist);
13361+ au_set_dbstart(d, a->btgt);
13362+ }
13363+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
13364+ if (unlikely(err))
13365+ goto out;
1facf9fc 13366+
dece6358
AM
13367+ d = a->src_dentry;
13368+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
13369+ if (au_ftest_ren(a->flags, ISDIR)) {
13370+ err = may_rename_srcdir(d, a->btgt);
13371+ if (unlikely(err)) {
13372+ au_nhash_wh_free(&a->whlist);
13373+ a->whlist.nh_num = 0;
13374+ }
13375+ }
13376+ out:
13377+ return err;
1facf9fc 13378+}
1facf9fc 13379+
13380+/* ---------------------------------------------------------------------- */
13381+
1facf9fc 13382+/*
dece6358
AM
13383+ * simple tests for rename.
13384+ * following the checks in vfs, plus the parent-child relationship.
1facf9fc 13385+ */
dece6358
AM
13386+static int au_may_ren(struct au_ren_args *a)
13387+{
13388+ int err, isdir;
13389+ struct inode *h_inode;
13390+
13391+ if (a->src_bstart == a->btgt) {
13392+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
13393+ au_ftest_ren(a->flags, ISDIR));
13394+ if (unlikely(err))
13395+ goto out;
13396+ err = -EINVAL;
13397+ if (unlikely(a->src_h_dentry == a->h_trap))
13398+ goto out;
13399+ }
13400+
13401+ err = 0;
13402+ if (a->dst_bstart != a->btgt)
13403+ goto out;
13404+
13405+ err = -EIO;
13406+ h_inode = a->dst_h_dentry->d_inode;
13407+ isdir = !!au_ftest_ren(a->flags, ISDIR);
13408+ if (!a->dst_dentry->d_inode) {
13409+ if (unlikely(h_inode))
13410+ goto out;
13411+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
13412+ isdir);
13413+ } else {
13414+ if (unlikely(!h_inode || !h_inode->i_nlink))
13415+ goto out;
13416+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
13417+ isdir);
13418+ if (unlikely(err))
13419+ goto out;
13420+ err = -ENOTEMPTY;
13421+ if (unlikely(a->dst_h_dentry == a->h_trap))
13422+ goto out;
13423+ err = 0;
13424+ }
1facf9fc 13425+
dece6358
AM
13426+ out:
13427+ if (unlikely(err == -ENOENT || err == -EEXIST))
13428+ err = -EIO;
13429+ return err;
1facf9fc 13430+}
13431+
dece6358 13432+/* ---------------------------------------------------------------------- */
1facf9fc 13433+
13434+/*
dece6358
AM
13435+ * locking order
13436+ * (VFS)
13437+ * - src_dir and dir by lock_rename()
13438+ * - inode if exitsts
13439+ * (aufs)
13440+ * - lock all
13441+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
13442+ * + si_read_lock
13443+ * + di_write_lock2_child()
13444+ * + di_write_lock_child()
13445+ * + ii_write_lock_child()
13446+ * + di_write_lock_child2()
13447+ * + ii_write_lock_child2()
13448+ * + src_parent and parent
13449+ * + di_write_lock_parent()
13450+ * + ii_write_lock_parent()
13451+ * + di_write_lock_parent2()
13452+ * + ii_write_lock_parent2()
13453+ * + lower src_dir and dir by vfsub_lock_rename()
13454+ * + verify the every relationships between child and parent. if any
13455+ * of them failed, unlock all and return -EBUSY.
1facf9fc 13456+ */
dece6358 13457+static void au_ren_unlock(struct au_ren_args *a)
1facf9fc 13458+{
dece6358 13459+ struct super_block *sb;
1facf9fc 13460+
dece6358
AM
13461+ sb = a->dst_dentry->d_sb;
13462+ if (au_ftest_ren(a->flags, MNT_WRITE))
13463+ mnt_drop_write(a->br->br_mnt);
13464+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
13465+ a->dst_h_parent, a->dst_hdir);
1facf9fc 13466+}
13467+
dece6358 13468+static int au_ren_lock(struct au_ren_args *a)
1facf9fc 13469+{
dece6358
AM
13470+ int err;
13471+ unsigned int udba;
13472+
13473+ err = 0;
13474+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
13475+ a->src_hdir = au_hi(a->src_dir, a->btgt);
13476+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
13477+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
13478+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
13479+ a->dst_h_parent, a->dst_hdir);
13480+ udba = au_opt_udba(a->src_dentry->d_sb);
13481+ if (au_dbstart(a->src_dentry) == a->btgt)
13482+ err = au_h_verify(a->src_h_dentry, udba,
13483+ a->src_h_parent->d_inode, a->src_h_parent,
13484+ a->br);
13485+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
13486+ err = au_h_verify(a->dst_h_dentry, udba,
13487+ a->dst_h_parent->d_inode, a->dst_h_parent,
13488+ a->br);
13489+ if (!err) {
13490+ err = mnt_want_write(a->br->br_mnt);
13491+ if (unlikely(err))
13492+ goto out_unlock;
13493+ au_fset_ren(a->flags, MNT_WRITE);
13494+ goto out; /* success */
1facf9fc 13495+ }
dece6358
AM
13496+
13497+ err = au_busy_or_stale();
13498+
13499+ out_unlock:
13500+ au_ren_unlock(a);
13501+ out:
13502+ return err;
1facf9fc 13503+}
13504+
13505+/* ---------------------------------------------------------------------- */
13506+
dece6358 13507+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 13508+{
dece6358 13509+ struct inode *dir;
1facf9fc 13510+
dece6358
AM
13511+ dir = a->dst_dir;
13512+ dir->i_version++;
13513+ if (au_ftest_ren(a->flags, ISDIR)) {
13514+ /* is this updating defined in POSIX? */
13515+ au_cpup_attr_timesizes(a->src_inode);
13516+ au_cpup_attr_nlink(dir, /*force*/1);
13517+ if (a->dst_inode) {
13518+ clear_nlink(a->dst_inode);
13519+ au_cpup_attr_timesizes(a->dst_inode);
13520+ }
13521+ }
13522+ if (au_ibstart(dir) == a->btgt)
13523+ au_cpup_attr_timesizes(dir);
1facf9fc 13524+
dece6358
AM
13525+ if (au_ftest_ren(a->flags, ISSAMEDIR))
13526+ return;
1facf9fc 13527+
dece6358
AM
13528+ dir = a->src_dir;
13529+ dir->i_version++;
13530+ if (au_ftest_ren(a->flags, ISDIR))
13531+ au_cpup_attr_nlink(dir, /*force*/1);
13532+ if (au_ibstart(dir) == a->btgt)
13533+ au_cpup_attr_timesizes(dir);
1facf9fc 13534+}
13535+
dece6358 13536+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 13537+{
dece6358
AM
13538+ aufs_bindex_t bend, bindex;
13539+ struct dentry *d, *h_d;
13540+ struct inode *i, *h_i;
13541+ struct super_block *sb;
1facf9fc 13542+
dece6358
AM
13543+ d = a->src_dentry;
13544+ au_set_dbwh(d, -1);
13545+ bend = au_dbend(d);
13546+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
13547+ h_d = au_h_dptr(d, bindex);
13548+ if (h_d)
13549+ au_set_h_dptr(d, bindex, NULL);
13550+ }
13551+ au_set_dbend(d, a->btgt);
1facf9fc 13552+
dece6358
AM
13553+ sb = d->d_sb;
13554+ i = a->src_inode;
13555+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
13556+ return; /* success */
1facf9fc 13557+
dece6358
AM
13558+ bend = au_ibend(i);
13559+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
13560+ h_i = au_h_iptr(i, bindex);
13561+ if (h_i) {
13562+ au_xino_write0(sb, bindex, h_i->i_ino, 0);
13563+ /* ignore this error */
13564+ au_set_h_iptr(i, bindex, NULL, 0);
13565+ }
13566+ }
13567+ au_set_ibend(i, a->btgt);
1facf9fc 13568+}
13569+
13570+/* ---------------------------------------------------------------------- */
13571+
dece6358
AM
13572+/* mainly for link(2) and rename(2) */
13573+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1facf9fc 13574+{
dece6358
AM
13575+ aufs_bindex_t bdiropq, bwh;
13576+ struct dentry *parent;
13577+ struct au_branch *br;
13578+
13579+ parent = dentry->d_parent;
13580+ IMustLock(parent->d_inode); /* dir is locked */
13581+
13582+ bdiropq = au_dbdiropq(parent);
13583+ bwh = au_dbwh(dentry);
13584+ br = au_sbr(dentry->d_sb, btgt);
13585+ if (au_br_rdonly(br)
13586+ || (0 <= bdiropq && bdiropq < btgt)
13587+ || (0 <= bwh && bwh < btgt))
13588+ btgt = -1;
13589+
13590+ AuDbg("btgt %d\n", btgt);
13591+ return btgt;
1facf9fc 13592+}
13593+
dece6358
AM
13594+/* sets src_bstart, dst_bstart and btgt */
13595+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 13596+{
dece6358
AM
13597+ int err;
13598+ struct au_wr_dir_args wr_dir_args = {
13599+ /* .force_btgt = -1, */
13600+ .flags = AuWrDir_ADD_ENTRY
13601+ };
13602+
13603+ a->src_bstart = au_dbstart(a->src_dentry);
13604+ a->dst_bstart = au_dbstart(a->dst_dentry);
13605+ if (au_ftest_ren(a->flags, ISDIR))
13606+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
13607+ wr_dir_args.force_btgt = a->src_bstart;
13608+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
13609+ wr_dir_args.force_btgt = a->dst_bstart;
13610+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
13611+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
13612+ a->btgt = err;
13613+
13614+ return err;
1facf9fc 13615+}
13616+
dece6358 13617+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 13618+{
dece6358
AM
13619+ a->h_path.dentry = a->src_h_parent;
13620+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
13621+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
13622+ a->h_path.dentry = a->dst_h_parent;
13623+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
13624+ }
13625+
13626+ au_fclr_ren(a->flags, DT_DSTDIR);
13627+ if (!au_ftest_ren(a->flags, ISDIR))
13628+ return;
13629+
13630+ a->h_path.dentry = a->src_h_dentry;
13631+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
13632+ if (a->dst_h_dentry->d_inode) {
13633+ au_fset_ren(a->flags, DT_DSTDIR);
13634+ a->h_path.dentry = a->dst_h_dentry;
13635+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
13636+ }
1facf9fc 13637+}
13638+
dece6358 13639+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1facf9fc 13640+{
dece6358
AM
13641+ struct dentry *h_d;
13642+ struct mutex *h_mtx;
1facf9fc 13643+
dece6358
AM
13644+ au_dtime_revert(a->src_dt + AuPARENT);
13645+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
13646+ au_dtime_revert(a->dst_dt + AuPARENT);
13647+
13648+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
13649+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
13650+ h_mtx = &h_d->d_inode->i_mutex;
13651+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13652+ au_dtime_revert(a->src_dt + AuCHILD);
13653+ mutex_unlock(h_mtx);
13654+
13655+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
13656+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
13657+ h_mtx = &h_d->d_inode->i_mutex;
13658+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13659+ au_dtime_revert(a->dst_dt + AuCHILD);
13660+ mutex_unlock(h_mtx);
1facf9fc 13661+ }
13662+ }
13663+}
13664+
dece6358
AM
13665+/* ---------------------------------------------------------------------- */
13666+
13667+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
13668+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 13669+{
dece6358
AM
13670+ int err;
13671+ /* reduce stack space */
13672+ struct au_ren_args *a;
13673+
13674+ IMustLock(_src_dir);
13675+ IMustLock(_dst_dir);
13676+
13677+ err = -ENOMEM;
13678+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
13679+ a = kzalloc(sizeof(*a), GFP_NOFS);
13680+ if (unlikely(!a))
13681+ goto out;
13682+
13683+ a->src_dir = _src_dir;
13684+ a->src_dentry = _src_dentry;
13685+ a->src_inode = a->src_dentry->d_inode;
13686+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
13687+ a->dst_dir = _dst_dir;
13688+ a->dst_dentry = _dst_dentry;
13689+ a->dst_inode = a->dst_dentry->d_inode;
13690+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
13691+ if (a->dst_inode) {
13692+ IMustLock(a->dst_inode);
13693+ au_igrab(a->dst_inode);
1facf9fc 13694+ }
1facf9fc 13695+
dece6358
AM
13696+ err = -ENOTDIR;
13697+ if (S_ISDIR(a->src_inode->i_mode)) {
13698+ au_fset_ren(a->flags, ISDIR);
13699+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
13700+ goto out_free;
13701+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
13702+ AuLock_DIR | AuLock_FLUSH);
13703+ } else
13704+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
13705+ AuLock_FLUSH);
1facf9fc 13706+
dece6358
AM
13707+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
13708+ di_write_lock_parent(a->dst_parent);
1facf9fc 13709+
dece6358
AM
13710+ /* which branch we process */
13711+ err = au_ren_wbr(a);
13712+ if (unlikely(err < 0))
13713+ goto out_unlock;
13714+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
13715+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 13716+
dece6358
AM
13717+ /* are they available to be renamed */
13718+ err = au_ren_may_dir(a);
13719+ if (unlikely(err))
13720+ goto out_unlock;
1facf9fc 13721+
dece6358
AM
13722+ /* prepare the writable parent dir on the same branch */
13723+ if (a->dst_bstart == a->btgt) {
13724+ au_fset_ren(a->flags, WHDST);
13725+ } else {
13726+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
13727+ if (unlikely(err))
13728+ goto out_children;
13729+ }
1facf9fc 13730+
dece6358
AM
13731+ if (a->src_dir != a->dst_dir) {
13732+ /*
13733+ * this temporary unlock is safe,
13734+ * because both dir->i_mutex are locked.
13735+ */
13736+ di_write_unlock(a->dst_parent);
13737+ di_write_lock_parent(a->src_parent);
13738+ err = au_wr_dir_need_wh(a->src_dentry,
13739+ au_ftest_ren(a->flags, ISDIR),
13740+ &a->btgt);
13741+ di_write_unlock(a->src_parent);
13742+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
13743+ au_fclr_ren(a->flags, ISSAMEDIR);
13744+ } else
13745+ err = au_wr_dir_need_wh(a->src_dentry,
13746+ au_ftest_ren(a->flags, ISDIR),
13747+ &a->btgt);
13748+ if (unlikely(err < 0))
13749+ goto out_children;
13750+ if (err)
13751+ au_fset_ren(a->flags, WHSRC);
1facf9fc 13752+
dece6358
AM
13753+ /* lock them all */
13754+ err = au_ren_lock(a);
13755+ if (unlikely(err))
13756+ goto out_children;
1facf9fc 13757+
dece6358
AM
13758+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) {
13759+ err = au_may_ren(a);
13760+ if (unlikely(err))
13761+ goto out_hdir;
13762+ }
1facf9fc 13763+
dece6358
AM
13764+ /* store timestamps to be revertible */
13765+ au_ren_dt(a);
1facf9fc 13766+
dece6358
AM
13767+ /* here we go */
13768+ err = do_rename(a);
13769+ if (unlikely(err))
13770+ goto out_dt;
1facf9fc 13771+
dece6358
AM
13772+ /* update dir attributes */
13773+ au_ren_refresh_dir(a);
1facf9fc 13774+
dece6358
AM
13775+ /* dput/iput all lower dentries */
13776+ au_ren_refresh(a);
1facf9fc 13777+
dece6358
AM
13778+ goto out_hdir; /* success */
13779+
13780+ out_dt:
13781+ au_ren_rev_dt(err, a);
13782+ out_hdir:
13783+ au_ren_unlock(a);
13784+ out_children:
13785+ au_nhash_wh_free(&a->whlist);
13786+ out_unlock:
13787+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
13788+ au_update_dbstart(a->dst_dentry);
13789+ d_drop(a->dst_dentry);
13790+ }
13791+ if (!err)
13792+ d_move(a->src_dentry, a->dst_dentry);
13793+ if (au_ftest_ren(a->flags, ISSAMEDIR))
13794+ di_write_unlock(a->dst_parent);
13795+ else
13796+ di_write_unlock2(a->src_parent, a->dst_parent);
13797+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
13798+ out_free:
13799+ iput(a->dst_inode);
13800+ if (a->thargs)
13801+ au_whtmp_rmdir_free(a->thargs);
13802+ kfree(a);
13803+ out:
13804+ return err;
1facf9fc 13805+}
dece6358
AM
13806diff -urN linux-2.6.30.org/fs/aufs/Kconfig linux-2.6.30/fs/aufs/Kconfig
13807--- linux-2.6.30.org/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
13808+++ linux-2.6.30/fs/aufs/Kconfig 2009-07-21 08:54:18.000000000 +0200
13809@@ -0,0 +1,132 @@
13810+config AUFS_FS
13811+ tristate "Aufs (Advanced multi layered unification filesystem) support"
13812+ depends on EXPERIMENTAL
13813+ help
13814+ Aufs is a stackable unification filesystem such as Unionfs,
13815+ which unifies several directories and provides a merged single
13816+ directory.
13817+ In the early days, aufs was entirely re-designed and
13818+ re-implemented Unionfs Version 1.x series. Introducing many
13819+ original ideas, approaches and improvements, it becomes totally
13820+ different from Unionfs while keeping the basic features.
13821+
13822+if AUFS_FS
13823+choice
13824+ prompt "Maximum number of branches"
13825+ default AUFS_BRANCH_MAX_127
13826+ help
13827+ Specifies the maximum number of branches (or member directories)
13828+ in a single aufs. The larger value consumes more system
13829+ resources and has a minor impact to performance.
13830+config AUFS_BRANCH_MAX_127
13831+ bool "127"
13832+ help
13833+ Specifies the maximum number of branches (or member directories)
13834+ in a single aufs. The larger value consumes more system
13835+ resources and has a minor impact to performance.
13836+config AUFS_BRANCH_MAX_511
13837+ bool "511"
13838+ help
13839+ Specifies the maximum number of branches (or member directories)
13840+ in a single aufs. The larger value consumes more system
13841+ resources and has a minor impact to performance.
13842+config AUFS_BRANCH_MAX_1023
13843+ bool "1023"
13844+ help
13845+ Specifies the maximum number of branches (or member directories)
13846+ in a single aufs. The larger value consumes more system
13847+ resources and has a minor impact to performance.
13848+config AUFS_BRANCH_MAX_32767
13849+ bool "32767"
13850+ help
13851+ Specifies the maximum number of branches (or member directories)
13852+ in a single aufs. The larger value consumes more system
13853+ resources and has a minor impact to performance.
13854+endchoice
1facf9fc 13855+
dece6358
AM
13856+config AUFS_HINOTIFY
13857+ bool "Use inotify to detect actions on a branch"
13858+ depends on INOTIFY
13859+ help
13860+ If you want to modify files on branches directly, eg. bypassing aufs,
13861+ and want aufs to detect the changes of them fully, then enable this
13862+ option and use 'udba=inotify' mount option.
13863+ It will have a negative impact to the performance.
13864+ See detail in aufs.5.
1facf9fc 13865+
dece6358
AM
13866+config AUFS_EXPORT
13867+ bool "NFS-exportable aufs"
13868+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
13869+ help
13870+ If you want to export your mounted aufs via NFS, then enable this
13871+ option. There are several requirements for this configuration.
13872+ See detail in aufs.5.
1facf9fc 13873+
dece6358
AM
13874+config AUFS_SHWH
13875+ bool "Show whiteouts"
13876+ help
13877+ If you want to make the whiteouts in aufs visible, then enable
13878+ this option and specify 'shwh' mount option. Although it may
13879+ sounds like philosophy or something, but in technically it
13880+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 13881+
dece6358
AM
13882+config AUFS_BR_RAMFS
13883+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
13884+ help
13885+ If you want to use ramfs as an aufs branch fs, then enable this
13886+ option. Generally tmpfs is recommended.
13887+ Aufs prohibited them to be a branch fs by default, because
13888+ initramfs becomes unusable after switch_root or something
13889+ generally. If you sets initramfs as an aufs branch and boot your
13890+ system by switch_root, you will meet a problem easily since the
13891+ files in initramfs may be inaccessible.
13892+ Unless you are going to use ramfs as an aufs branch fs without
13893+ switch_root or something, leave it N.
1facf9fc 13894+
dece6358
AM
13895+config AUFS_BR_FUSE
13896+ bool "Fuse fs as an aufs branch"
13897+ depends on FUSE_FS
13898+ select AUFS_POLL
13899+ help
13900+ If you want to use fuse-based userspace filesystem as an aufs
13901+ branch fs, then enable this option.
13902+ It implements the internal poll(2) operation which is
13903+ implemented by fuse only (curretnly).
1facf9fc 13904+
dece6358
AM
13905+config AUFS_DEBUG
13906+ bool "Debug aufs"
13907+ help
13908+ Enable this to compile aufs internal debug code.
13909+ It will have a negative impact to the performance.
1facf9fc 13910+
dece6358
AM
13911+config AUFS_MAGIC_SYSRQ
13912+ bool
13913+ depends on AUFS_DEBUG && MAGIC_SYSRQ
13914+ default y
13915+ help
13916+ Automatic configuration for internal use.
13917+ When aufs supports Magic SysRq, enabled automatically.
1facf9fc 13918+
dece6358
AM
13919+config AUFS_BDEV_LOOP
13920+ bool
13921+ depends on BLK_DEV_LOOP
13922+ default y
13923+ help
13924+ Automatic configuration for internal use.
13925+ Convert =[ym] into =y.
1facf9fc 13926+
dece6358
AM
13927+config AUFS_INO_T_64
13928+ bool
13929+ depends on AUFS_EXPORT
13930+ depends on 64BIT && !(ALPHA || S390)
13931+ default y
13932+ help
13933+ Automatic configuration for internal use.
13934+ /* typedef unsigned long/int __kernel_ino_t */
13935+ /* alpha and s390x are int */
1facf9fc 13936+
dece6358
AM
13937+config AUFS_POLL
13938+ bool
13939+ help
13940+ Automatic configuration for internal use.
13941+endif
13942diff -urN linux-2.6.30.org/fs/aufs/loop.c linux-2.6.30/fs/aufs/loop.c
13943--- linux-2.6.30.org/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
13944+++ linux-2.6.30/fs/aufs/loop.c 2009-07-21 08:54:19.000000000 +0200
13945@@ -0,0 +1,55 @@
1facf9fc 13946+/*
13947+ * Copyright (C) 2005-2009 Junjiro R. Okajima
13948+ *
13949+ * This program, aufs is free software; you can redistribute it and/or modify
13950+ * it under the terms of the GNU General Public License as published by
13951+ * the Free Software Foundation; either version 2 of the License, or
13952+ * (at your option) any later version.
dece6358
AM
13953+ *
13954+ * This program is distributed in the hope that it will be useful,
13955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13957+ * GNU General Public License for more details.
13958+ *
13959+ * You should have received a copy of the GNU General Public License
13960+ * along with this program; if not, write to the Free Software
13961+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 13962+ */
13963+
13964+/*
13965+ * support for loopback block device as a branch
13966+ */
13967+
13968+#include <linux/loop.h>
13969+#include "aufs.h"
13970+
13971+/*
13972+ * test if two lower dentries have overlapping branches.
13973+ */
13974+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
13975+ struct dentry *h_d2)
13976+{
13977+ struct inode *h_inode;
13978+ struct loop_device *l;
13979+
13980+ h_inode = h_d1->d_inode;
13981+ if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
13982+ return 0;
13983+
13984+ l = h_inode->i_sb->s_bdev->bd_disk->private_data;
13985+ h_d1 = l->lo_backing_file->f_dentry;
13986+ /* h_d1 can be local NFS. in this case aufs cannot detect the loop */
13987+ if (unlikely(h_d1->d_sb == sb))
13988+ return 1;
13989+ return !!au_test_subdir(h_d1, h_d2);
13990+}
13991+
13992+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
13993+int au_test_loopback_kthread(void)
13994+{
13995+ const char c = current->comm[4];
13996+
13997+ return current->mm == NULL
13998+ && '0' <= c && c <= '9'
13999+ && strncmp(current->comm, "loop", 4) == 0;
14000+}
dece6358
AM
14001diff -urN linux-2.6.30.org/fs/aufs/loop.h linux-2.6.30/fs/aufs/loop.h
14002--- linux-2.6.30.org/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
14003+++ linux-2.6.30/fs/aufs/loop.h 2009-07-21 08:54:19.000000000 +0200
14004@@ -0,0 +1,51 @@
1facf9fc 14005+/*
14006+ * Copyright (C) 2005-2009 Junjiro R. Okajima
14007+ *
14008+ * This program, aufs is free software; you can redistribute it and/or modify
14009+ * it under the terms of the GNU General Public License as published by
14010+ * the Free Software Foundation; either version 2 of the License, or
14011+ * (at your option) any later version.
dece6358
AM
14012+ *
14013+ * This program is distributed in the hope that it will be useful,
14014+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14015+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14016+ * GNU General Public License for more details.
14017+ *
14018+ * You should have received a copy of the GNU General Public License
14019+ * along with this program; if not, write to the Free Software
14020+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14021+ */
14022+
14023+/*
14024+ * support for loopback mount as a branch
14025+ */
14026+
14027+#ifndef __AUFS_LOOP_H__
14028+#define __AUFS_LOOP_H__
14029+
14030+#ifdef __KERNEL__
14031+
dece6358
AM
14032+struct dentry;
14033+struct super_block;
1facf9fc 14034+
14035+#ifdef CONFIG_AUFS_BDEV_LOOP
14036+/* loop.c */
14037+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
14038+ struct dentry *h_d2);
14039+int au_test_loopback_kthread(void);
14040+#else
14041+static inline
14042+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
14043+ struct dentry *h_d2)
14044+{
14045+ return 0;
14046+}
14047+
14048+static inline int au_test_loopback_kthread(void)
14049+{
14050+ return 0;
14051+}
14052+#endif /* BLK_DEV_LOOP */
14053+
14054+#endif /* __KERNEL__ */
14055+#endif /* __AUFS_LOOP_H__ */
dece6358
AM
14056diff -urN linux-2.6.30.org/fs/aufs/magic.mk linux-2.6.30/fs/aufs/magic.mk
14057--- linux-2.6.30.org/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
14058+++ linux-2.6.30/fs/aufs/magic.mk 2009-07-21 08:54:19.000000000 +0200
14059@@ -0,0 +1,52 @@
1facf9fc 14060+
14061+# defined in ${srctree}/fs/fuse/inode.c
14062+# tristate
14063+ifdef CONFIG_FUSE_FS
14064+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
14065+endif
14066+
14067+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
14068+# tristate
14069+ifdef CONFIG_OCFS2_FS
14070+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
14071+endif
14072+
14073+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
14074+# tristate
14075+ifdef CONFIG_OCFS2_FS_O2CB
14076+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
14077+endif
14078+
14079+# defined in ${srctree}/fs/ramfs/inode.c
14080+# always true
14081+ccflags-y += -DRAMFS_MAGIC=0x858458f6
14082+
14083+# defined in ${srctree}/fs/cifs/cifsfs.c
14084+# tristate
14085+ifdef CONFIG_CIFS_FS
14086+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
14087+endif
14088+
14089+# defined in ${srctree}/fs/xfs/xfs_sb.h
14090+# tristate
14091+ifdef CONFIG_XFS_FS
14092+ccflags-y += -DXFS_SB_MAGIC=0x58465342
14093+endif
14094+
14095+# defined in ${srctree}/fs/configfs/mount.c
14096+# tristate
14097+ifdef CONFIG_CONFIGFS_FS
14098+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
14099+endif
14100+
14101+# defined in ${srctree}/fs/9p/v9fs.h
14102+# tristate
14103+ifdef CONFIG_9P_FS
14104+ccflags-y += -DV9FS_MAGIC=0x01021997
14105+endif
14106+
14107+# defined in ${srctree}/fs/ubifs/ubifs.h
14108+# tristate
14109+ifdef CONFIG_UBIFS_FS
14110+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
14111+endif
dece6358
AM
14112diff -urN linux-2.6.30.org/fs/aufs/Makefile linux-2.6.30/fs/aufs/Makefile
14113--- linux-2.6.30.org/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
14114+++ linux-2.6.30/fs/aufs/Makefile 2009-07-21 08:54:18.000000000 +0200
14115@@ -0,0 +1,23 @@
1facf9fc 14116+
dece6358
AM
14117+include ${src}/magic.mk
14118+-include ${src}/priv_def.mk
14119+
14120+obj-$(CONFIG_AUFS_FS) += aufs.o
14121+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
14122+ wkq.o vfsub.o dcsub.o \
14123+ cpup.o whout.o plink.o wbr_policy.o \
14124+ dinfo.o dentry.o \
14125+ finfo.o file.o f_op.o \
14126+ dir.o vdir.o \
14127+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
14128+ ioctl.o
14129+
14130+# all are boolean
14131+aufs-$(CONFIG_SYSFS) += sysfs.o
14132+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
14133+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
14134+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
14135+aufs-$(CONFIG_AUFS_EXPORT) += export.o
14136+aufs-$(CONFIG_AUFS_POLL) += poll.o
14137+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
14138+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
14139diff -urN linux-2.6.30.org/fs/aufs/module.c linux-2.6.30/fs/aufs/module.c
14140--- linux-2.6.30.org/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
14141+++ linux-2.6.30/fs/aufs/module.c 2009-07-21 08:54:19.000000000 +0200
14142@@ -0,0 +1,173 @@
1facf9fc 14143+/*
14144+ * Copyright (C) 2005-2009 Junjiro R. Okajima
14145+ *
14146+ * This program, aufs is free software; you can redistribute it and/or modify
14147+ * it under the terms of the GNU General Public License as published by
14148+ * the Free Software Foundation; either version 2 of the License, or
14149+ * (at your option) any later version.
dece6358
AM
14150+ *
14151+ * This program is distributed in the hope that it will be useful,
14152+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14153+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14154+ * GNU General Public License for more details.
14155+ *
14156+ * You should have received a copy of the GNU General Public License
14157+ * along with this program; if not, write to the Free Software
14158+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14159+ */
14160+
14161+/*
14162+ * module global variables and operations
14163+ */
14164+
14165+#include <linux/module.h>
14166+#include <linux/seq_file.h>
14167+#include "aufs.h"
14168+
14169+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
14170+{
14171+ if (new_sz <= nused)
14172+ return p;
14173+
14174+ p = krealloc(p, new_sz, gfp);
14175+ if (p)
14176+ memset(p + nused, 0, new_sz - nused);
14177+ return p;
14178+}
14179+
14180+/* ---------------------------------------------------------------------- */
14181+
14182+/*
14183+ * aufs caches
14184+ */
14185+struct kmem_cache *au_cachep[AuCache_Last];
14186+static int __init au_cache_init(void)
14187+{
14188+ au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
14189+ if (au_cachep[AuCache_DINFO])
14190+ au_cachep[AuCache_ICNTNR] = AuCache(au_icntnr);
14191+ if (au_cachep[AuCache_ICNTNR])
14192+ au_cachep[AuCache_FINFO] = AuCache(au_finfo);
14193+ if (au_cachep[AuCache_FINFO])
14194+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
14195+ if (au_cachep[AuCache_VDIR])
14196+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
14197+ if (au_cachep[AuCache_DEHSTR])
14198+ return 0;
14199+
14200+ return -ENOMEM;
14201+}
14202+
14203+static void au_cache_fin(void)
14204+{
14205+ int i;
14206+ for (i = 0; i < AuCache_Last; i++)
14207+ if (au_cachep[i]) {
14208+ kmem_cache_destroy(au_cachep[i]);
14209+ au_cachep[i] = NULL;
14210+ }
14211+}
14212+
14213+/* ---------------------------------------------------------------------- */
14214+
14215+int au_dir_roflags;
14216+
14217+/*
14218+ * functions for module interface.
14219+ */
14220+MODULE_LICENSE("GPL");
14221+/* MODULE_LICENSE("GPL v2"); */
dece6358 14222+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 14223+MODULE_DESCRIPTION(AUFS_NAME
14224+ " -- Advanced multi layered unification filesystem");
14225+MODULE_VERSION(AUFS_VERSION);
14226+
14227+/* it should be 'byte', but param_set_byte() prints it by "%c" */
14228+short aufs_nwkq = AUFS_NWKQ_DEF;
14229+MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
14230+module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
14231+
14232+/* this module parameter has no meaning when SYSFS is disabled */
14233+int sysaufs_brs = 1;
14234+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
14235+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
14236+
14237+/* ---------------------------------------------------------------------- */
14238+
14239+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
14240+
14241+int au_seq_path(struct seq_file *seq, struct path *path)
14242+{
14243+ return seq_path(seq, path, au_esc_chars);
14244+}
14245+
14246+/* ---------------------------------------------------------------------- */
14247+
14248+static int __init aufs_init(void)
14249+{
14250+ int err, i;
14251+ char *p;
14252+
14253+ p = au_esc_chars;
14254+ for (i = 1; i <= ' '; i++)
14255+ *p++ = i;
14256+ *p++ = '\\';
14257+ *p++ = '\x7f';
14258+ *p = 0;
14259+
14260+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
14261+
14262+ sysaufs_brs_init();
14263+ au_debug_init();
14264+
14265+ err = -EINVAL;
14266+ if (unlikely(aufs_nwkq <= 0))
14267+ goto out;
14268+
14269+ err = sysaufs_init();
14270+ if (unlikely(err))
14271+ goto out;
14272+ err = au_wkq_init();
14273+ if (unlikely(err))
14274+ goto out_sysaufs;
14275+ err = au_hinotify_init();
14276+ if (unlikely(err))
14277+ goto out_wkq;
14278+ err = au_sysrq_init();
14279+ if (unlikely(err))
14280+ goto out_hin;
14281+ err = au_cache_init();
14282+ if (unlikely(err))
14283+ goto out_sysrq;
14284+ err = register_filesystem(&aufs_fs_type);
14285+ if (unlikely(err))
14286+ goto out_cache;
14287+ pr_info(AUFS_NAME " " AUFS_VERSION "\n");
14288+ goto out; /* success */
14289+
14290+ out_cache:
14291+ au_cache_fin();
14292+ out_sysrq:
14293+ au_sysrq_fin();
14294+ out_hin:
14295+ au_hinotify_fin();
14296+ out_wkq:
14297+ au_wkq_fin();
14298+ out_sysaufs:
14299+ sysaufs_fin();
14300+ out:
14301+ return err;
14302+}
14303+
14304+static void __exit aufs_exit(void)
14305+{
14306+ unregister_filesystem(&aufs_fs_type);
14307+ au_cache_fin();
14308+ au_sysrq_fin();
14309+ au_hinotify_fin();
14310+ au_wkq_fin();
14311+ sysaufs_fin();
14312+}
14313+
14314+module_init(aufs_init);
14315+module_exit(aufs_exit);
dece6358
AM
14316diff -urN linux-2.6.30.org/fs/aufs/module.h linux-2.6.30/fs/aufs/module.h
14317--- linux-2.6.30.org/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
14318+++ linux-2.6.30/fs/aufs/module.h 2009-07-21 08:54:19.000000000 +0200
14319@@ -0,0 +1,78 @@
1facf9fc 14320+/*
14321+ * Copyright (C) 2005-2009 Junjiro R. Okajima
14322+ *
14323+ * This program, aufs is free software; you can redistribute it and/or modify
14324+ * it under the terms of the GNU General Public License as published by
14325+ * the Free Software Foundation; either version 2 of the License, or
14326+ * (at your option) any later version.
dece6358
AM
14327+ *
14328+ * This program is distributed in the hope that it will be useful,
14329+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14330+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14331+ * GNU General Public License for more details.
14332+ *
14333+ * You should have received a copy of the GNU General Public License
14334+ * along with this program; if not, write to the Free Software
14335+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14336+ */
14337+
14338+/*
14339+ * module initialization and module-global
14340+ */
14341+
14342+#ifndef __AUFS_MODULE_H__
14343+#define __AUFS_MODULE_H__
14344+
14345+#ifdef __KERNEL__
14346+
14347+#include <linux/slab.h>
14348+
dece6358
AM
14349+struct path;
14350+struct seq_file;
14351+
1facf9fc 14352+/* module parameters */
14353+extern short aufs_nwkq;
14354+extern int sysaufs_brs;
14355+
14356+/* ---------------------------------------------------------------------- */
14357+
14358+extern int au_dir_roflags;
14359+
14360+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
14361+int au_seq_path(struct seq_file *seq, struct path *path);
14362+
14363+/* ---------------------------------------------------------------------- */
14364+
14365+/* kmem cache */
14366+enum {
14367+ AuCache_DINFO,
14368+ AuCache_ICNTNR,
14369+ AuCache_FINFO,
14370+ AuCache_VDIR,
14371+ AuCache_DEHSTR,
14372+#ifdef CONFIG_AUFS_HINOTIFY
14373+ AuCache_HINOTIFY,
14374+#endif
14375+ AuCache_Last
14376+};
14377+
14378+#define AuCache(type) KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT)
14379+
14380+extern struct kmem_cache *au_cachep[];
14381+
14382+#define AuCacheFuncs(name, index) \
14383+static inline void *au_cache_alloc_##name(void) \
14384+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
14385+static inline void au_cache_free_##name(void *p) \
14386+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
14387+
14388+AuCacheFuncs(dinfo, DINFO);
14389+AuCacheFuncs(icntnr, ICNTNR);
14390+AuCacheFuncs(finfo, FINFO);
14391+AuCacheFuncs(vdir, VDIR);
14392+AuCacheFuncs(dehstr, DEHSTR);
14393+
14394+/* ---------------------------------------------------------------------- */
14395+
14396+#endif /* __KERNEL__ */
14397+#endif /* __AUFS_MODULE_H__ */
dece6358
AM
14398diff -urN linux-2.6.30.org/fs/aufs/opts.c linux-2.6.30/fs/aufs/opts.c
14399--- linux-2.6.30.org/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
14400+++ linux-2.6.30/fs/aufs/opts.c 2009-07-21 08:54:19.000000000 +0200
14401@@ -0,0 +1,1543 @@
1facf9fc 14402+/*
14403+ * Copyright (C) 2005-2009 Junjiro R. Okajima
14404+ *
14405+ * This program, aufs is free software; you can redistribute it and/or modify
14406+ * it under the terms of the GNU General Public License as published by
14407+ * the Free Software Foundation; either version 2 of the License, or
14408+ * (at your option) any later version.
dece6358
AM
14409+ *
14410+ * This program is distributed in the hope that it will be useful,
14411+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14412+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14413+ * GNU General Public License for more details.
14414+ *
14415+ * You should have received a copy of the GNU General Public License
14416+ * along with this program; if not, write to the Free Software
14417+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14418+ */
14419+
14420+/*
14421+ * mount options/flags
14422+ */
14423+
dece6358
AM
14424+#include <linux/file.h>
14425+#include <linux/namei.h>
1facf9fc 14426+#include <linux/types.h> /* a distribution requires */
14427+#include <linux/parser.h>
14428+#include "aufs.h"
14429+
14430+/* ---------------------------------------------------------------------- */
14431+
14432+enum {
14433+ Opt_br,
14434+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
14435+ Opt_idel, Opt_imod, Opt_ireorder,
14436+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 14437+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 14438+ Opt_xino, Opt_zxino, Opt_noxino,
14439+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
14440+ Opt_trunc_xino_path, Opt_itrunc_xino,
14441+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 14442+ Opt_shwh, Opt_noshwh,
1facf9fc 14443+ Opt_plink, Opt_noplink, Opt_list_plink,
14444+ Opt_udba,
14445+ /* Opt_lock, Opt_unlock, */
14446+ Opt_cmd, Opt_cmd_args,
14447+ Opt_diropq_a, Opt_diropq_w,
14448+ Opt_warn_perm, Opt_nowarn_perm,
14449+ Opt_wbr_copyup, Opt_wbr_create,
14450+ Opt_refrof, Opt_norefrof,
14451+ Opt_verbose, Opt_noverbose,
14452+ Opt_sum, Opt_nosum, Opt_wsum,
14453+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
14454+};
14455+
14456+static match_table_t options = {
14457+ {Opt_br, "br=%s"},
14458+ {Opt_br, "br:%s"},
14459+
14460+ {Opt_add, "add=%d:%s"},
14461+ {Opt_add, "add:%d:%s"},
14462+ {Opt_add, "ins=%d:%s"},
14463+ {Opt_add, "ins:%d:%s"},
14464+ {Opt_append, "append=%s"},
14465+ {Opt_append, "append:%s"},
14466+ {Opt_prepend, "prepend=%s"},
14467+ {Opt_prepend, "prepend:%s"},
14468+
14469+ {Opt_del, "del=%s"},
14470+ {Opt_del, "del:%s"},
14471+ /* {Opt_idel, "idel:%d"}, */
14472+ {Opt_mod, "mod=%s"},
14473+ {Opt_mod, "mod:%s"},
14474+ /* {Opt_imod, "imod:%d:%s"}, */
14475+
14476+ {Opt_dirwh, "dirwh=%d"},
14477+
14478+ {Opt_xino, "xino=%s"},
14479+ {Opt_noxino, "noxino"},
14480+ {Opt_trunc_xino, "trunc_xino"},
14481+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
14482+ {Opt_notrunc_xino, "notrunc_xino"},
14483+ {Opt_trunc_xino_path, "trunc_xino=%s"},
14484+ {Opt_itrunc_xino, "itrunc_xino=%d"},
14485+ /* {Opt_zxino, "zxino=%s"}, */
14486+ {Opt_trunc_xib, "trunc_xib"},
14487+ {Opt_notrunc_xib, "notrunc_xib"},
14488+
14489+ {Opt_plink, "plink"},
14490+ {Opt_noplink, "noplink"},
14491+#ifdef CONFIG_AUFS_DEBUG
14492+ {Opt_list_plink, "list_plink"},
14493+#endif
14494+
14495+ {Opt_udba, "udba=%s"},
14496+
14497+ {Opt_diropq_a, "diropq=always"},
14498+ {Opt_diropq_a, "diropq=a"},
14499+ {Opt_diropq_w, "diropq=whiteouted"},
14500+ {Opt_diropq_w, "diropq=w"},
14501+
14502+ {Opt_warn_perm, "warn_perm"},
14503+ {Opt_nowarn_perm, "nowarn_perm"},
14504+
14505+ /* keep them temporary */
14506+ {Opt_ignore_silent, "coo=%s"},
14507+ {Opt_ignore_silent, "nodlgt"},
14508+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 14509+ {Opt_ignore_silent, "clean_plink"},
14510+
dece6358
AM
14511+#ifdef CONFIG_AUFS_SHWH
14512+ {Opt_shwh, "shwh"},
14513+#endif
14514+ {Opt_noshwh, "noshwh"},
14515+
1facf9fc 14516+ {Opt_rendir, "rendir=%d"},
14517+
14518+ {Opt_refrof, "refrof"},
14519+ {Opt_norefrof, "norefrof"},
14520+
14521+ {Opt_verbose, "verbose"},
14522+ {Opt_verbose, "v"},
14523+ {Opt_noverbose, "noverbose"},
14524+ {Opt_noverbose, "quiet"},
14525+ {Opt_noverbose, "q"},
14526+ {Opt_noverbose, "silent"},
14527+
14528+ {Opt_sum, "sum"},
14529+ {Opt_nosum, "nosum"},
14530+ {Opt_wsum, "wsum"},
14531+
14532+ {Opt_rdcache, "rdcache=%d"},
14533+ {Opt_rdblk, "rdblk=%d"},
dece6358 14534+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 14535+ {Opt_rdhash, "rdhash=%d"},
dece6358 14536+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 14537+
14538+ {Opt_wbr_create, "create=%s"},
14539+ {Opt_wbr_create, "create_policy=%s"},
14540+ {Opt_wbr_copyup, "cpup=%s"},
14541+ {Opt_wbr_copyup, "copyup=%s"},
14542+ {Opt_wbr_copyup, "copyup_policy=%s"},
14543+
14544+ /* internal use for the scripts */
14545+ {Opt_ignore_silent, "si=%s"},
14546+
14547+ {Opt_br, "dirs=%s"},
14548+ {Opt_ignore, "debug=%d"},
14549+ {Opt_ignore, "delete=whiteout"},
14550+ {Opt_ignore, "delete=all"},
14551+ {Opt_ignore, "imap=%s"},
14552+
14553+ {Opt_err, NULL}
14554+};
14555+
14556+/* ---------------------------------------------------------------------- */
14557+
14558+static const char *au_parser_pattern(int val, struct match_token *token)
14559+{
14560+ while (token->pattern) {
14561+ if (token->token == val)
14562+ return token->pattern;
14563+ token++;
14564+ }
14565+ BUG();
14566+ return "??";
14567+}
14568+
14569+/* ---------------------------------------------------------------------- */
14570+
14571+static match_table_t brperms = {
14572+ {AuBrPerm_RO, AUFS_BRPERM_RO},
14573+ {AuBrPerm_RR, AUFS_BRPERM_RR},
14574+ {AuBrPerm_RW, AUFS_BRPERM_RW},
14575+
14576+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
14577+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
14578+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
14579+
14580+ {AuBrPerm_ROWH, "nfsro"},
14581+ {AuBrPerm_RO, NULL}
14582+};
14583+
14584+static int br_perm_val(char *perm)
14585+{
14586+ int val;
14587+ substring_t args[MAX_OPT_ARGS];
14588+
14589+ val = match_token(perm, brperms, args);
14590+ return val;
14591+}
14592+
14593+const char *au_optstr_br_perm(int brperm)
14594+{
14595+ return au_parser_pattern(brperm, (void *)brperms);
14596+}
14597+
14598+/* ---------------------------------------------------------------------- */
14599+
14600+static match_table_t udbalevel = {
14601+ {AuOpt_UDBA_REVAL, "reval"},
14602+ {AuOpt_UDBA_NONE, "none"},
14603+#ifdef CONFIG_AUFS_HINOTIFY
14604+ {AuOpt_UDBA_HINOTIFY, "inotify"},
14605+#endif
14606+ {-1, NULL}
14607+};
14608+
14609+static int udba_val(char *str)
14610+{
14611+ substring_t args[MAX_OPT_ARGS];
14612+
14613+ return match_token(str, udbalevel, args);
14614+}
14615+
14616+const char *au_optstr_udba(int udba)
14617+{
14618+ return au_parser_pattern(udba, (void *)udbalevel);
14619+}
14620+
14621+/* ---------------------------------------------------------------------- */
14622+
14623+static match_table_t au_wbr_create_policy = {
14624+ {AuWbrCreate_TDP, "tdp"},
14625+ {AuWbrCreate_TDP, "top-down-parent"},
14626+ {AuWbrCreate_RR, "rr"},
14627+ {AuWbrCreate_RR, "round-robin"},
14628+ {AuWbrCreate_MFS, "mfs"},
14629+ {AuWbrCreate_MFS, "most-free-space"},
14630+ {AuWbrCreate_MFSV, "mfs:%d"},
14631+ {AuWbrCreate_MFSV, "most-free-space:%d"},
14632+
14633+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
14634+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
14635+ {AuWbrCreate_PMFS, "pmfs"},
14636+ {AuWbrCreate_PMFSV, "pmfs:%d"},
14637+
14638+ {-1, NULL}
14639+};
14640+
dece6358
AM
14641+/*
14642+ * cf. linux/lib/parser.c and cmdline.c
14643+ * gave up calling memparse() since it uses simple_strtoull() instead of
14644+ * strict_...().
14645+ */
1facf9fc 14646+static int au_match_ull(substring_t *s, unsigned long long *result)
14647+{
14648+ int err;
14649+ unsigned int len;
14650+ char a[32];
14651+
14652+ err = -ERANGE;
14653+ len = s->to - s->from;
14654+ if (len + 1 <= sizeof(a)) {
14655+ memcpy(a, s->from, len);
14656+ a[len] = '\0';
14657+ err = strict_strtoull(a, 0, result);
14658+ }
14659+ return err;
14660+}
14661+
14662+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
14663+ struct au_opt_wbr_create *create)
14664+{
14665+ int err;
14666+ unsigned long long ull;
14667+
14668+ err = 0;
14669+ if (!au_match_ull(arg, &ull))
14670+ create->mfsrr_watermark = ull;
14671+ else {
14672+ AuErr("bad integer in %s\n", str);
14673+ err = -EINVAL;
14674+ }
14675+
14676+ return err;
14677+}
14678+
14679+static int au_wbr_mfs_sec(substring_t *arg, char *str,
14680+ struct au_opt_wbr_create *create)
14681+{
14682+ int n, err;
14683+
14684+ err = 0;
14685+ if (!match_int(arg, &n) && 0 <= n)
14686+ create->mfs_second = n;
14687+ else {
14688+ AuErr("bad integer in %s\n", str);
14689+ err = -EINVAL;
14690+ }
14691+
14692+ return err;
14693+}
14694+
14695+static int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
14696+{
14697+ int err, e;
14698+ substring_t args[MAX_OPT_ARGS];
14699+
14700+ err = match_token(str, au_wbr_create_policy, args);
14701+ create->wbr_create = err;
14702+ switch (err) {
14703+ case AuWbrCreate_MFSRRV:
14704+ e = au_wbr_mfs_wmark(&args[0], str, create);
14705+ if (!e)
14706+ e = au_wbr_mfs_sec(&args[1], str, create);
14707+ if (unlikely(e))
14708+ err = e;
14709+ break;
14710+ case AuWbrCreate_MFSRR:
14711+ e = au_wbr_mfs_wmark(&args[0], str, create);
14712+ if (unlikely(e)) {
14713+ err = e;
14714+ break;
14715+ }
14716+ /*FALLTHROUGH*/
14717+ case AuWbrCreate_MFS:
14718+ case AuWbrCreate_PMFS:
14719+ create->mfs_second = AUFS_MFS_SECOND_DEF;
14720+ break;
14721+ case AuWbrCreate_MFSV:
14722+ case AuWbrCreate_PMFSV:
14723+ e = au_wbr_mfs_sec(&args[0], str, create);
14724+ if (unlikely(e))
14725+ err = e;
14726+ break;
14727+ }
14728+
14729+ return err;
14730+}
14731+
14732+const char *au_optstr_wbr_create(int wbr_create)
14733+{
14734+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
14735+}
14736+
14737+static match_table_t au_wbr_copyup_policy = {
14738+ {AuWbrCopyup_TDP, "tdp"},
14739+ {AuWbrCopyup_TDP, "top-down-parent"},
14740+ {AuWbrCopyup_BUP, "bup"},
14741+ {AuWbrCopyup_BUP, "bottom-up-parent"},
14742+ {AuWbrCopyup_BU, "bu"},
14743+ {AuWbrCopyup_BU, "bottom-up"},
14744+ {-1, NULL}
14745+};
14746+
14747+static int au_wbr_copyup_val(char *str)
14748+{
14749+ substring_t args[MAX_OPT_ARGS];
14750+
14751+ return match_token(str, au_wbr_copyup_policy, args);
14752+}
14753+
14754+const char *au_optstr_wbr_copyup(int wbr_copyup)
14755+{
14756+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
14757+}
14758+
14759+/* ---------------------------------------------------------------------- */
14760+
14761+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
14762+
14763+static void dump_opts(struct au_opts *opts)
14764+{
14765+#ifdef CONFIG_AUFS_DEBUG
14766+ /* reduce stack space */
14767+ union {
14768+ struct au_opt_add *add;
14769+ struct au_opt_del *del;
14770+ struct au_opt_mod *mod;
14771+ struct au_opt_xino *xino;
14772+ struct au_opt_xino_itrunc *xino_itrunc;
14773+ struct au_opt_wbr_create *create;
14774+ } u;
14775+ struct au_opt *opt;
14776+
14777+ opt = opts->opt;
14778+ while (opt->type != Opt_tail) {
14779+ switch (opt->type) {
14780+ case Opt_add:
14781+ u.add = &opt->add;
14782+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
14783+ u.add->bindex, u.add->pathname, u.add->perm,
14784+ u.add->path.dentry);
14785+ break;
14786+ case Opt_del:
14787+ case Opt_idel:
14788+ u.del = &opt->del;
14789+ AuDbg("del {%s, %p}\n",
14790+ u.del->pathname, u.del->h_path.dentry);
14791+ break;
14792+ case Opt_mod:
14793+ case Opt_imod:
14794+ u.mod = &opt->mod;
14795+ AuDbg("mod {%s, 0x%x, %p}\n",
14796+ u.mod->path, u.mod->perm, u.mod->h_root);
14797+ break;
14798+ case Opt_append:
14799+ u.add = &opt->add;
14800+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
14801+ u.add->bindex, u.add->pathname, u.add->perm,
14802+ u.add->path.dentry);
14803+ break;
14804+ case Opt_prepend:
14805+ u.add = &opt->add;
14806+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
14807+ u.add->bindex, u.add->pathname, u.add->perm,
14808+ u.add->path.dentry);
14809+ break;
14810+ case Opt_dirwh:
14811+ AuDbg("dirwh %d\n", opt->dirwh);
14812+ break;
14813+ case Opt_rdcache:
14814+ AuDbg("rdcache %d\n", opt->rdcache);
14815+ break;
14816+ case Opt_rdblk:
14817+ AuDbg("rdblk %u\n", opt->rdblk);
14818+ break;
dece6358
AM
14819+ case Opt_rdblk_def:
14820+ AuDbg("rdblk_def\n");
14821+ break;
1facf9fc 14822+ case Opt_rdhash:
14823+ AuDbg("rdhash %u\n", opt->rdhash);
14824+ break;
dece6358
AM
14825+ case Opt_rdhash_def:
14826+ AuDbg("rdhash_def\n");
14827+ break;
1facf9fc 14828+ case Opt_xino:
14829+ u.xino = &opt->xino;
14830+ AuDbg("xino {%s %.*s}\n",
14831+ u.xino->path,
14832+ AuDLNPair(u.xino->file->f_dentry));
14833+ break;
14834+ case Opt_trunc_xino:
14835+ AuLabel(trunc_xino);
14836+ break;
14837+ case Opt_notrunc_xino:
14838+ AuLabel(notrunc_xino);
14839+ break;
14840+ case Opt_trunc_xino_path:
14841+ case Opt_itrunc_xino:
14842+ u.xino_itrunc = &opt->xino_itrunc;
14843+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
14844+ break;
14845+
14846+ case Opt_noxino:
14847+ AuLabel(noxino);
14848+ break;
14849+ case Opt_trunc_xib:
14850+ AuLabel(trunc_xib);
14851+ break;
14852+ case Opt_notrunc_xib:
14853+ AuLabel(notrunc_xib);
14854+ break;
dece6358
AM
14855+ case Opt_shwh:
14856+ AuLabel(shwh);
14857+ break;
14858+ case Opt_noshwh:
14859+ AuLabel(noshwh);
14860+ break;
1facf9fc 14861+ case Opt_plink:
14862+ AuLabel(plink);
14863+ break;
14864+ case Opt_noplink:
14865+ AuLabel(noplink);
14866+ break;
14867+ case Opt_list_plink:
14868+ AuLabel(list_plink);
14869+ break;
14870+ case Opt_udba:
14871+ AuDbg("udba %d, %s\n",
14872+ opt->udba, au_optstr_udba(opt->udba));
14873+ break;
14874+ case Opt_diropq_a:
14875+ AuLabel(diropq_a);
14876+ break;
14877+ case Opt_diropq_w:
14878+ AuLabel(diropq_w);
14879+ break;
14880+ case Opt_warn_perm:
14881+ AuLabel(warn_perm);
14882+ break;
14883+ case Opt_nowarn_perm:
14884+ AuLabel(nowarn_perm);
14885+ break;
14886+ case Opt_refrof:
14887+ AuLabel(refrof);
14888+ break;
14889+ case Opt_norefrof:
14890+ AuLabel(norefrof);
14891+ break;
14892+ case Opt_verbose:
14893+ AuLabel(verbose);
14894+ break;
14895+ case Opt_noverbose:
14896+ AuLabel(noverbose);
14897+ break;
14898+ case Opt_sum:
14899+ AuLabel(sum);
14900+ break;
14901+ case Opt_nosum:
14902+ AuLabel(nosum);
14903+ break;
14904+ case Opt_wsum:
14905+ AuLabel(wsum);
14906+ break;
14907+ case Opt_wbr_create:
14908+ u.create = &opt->wbr_create;
14909+ AuDbg("create %d, %s\n", u.create->wbr_create,
14910+ au_optstr_wbr_create(u.create->wbr_create));
14911+ switch (u.create->wbr_create) {
14912+ case AuWbrCreate_MFSV:
14913+ case AuWbrCreate_PMFSV:
14914+ AuDbg("%d sec\n", u.create->mfs_second);
14915+ break;
14916+ case AuWbrCreate_MFSRR:
14917+ AuDbg("%llu watermark\n",
14918+ u.create->mfsrr_watermark);
14919+ break;
14920+ case AuWbrCreate_MFSRRV:
14921+ AuDbg("%llu watermark, %d sec\n",
14922+ u.create->mfsrr_watermark,
14923+ u.create->mfs_second);
14924+ break;
14925+ }
14926+ break;
14927+ case Opt_wbr_copyup:
14928+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
14929+ au_optstr_wbr_copyup(opt->wbr_copyup));
14930+ break;
14931+ default:
14932+ BUG();
14933+ }
14934+ opt++;
14935+ }
14936+#endif
14937+}
14938+
14939+void au_opts_free(struct au_opts *opts)
14940+{
14941+ struct au_opt *opt;
14942+
14943+ opt = opts->opt;
14944+ while (opt->type != Opt_tail) {
14945+ switch (opt->type) {
14946+ case Opt_add:
14947+ case Opt_append:
14948+ case Opt_prepend:
14949+ path_put(&opt->add.path);
14950+ break;
14951+ case Opt_del:
14952+ case Opt_idel:
14953+ path_put(&opt->del.h_path);
14954+ break;
14955+ case Opt_mod:
14956+ case Opt_imod:
14957+ dput(opt->mod.h_root);
14958+ break;
14959+ case Opt_xino:
14960+ fput(opt->xino.file);
14961+ break;
14962+ }
14963+ opt++;
14964+ }
14965+}
14966+
14967+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
14968+ aufs_bindex_t bindex)
14969+{
14970+ int err;
14971+ struct au_opt_add *add = &opt->add;
14972+ char *p;
14973+
14974+ add->bindex = bindex;
14975+ add->perm = AuBrPerm_Last;
14976+ add->pathname = opt_str;
14977+ p = strchr(opt_str, '=');
14978+ if (p) {
14979+ *p++ = 0;
14980+ if (*p)
14981+ add->perm = br_perm_val(p);
14982+ }
14983+
14984+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
14985+ if (!err) {
14986+ if (!p) {
14987+ add->perm = AuBrPerm_RO;
14988+ if (au_test_fs_rr(add->path.dentry->d_sb))
14989+ add->perm = AuBrPerm_RR;
14990+ else if (!bindex && !(sb_flags & MS_RDONLY))
14991+ add->perm = AuBrPerm_RW;
14992+ }
14993+ opt->type = Opt_add;
14994+ goto out;
14995+ }
14996+ AuErr("lookup failed %s (%d)\n", add->pathname, err);
14997+ err = -EINVAL;
14998+
14999+ out:
15000+ return err;
15001+}
15002+
15003+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
15004+{
15005+ int err;
15006+
15007+ del->pathname = args[0].from;
15008+ AuDbg("del path %s\n", del->pathname);
15009+
15010+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
15011+ if (unlikely(err))
15012+ AuErr("lookup failed %s (%d)\n", del->pathname, err);
15013+
15014+ return err;
15015+}
15016+
15017+#if 0 /* reserved for future use */
15018+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
15019+ struct au_opt_del *del, substring_t args[])
15020+{
15021+ int err;
15022+ struct dentry *root;
15023+
15024+ err = -EINVAL;
15025+ root = sb->s_root;
15026+ aufs_read_lock(root, AuLock_FLUSH);
15027+ if (bindex < 0 || au_sbend(sb) < bindex) {
15028+ AuErr("out of bounds, %d\n", bindex);
15029+ goto out;
15030+ }
15031+
15032+ err = 0;
15033+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
15034+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
15035+
15036+ out:
15037+ aufs_read_unlock(root, !AuLock_IR);
15038+ return err;
15039+}
15040+#endif
15041+
15042+static int au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
15043+{
15044+ int err;
15045+ struct path path;
15046+ char *p;
15047+
15048+ err = -EINVAL;
15049+ mod->path = args[0].from;
15050+ p = strchr(mod->path, '=');
15051+ if (unlikely(!p)) {
15052+ AuErr("no permssion %s\n", args[0].from);
15053+ goto out;
15054+ }
15055+
15056+ *p++ = 0;
15057+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
15058+ if (unlikely(err)) {
15059+ AuErr("lookup failed %s (%d)\n", mod->path, err);
15060+ goto out;
15061+ }
15062+
15063+ mod->perm = br_perm_val(p);
15064+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
15065+ mod->h_root = dget(path.dentry);
15066+ path_put(&path);
15067+
15068+ out:
15069+ return err;
15070+}
15071+
15072+#if 0 /* reserved for future use */
15073+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
15074+ struct au_opt_mod *mod, substring_t args[])
15075+{
15076+ int err;
15077+ struct dentry *root;
15078+
15079+ err = -EINVAL;
15080+ root = sb->s_root;
15081+ aufs_read_lock(root, AuLock_FLUSH);
15082+ if (bindex < 0 || au_sbend(sb) < bindex) {
15083+ AuErr("out of bounds, %d\n", bindex);
15084+ goto out;
15085+ }
15086+
15087+ err = 0;
15088+ mod->perm = br_perm_val(args[1].from);
15089+ AuDbg("mod path %s, perm 0x%x, %s\n",
15090+ mod->path, mod->perm, args[1].from);
15091+ mod->h_root = dget(au_h_dptr(root, bindex));
15092+
15093+ out:
15094+ aufs_read_unlock(root, !AuLock_IR);
15095+ return err;
15096+}
15097+#endif
15098+
15099+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
15100+ substring_t args[])
15101+{
15102+ int err;
15103+ struct file *file;
15104+
15105+ file = au_xino_create(sb, args[0].from, /*silent*/0);
15106+ err = PTR_ERR(file);
15107+ if (IS_ERR(file))
15108+ goto out;
15109+
15110+ err = -EINVAL;
15111+ if (unlikely(file->f_dentry->d_sb == sb)) {
15112+ fput(file);
15113+ AuErr("%s must be outside\n", args[0].from);
15114+ goto out;
15115+ }
15116+
15117+ err = 0;
15118+ xino->file = file;
15119+ xino->path = args[0].from;
15120+
15121+ out:
15122+ return err;
15123+}
15124+
15125+static
15126+int au_opts_parse_xino_itrunc_path(struct super_block *sb,
15127+ struct au_opt_xino_itrunc *xino_itrunc,
15128+ substring_t args[])
15129+{
15130+ int err;
15131+ aufs_bindex_t bend, bindex;
15132+ struct path path;
15133+ struct dentry *root;
15134+
15135+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
15136+ if (unlikely(err)) {
15137+ AuErr("lookup failed %s (%d)\n", args[0].from, err);
15138+ goto out;
15139+ }
15140+
15141+ xino_itrunc->bindex = -1;
15142+ root = sb->s_root;
15143+ aufs_read_lock(root, AuLock_FLUSH);
15144+ bend = au_sbend(sb);
15145+ for (bindex = 0; bindex <= bend; bindex++) {
15146+ if (au_h_dptr(root, bindex) == path.dentry) {
15147+ xino_itrunc->bindex = bindex;
15148+ break;
15149+ }
15150+ }
15151+ aufs_read_unlock(root, !AuLock_IR);
15152+ path_put(&path);
15153+
15154+ if (unlikely(xino_itrunc->bindex < 0)) {
15155+ AuErr("no such branch %s\n", args[0].from);
15156+ err = -EINVAL;
15157+ }
15158+
15159+ out:
15160+ return err;
15161+}
15162+
15163+/* called without aufs lock */
15164+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
15165+{
15166+ int err, n, token;
15167+ aufs_bindex_t bindex;
15168+ unsigned char skipped;
15169+ struct dentry *root;
15170+ struct au_opt *opt, *opt_tail;
15171+ char *opt_str;
15172+ /* reduce the stack space */
15173+ union {
15174+ struct au_opt_xino_itrunc *xino_itrunc;
15175+ struct au_opt_wbr_create *create;
15176+ } u;
15177+ struct {
15178+ substring_t args[MAX_OPT_ARGS];
15179+ } *a;
15180+
15181+ err = -ENOMEM;
15182+ a = kmalloc(sizeof(*a), GFP_NOFS);
15183+ if (unlikely(!a))
15184+ goto out;
15185+
15186+ root = sb->s_root;
15187+ err = 0;
15188+ bindex = 0;
15189+ opt = opts->opt;
15190+ opt_tail = opt + opts->max_opt - 1;
15191+ opt->type = Opt_tail;
15192+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
15193+ err = -EINVAL;
15194+ skipped = 0;
15195+ token = match_token(opt_str, options, a->args);
15196+ switch (token) {
15197+ case Opt_br:
15198+ err = 0;
15199+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
15200+ && *opt_str) {
15201+ err = opt_add(opt, opt_str, opts->sb_flags,
15202+ bindex++);
15203+ if (unlikely(!err && ++opt > opt_tail)) {
15204+ err = -E2BIG;
15205+ break;
15206+ }
15207+ opt->type = Opt_tail;
15208+ skipped = 1;
15209+ }
15210+ break;
15211+ case Opt_add:
15212+ if (unlikely(match_int(&a->args[0], &n))) {
15213+ AuErr("bad integer in %s\n", opt_str);
15214+ break;
15215+ }
15216+ bindex = n;
15217+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
15218+ bindex);
15219+ if (!err)
15220+ opt->type = token;
15221+ break;
15222+ case Opt_append:
15223+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
15224+ /*dummy bindex*/1);
15225+ if (!err)
15226+ opt->type = token;
15227+ break;
15228+ case Opt_prepend:
15229+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
15230+ /*bindex*/0);
15231+ if (!err)
15232+ opt->type = token;
15233+ break;
15234+ case Opt_del:
15235+ err = au_opts_parse_del(&opt->del, a->args);
15236+ if (!err)
15237+ opt->type = token;
15238+ break;
15239+#if 0 /* reserved for future use */
15240+ case Opt_idel:
15241+ del->pathname = "(indexed)";
15242+ if (unlikely(match_int(&args[0], &n))) {
15243+ AuErr("bad integer in %s\n", opt_str);
15244+ break;
15245+ }
15246+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
15247+ if (!err)
15248+ opt->type = token;
15249+ break;
15250+#endif
15251+ case Opt_mod:
15252+ err = au_opts_parse_mod(&opt->mod, a->args);
15253+ if (!err)
15254+ opt->type = token;
15255+ break;
15256+#ifdef IMOD /* reserved for future use */
15257+ case Opt_imod:
15258+ u.mod->path = "(indexed)";
15259+ if (unlikely(match_int(&a->args[0], &n))) {
15260+ AuErr("bad integer in %s\n", opt_str);
15261+ break;
15262+ }
15263+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
15264+ if (!err)
15265+ opt->type = token;
15266+ break;
15267+#endif
15268+ case Opt_xino:
15269+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
15270+ if (!err)
15271+ opt->type = token;
15272+ break;
15273+
15274+ case Opt_trunc_xino_path:
15275+ err = au_opts_parse_xino_itrunc_path
15276+ (sb, &opt->xino_itrunc, a->args);
15277+ if (!err)
15278+ opt->type = token;
15279+ break;
15280+
15281+ case Opt_itrunc_xino:
15282+ u.xino_itrunc = &opt->xino_itrunc;
15283+ if (unlikely(match_int(&a->args[0], &n))) {
15284+ AuErr("bad integer in %s\n", opt_str);
15285+ break;
15286+ }
15287+ u.xino_itrunc->bindex = n;
15288+ aufs_read_lock(root, AuLock_FLUSH);
15289+ if (n < 0 || au_sbend(sb) < n) {
15290+ AuErr("out of bounds, %d\n", n);
15291+ aufs_read_unlock(root, !AuLock_IR);
15292+ break;
15293+ }
15294+ aufs_read_unlock(root, !AuLock_IR);
15295+ err = 0;
15296+ opt->type = token;
15297+ break;
15298+
15299+ case Opt_dirwh:
15300+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
15301+ break;
15302+ err = 0;
15303+ opt->type = token;
15304+ break;
15305+
15306+ case Opt_rdcache:
15307+ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
15308+ break;
15309+ err = 0;
15310+ opt->type = token;
15311+ break;
15312+ case Opt_rdblk:
15313+ if (unlikely(match_int(&a->args[0], &n)
15314+ || n <= 0
15315+ || n > KMALLOC_MAX_SIZE)) {
15316+ AuErr("bad integer in %s\n", opt_str);
15317+ break;
15318+ }
15319+ if (unlikely(n < NAME_MAX)) {
15320+ AuErr("rdblk must be larger than %d\n",
15321+ NAME_MAX);
15322+ break;
15323+ }
15324+ opt->rdblk = n;
15325+ err = 0;
15326+ opt->type = token;
15327+ break;
15328+ case Opt_rdhash:
15329+ if (unlikely(match_int(&a->args[0], &n)
15330+ || n <= 0
15331+ || n * sizeof(struct hlist_head)
15332+ > KMALLOC_MAX_SIZE)) {
15333+ AuErr("bad integer in %s\n", opt_str);
15334+ break;
15335+ }
15336+ opt->rdhash = n;
15337+ err = 0;
15338+ opt->type = token;
15339+ break;
15340+
15341+ case Opt_trunc_xino:
15342+ case Opt_notrunc_xino:
15343+ case Opt_noxino:
15344+ case Opt_trunc_xib:
15345+ case Opt_notrunc_xib:
dece6358
AM
15346+ case Opt_shwh:
15347+ case Opt_noshwh:
1facf9fc 15348+ case Opt_plink:
15349+ case Opt_noplink:
15350+ case Opt_list_plink:
15351+ case Opt_diropq_a:
15352+ case Opt_diropq_w:
15353+ case Opt_warn_perm:
15354+ case Opt_nowarn_perm:
15355+ case Opt_refrof:
15356+ case Opt_norefrof:
15357+ case Opt_verbose:
15358+ case Opt_noverbose:
15359+ case Opt_sum:
15360+ case Opt_nosum:
15361+ case Opt_wsum:
dece6358
AM
15362+ case Opt_rdblk_def:
15363+ case Opt_rdhash_def:
1facf9fc 15364+ err = 0;
15365+ opt->type = token;
15366+ break;
15367+
15368+ case Opt_udba:
15369+ opt->udba = udba_val(a->args[0].from);
15370+ if (opt->udba >= 0) {
15371+ err = 0;
15372+ opt->type = token;
15373+ } else
15374+ AuErr("wrong value, %s\n", opt_str);
15375+ break;
15376+
15377+ case Opt_wbr_create:
15378+ u.create = &opt->wbr_create;
15379+ u.create->wbr_create
15380+ = au_wbr_create_val(a->args[0].from, u.create);
15381+ if (u.create->wbr_create >= 0) {
15382+ err = 0;
15383+ opt->type = token;
15384+ } else
15385+ AuErr("wrong value, %s\n", opt_str);
15386+ break;
15387+ case Opt_wbr_copyup:
15388+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
15389+ if (opt->wbr_copyup >= 0) {
15390+ err = 0;
15391+ opt->type = token;
15392+ } else
15393+ AuErr("wrong value, %s\n", opt_str);
15394+ break;
15395+
15396+ case Opt_ignore:
15397+ AuWarn("ignored %s\n", opt_str);
15398+ /*FALLTHROUGH*/
15399+ case Opt_ignore_silent:
15400+ skipped = 1;
15401+ err = 0;
15402+ break;
15403+ case Opt_err:
15404+ AuErr("unknown option %s\n", opt_str);
15405+ break;
15406+ }
15407+
15408+ if (!err && !skipped) {
15409+ if (unlikely(++opt > opt_tail)) {
15410+ err = -E2BIG;
15411+ opt--;
15412+ opt->type = Opt_tail;
15413+ break;
15414+ }
15415+ opt->type = Opt_tail;
15416+ }
15417+ }
15418+
15419+ kfree(a);
15420+ dump_opts(opts);
15421+ if (unlikely(err))
15422+ au_opts_free(opts);
15423+
15424+ out:
15425+ return err;
15426+}
15427+
15428+static int au_opt_wbr_create(struct super_block *sb,
15429+ struct au_opt_wbr_create *create)
15430+{
15431+ int err;
15432+ struct au_sbinfo *sbinfo;
15433+
dece6358
AM
15434+ SiMustWriteLock(sb);
15435+
1facf9fc 15436+ err = 1; /* handled */
15437+ sbinfo = au_sbi(sb);
15438+ if (sbinfo->si_wbr_create_ops->fin) {
15439+ err = sbinfo->si_wbr_create_ops->fin(sb);
15440+ if (!err)
15441+ err = 1;
15442+ }
15443+
15444+ sbinfo->si_wbr_create = create->wbr_create;
15445+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
15446+ switch (create->wbr_create) {
15447+ case AuWbrCreate_MFSRRV:
15448+ case AuWbrCreate_MFSRR:
15449+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
15450+ /*FALLTHROUGH*/
15451+ case AuWbrCreate_MFS:
15452+ case AuWbrCreate_MFSV:
15453+ case AuWbrCreate_PMFS:
15454+ case AuWbrCreate_PMFSV:
15455+ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
15456+ break;
15457+ }
15458+
15459+ if (sbinfo->si_wbr_create_ops->init)
15460+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
15461+
15462+ return err;
15463+}
15464+
15465+/*
15466+ * returns,
15467+ * plus: processed without an error
15468+ * zero: unprocessed
15469+ */
15470+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
15471+ struct au_opts *opts)
15472+{
15473+ int err;
15474+ struct au_sbinfo *sbinfo;
15475+
dece6358
AM
15476+ SiMustWriteLock(sb);
15477+
1facf9fc 15478+ err = 1; /* handled */
15479+ sbinfo = au_sbi(sb);
15480+ switch (opt->type) {
15481+ case Opt_udba:
15482+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
15483+ sbinfo->si_mntflags |= opt->udba;
15484+ opts->given_udba |= opt->udba;
15485+ break;
15486+
15487+ case Opt_plink:
15488+ au_opt_set(sbinfo->si_mntflags, PLINK);
15489+ break;
15490+ case Opt_noplink:
15491+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
15492+ au_plink_put(sb);
15493+ au_opt_clr(sbinfo->si_mntflags, PLINK);
15494+ break;
15495+ case Opt_list_plink:
15496+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
15497+ au_plink_list(sb);
15498+ break;
15499+
15500+ case Opt_diropq_a:
15501+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
15502+ break;
15503+ case Opt_diropq_w:
15504+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
15505+ break;
15506+
15507+ case Opt_warn_perm:
15508+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
15509+ break;
15510+ case Opt_nowarn_perm:
15511+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
15512+ break;
15513+
15514+ case Opt_refrof:
15515+ au_opt_set(sbinfo->si_mntflags, REFROF);
15516+ break;
15517+ case Opt_norefrof:
15518+ au_opt_clr(sbinfo->si_mntflags, REFROF);
15519+ break;
15520+
15521+ case Opt_verbose:
15522+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
15523+ break;
15524+ case Opt_noverbose:
15525+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
15526+ break;
15527+
15528+ case Opt_sum:
15529+ au_opt_set(sbinfo->si_mntflags, SUM);
15530+ break;
15531+ case Opt_wsum:
15532+ au_opt_clr(sbinfo->si_mntflags, SUM);
15533+ au_opt_set(sbinfo->si_mntflags, SUM_W);
15534+ case Opt_nosum:
15535+ au_opt_clr(sbinfo->si_mntflags, SUM);
15536+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
15537+ break;
15538+
15539+ case Opt_wbr_create:
15540+ err = au_opt_wbr_create(sb, &opt->wbr_create);
15541+ break;
15542+ case Opt_wbr_copyup:
15543+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
15544+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
15545+ break;
15546+
15547+ case Opt_dirwh:
15548+ sbinfo->si_dirwh = opt->dirwh;
15549+ break;
15550+
15551+ case Opt_rdcache:
15552+ sbinfo->si_rdcache = opt->rdcache * HZ;
15553+ break;
15554+ case Opt_rdblk:
15555+ sbinfo->si_rdblk = opt->rdblk;
15556+ break;
dece6358
AM
15557+ case Opt_rdblk_def:
15558+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
15559+ break;
1facf9fc 15560+ case Opt_rdhash:
15561+ sbinfo->si_rdhash = opt->rdhash;
15562+ break;
dece6358
AM
15563+ case Opt_rdhash_def:
15564+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
15565+ break;
15566+
15567+ case Opt_shwh:
15568+ au_opt_set(sbinfo->si_mntflags, SHWH);
15569+ break;
15570+ case Opt_noshwh:
15571+ au_opt_clr(sbinfo->si_mntflags, SHWH);
15572+ break;
1facf9fc 15573+
15574+ case Opt_trunc_xino:
15575+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
15576+ break;
15577+ case Opt_notrunc_xino:
15578+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
15579+ break;
15580+
15581+ case Opt_trunc_xino_path:
15582+ case Opt_itrunc_xino:
15583+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
15584+ if (!err)
15585+ err = 1;
15586+ break;
15587+
15588+ case Opt_trunc_xib:
15589+ au_fset_opts(opts->flags, TRUNC_XIB);
15590+ break;
15591+ case Opt_notrunc_xib:
15592+ au_fclr_opts(opts->flags, TRUNC_XIB);
15593+ break;
15594+
15595+ default:
15596+ err = 0;
15597+ break;
15598+ }
15599+
15600+ return err;
15601+}
15602+
15603+/*
15604+ * returns tri-state.
15605+ * plus: processed without an error
15606+ * zero: unprocessed
15607+ * minus: error
15608+ */
15609+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
15610+ struct au_opts *opts)
15611+{
15612+ int err, do_refresh;
15613+
15614+ err = 0;
15615+ switch (opt->type) {
15616+ case Opt_append:
15617+ opt->add.bindex = au_sbend(sb) + 1;
15618+ if (opt->add.bindex < 0)
15619+ opt->add.bindex = 0;
15620+ goto add;
15621+ case Opt_prepend:
15622+ opt->add.bindex = 0;
15623+ add:
15624+ case Opt_add:
15625+ err = au_br_add(sb, &opt->add,
15626+ au_ftest_opts(opts->flags, REMOUNT));
15627+ if (!err) {
15628+ err = 1;
15629+ au_fset_opts(opts->flags, REFRESH_DIR);
15630+ if (au_br_whable(opt->add.perm))
15631+ au_fset_opts(opts->flags, REFRESH_NONDIR);
15632+ }
15633+ break;
15634+
15635+ case Opt_del:
15636+ case Opt_idel:
15637+ err = au_br_del(sb, &opt->del,
15638+ au_ftest_opts(opts->flags, REMOUNT));
15639+ if (!err) {
15640+ err = 1;
15641+ au_fset_opts(opts->flags, TRUNC_XIB);
15642+ au_fset_opts(opts->flags, REFRESH_DIR);
15643+ au_fset_opts(opts->flags, REFRESH_NONDIR);
15644+ }
15645+ break;
15646+
15647+ case Opt_mod:
15648+ case Opt_imod:
15649+ err = au_br_mod(sb, &opt->mod,
15650+ au_ftest_opts(opts->flags, REMOUNT),
15651+ &do_refresh);
15652+ if (!err) {
15653+ err = 1;
15654+ if (do_refresh) {
15655+ au_fset_opts(opts->flags, REFRESH_DIR);
15656+ au_fset_opts(opts->flags, REFRESH_NONDIR);
15657+ }
15658+ }
15659+ break;
15660+ }
15661+
15662+ return err;
15663+}
15664+
15665+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
15666+ struct au_opt_xino **opt_xino,
15667+ struct au_opts *opts)
15668+{
15669+ int err;
15670+ aufs_bindex_t bend, bindex;
15671+ struct dentry *root, *parent, *h_root;
15672+
15673+ err = 0;
15674+ switch (opt->type) {
15675+ case Opt_xino:
15676+ err = au_xino_set(sb, &opt->xino,
15677+ !!au_ftest_opts(opts->flags, REMOUNT));
15678+ if (unlikely(err))
15679+ break;
15680+
15681+ *opt_xino = &opt->xino;
15682+ au_xino_brid_set(sb, -1);
15683+
15684+ /* safe d_parent access */
15685+ parent = opt->xino.file->f_dentry->d_parent;
15686+ root = sb->s_root;
15687+ bend = au_sbend(sb);
15688+ for (bindex = 0; bindex <= bend; bindex++) {
15689+ h_root = au_h_dptr(root, bindex);
15690+ if (h_root == parent) {
15691+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
15692+ break;
15693+ }
15694+ }
15695+ break;
15696+
15697+ case Opt_noxino:
15698+ au_xino_clr(sb);
15699+ au_xino_brid_set(sb, -1);
15700+ *opt_xino = (void *)-1;
15701+ break;
15702+ }
15703+
15704+ return err;
15705+}
15706+
15707+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
15708+ unsigned int pending)
15709+{
15710+ int err;
15711+ aufs_bindex_t bindex, bend;
15712+ unsigned char do_plink, skip, do_free;
15713+ struct au_branch *br;
15714+ struct au_wbr *wbr;
15715+ struct dentry *root;
15716+ struct inode *dir, *h_dir;
15717+ struct au_sbinfo *sbinfo;
15718+ struct au_hinode *hdir;
15719+
dece6358
AM
15720+ SiMustAnyLock(sb);
15721+
1facf9fc 15722+ sbinfo = au_sbi(sb);
15723+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
15724+
dece6358
AM
15725+ if (!(sb_flags & MS_RDONLY)) {
15726+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
15727+ AuWarn("first branch should be rw\n");
15728+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
15729+ AuWarn("shwh should be used with ro\n");
15730+ }
1facf9fc 15731+
15732+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HINOTIFY)
15733+ && !au_opt_test(sbinfo->si_mntflags, XINO))
15734+ AuWarn("udba=inotify requires xino\n");
15735+
15736+ err = 0;
15737+ root = sb->s_root;
15738+ dir = sb->s_root->d_inode;
15739+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
15740+ bend = au_sbend(sb);
15741+ for (bindex = 0; !err && bindex <= bend; bindex++) {
15742+ skip = 0;
15743+ h_dir = au_h_iptr(dir, bindex);
15744+ br = au_sbr(sb, bindex);
15745+ do_free = 0;
15746+
15747+ wbr = br->br_wbr;
15748+ if (wbr)
15749+ wbr_wh_read_lock(wbr);
15750+
15751+ switch (br->br_perm) {
15752+ case AuBrPerm_RO:
15753+ case AuBrPerm_ROWH:
15754+ case AuBrPerm_RR:
15755+ case AuBrPerm_RRWH:
15756+ do_free = !!wbr;
15757+ skip = (!wbr
15758+ || (!wbr->wbr_whbase
15759+ && !wbr->wbr_plink
15760+ && !wbr->wbr_orph));
15761+ break;
15762+
15763+ case AuBrPerm_RWNoLinkWH:
15764+ /* skip = (!br->br_whbase && !br->br_orph); */
15765+ skip = (!wbr || !wbr->wbr_whbase);
15766+ if (skip && wbr) {
15767+ if (do_plink)
15768+ skip = !!wbr->wbr_plink;
15769+ else
15770+ skip = !wbr->wbr_plink;
15771+ }
15772+ break;
15773+
15774+ case AuBrPerm_RW:
15775+ /* skip = (br->br_whbase && br->br_ohph); */
15776+ skip = (wbr && wbr->wbr_whbase);
15777+ if (skip) {
15778+ if (do_plink)
15779+ skip = !!wbr->wbr_plink;
15780+ else
15781+ skip = !wbr->wbr_plink;
15782+ }
15783+ break;
15784+
15785+ default:
15786+ BUG();
15787+ }
15788+ if (wbr)
15789+ wbr_wh_read_unlock(wbr);
15790+
15791+ if (skip)
15792+ continue;
15793+
15794+ hdir = au_hi(dir, bindex);
15795+ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
15796+ if (wbr)
15797+ wbr_wh_write_lock(wbr);
15798+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
15799+ if (wbr)
15800+ wbr_wh_write_unlock(wbr);
15801+ au_hin_imtx_unlock(hdir);
15802+
15803+ if (!err && do_free) {
15804+ kfree(wbr);
15805+ br->br_wbr = NULL;
15806+ }
15807+ }
15808+
15809+ return err;
15810+}
15811+
15812+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
15813+{
15814+ int err;
15815+ unsigned int tmp;
15816+ aufs_bindex_t bend;
15817+ struct au_opt *opt;
15818+ struct au_opt_xino *opt_xino, xino;
15819+ struct au_sbinfo *sbinfo;
15820+
dece6358
AM
15821+ SiMustWriteLock(sb);
15822+
1facf9fc 15823+ err = 0;
15824+ opt_xino = NULL;
15825+ opt = opts->opt;
15826+ while (err >= 0 && opt->type != Opt_tail)
15827+ err = au_opt_simple(sb, opt++, opts);
15828+ if (err > 0)
15829+ err = 0;
15830+ else if (unlikely(err < 0))
15831+ goto out;
15832+
15833+ /* disable xino and udba temporary */
15834+ sbinfo = au_sbi(sb);
15835+ tmp = sbinfo->si_mntflags;
15836+ au_opt_clr(sbinfo->si_mntflags, XINO);
15837+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
15838+
15839+ opt = opts->opt;
15840+ while (err >= 0 && opt->type != Opt_tail)
15841+ err = au_opt_br(sb, opt++, opts);
15842+ if (err > 0)
15843+ err = 0;
15844+ else if (unlikely(err < 0))
15845+ goto out;
15846+
15847+ bend = au_sbend(sb);
15848+ if (unlikely(bend < 0)) {
15849+ err = -EINVAL;
15850+ AuErr("no branches\n");
15851+ goto out;
15852+ }
15853+
15854+ if (au_opt_test(tmp, XINO))
15855+ au_opt_set(sbinfo->si_mntflags, XINO);
15856+ opt = opts->opt;
15857+ while (!err && opt->type != Opt_tail)
15858+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
15859+ if (unlikely(err))
15860+ goto out;
15861+
15862+ err = au_opts_verify(sb, sb->s_flags, tmp);
15863+ if (unlikely(err))
15864+ goto out;
15865+
15866+ /* restore xino */
15867+ if (au_opt_test(tmp, XINO) && !opt_xino) {
15868+ xino.file = au_xino_def(sb);
15869+ err = PTR_ERR(xino.file);
15870+ if (IS_ERR(xino.file))
15871+ goto out;
15872+
15873+ err = au_xino_set(sb, &xino, /*remount*/0);
15874+ fput(xino.file);
15875+ if (unlikely(err))
15876+ goto out;
15877+ }
15878+
15879+ /* restore udba */
15880+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
15881+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
15882+ if (au_opt_test(tmp, UDBA_HINOTIFY)) {
15883+ struct inode *dir = sb->s_root->d_inode;
15884+ au_reset_hinotify(dir,
15885+ au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
15886+ }
15887+
15888+ out:
15889+ return err;
15890+}
15891+
15892+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
15893+{
15894+ int err, rerr;
15895+ struct inode *dir;
15896+ struct au_opt_xino *opt_xino;
15897+ struct au_opt *opt;
15898+ struct au_sbinfo *sbinfo;
15899+
dece6358
AM
15900+ SiMustWriteLock(sb);
15901+
1facf9fc 15902+ dir = sb->s_root->d_inode;
15903+ sbinfo = au_sbi(sb);
15904+ err = 0;
15905+ opt_xino = NULL;
15906+ opt = opts->opt;
15907+ while (err >= 0 && opt->type != Opt_tail) {
15908+ err = au_opt_simple(sb, opt, opts);
15909+ if (!err)
15910+ err = au_opt_br(sb, opt, opts);
15911+ if (!err)
15912+ err = au_opt_xino(sb, opt, &opt_xino, opts);
15913+ opt++;
15914+ }
15915+ if (err > 0)
15916+ err = 0;
15917+ AuTraceErr(err);
15918+ /* go on even err */
15919+
15920+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
15921+ if (unlikely(rerr && !err))
15922+ err = rerr;
15923+
15924+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
15925+ rerr = au_xib_trunc(sb);
15926+ if (unlikely(rerr && !err))
15927+ err = rerr;
15928+ }
15929+
15930+ /* will be handled by the caller */
15931+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
15932+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
15933+ au_fset_opts(opts->flags, REFRESH_DIR);
15934+
15935+ AuDbg("status 0x%x\n", opts->flags);
15936+ return err;
15937+}
15938+
15939+/* ---------------------------------------------------------------------- */
15940+
15941+unsigned int au_opt_udba(struct super_block *sb)
15942+{
15943+ return au_mntflags(sb) & AuOptMask_UDBA;
15944+}
dece6358
AM
15945diff -urN linux-2.6.30.org/fs/aufs/opts.h linux-2.6.30/fs/aufs/opts.h
15946--- linux-2.6.30.org/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
15947+++ linux-2.6.30/fs/aufs/opts.h 2009-07-21 08:54:19.000000000 +0200
15948@@ -0,0 +1,196 @@
1facf9fc 15949+/*
15950+ * Copyright (C) 2005-2009 Junjiro R. Okajima
15951+ *
15952+ * This program, aufs is free software; you can redistribute it and/or modify
15953+ * it under the terms of the GNU General Public License as published by
15954+ * the Free Software Foundation; either version 2 of the License, or
15955+ * (at your option) any later version.
dece6358
AM
15956+ *
15957+ * This program is distributed in the hope that it will be useful,
15958+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15959+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15960+ * GNU General Public License for more details.
15961+ *
15962+ * You should have received a copy of the GNU General Public License
15963+ * along with this program; if not, write to the Free Software
15964+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15965+ */
15966+
15967+/*
15968+ * mount options/flags
15969+ */
15970+
15971+#ifndef __AUFS_OPTS_H__
15972+#define __AUFS_OPTS_H__
15973+
15974+#ifdef __KERNEL__
15975+
dece6358 15976+#include <linux/path.h>
1facf9fc 15977+#include <linux/aufs_type.h>
15978+
dece6358
AM
15979+struct file;
15980+struct super_block;
15981+
1facf9fc 15982+/* ---------------------------------------------------------------------- */
15983+
15984+/* mount flags */
15985+#define AuOpt_XINO 1 /* external inode number bitmap
15986+ and translation table */
15987+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
15988+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
15989+#define AuOpt_UDBA_REVAL (1 << 3)
15990+#define AuOpt_UDBA_HINOTIFY (1 << 4)
dece6358
AM
15991+#define AuOpt_SHWH (1 << 5) /* show whiteout */
15992+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
15993+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
15994+#define AuOpt_REFROF (1 << 8) /* unimplemented */
15995+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
15996+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
15997+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
15998+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
15999+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
1facf9fc 16000+
16001+#ifndef CONFIG_AUFS_HINOTIFY
16002+#undef AuOpt_UDBA_HINOTIFY
16003+#define AuOpt_UDBA_HINOTIFY 0
16004+#endif
dece6358
AM
16005+#ifndef CONFIG_AUFS_SHWH
16006+#undef AuOpt_SHWH
16007+#define AuOpt_SHWH 0
16008+#endif
1facf9fc 16009+
16010+#define AuOpt_Def (AuOpt_XINO \
16011+ | AuOpt_UDBA_REVAL \
16012+ | AuOpt_PLINK \
16013+ /* | AuOpt_DIRPERM1 */ \
16014+ | AuOpt_WARN_PERM)
16015+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
16016+ | AuOpt_UDBA_REVAL \
16017+ | AuOpt_UDBA_HINOTIFY)
16018+
16019+#define au_opt_test(flags, name) (flags & AuOpt_##name)
16020+#define au_opt_set(flags, name) do { \
16021+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
16022+ ((flags) |= AuOpt_##name); \
16023+} while (0)
16024+#define au_opt_set_udba(flags, name) do { \
16025+ (flags) &= ~AuOptMask_UDBA; \
16026+ ((flags) |= AuOpt_##name); \
16027+} while (0)
16028+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
16029+
16030+/* ---------------------------------------------------------------------- */
16031+
16032+/* policies to select one among multiple writable branches */
16033+enum {
16034+ AuWbrCreate_TDP, /* top down parent */
16035+ AuWbrCreate_RR, /* round robin */
16036+ AuWbrCreate_MFS, /* most free space */
16037+ AuWbrCreate_MFSV, /* mfs with seconds */
16038+ AuWbrCreate_MFSRR, /* mfs then rr */
16039+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
16040+ AuWbrCreate_PMFS, /* parent and mfs */
16041+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
16042+
16043+ AuWbrCreate_Def = AuWbrCreate_TDP
16044+};
16045+
16046+enum {
16047+ AuWbrCopyup_TDP, /* top down parent */
16048+ AuWbrCopyup_BUP, /* bottom up parent */
16049+ AuWbrCopyup_BU, /* bottom up */
16050+
16051+ AuWbrCopyup_Def = AuWbrCopyup_TDP
16052+};
16053+
16054+/* ---------------------------------------------------------------------- */
16055+
16056+struct au_opt_add {
16057+ aufs_bindex_t bindex;
16058+ char *pathname;
16059+ int perm;
16060+ struct path path;
16061+};
16062+
16063+struct au_opt_del {
16064+ char *pathname;
16065+ struct path h_path;
16066+};
16067+
16068+struct au_opt_mod {
16069+ char *path;
16070+ int perm;
16071+ struct dentry *h_root;
16072+};
16073+
16074+struct au_opt_xino {
16075+ char *path;
16076+ struct file *file;
16077+};
16078+
16079+struct au_opt_xino_itrunc {
16080+ aufs_bindex_t bindex;
16081+};
16082+
16083+struct au_opt_wbr_create {
16084+ int wbr_create;
16085+ int mfs_second;
16086+ unsigned long long mfsrr_watermark;
16087+};
16088+
16089+struct au_opt {
16090+ int type;
16091+ union {
16092+ struct au_opt_xino xino;
16093+ struct au_opt_xino_itrunc xino_itrunc;
16094+ struct au_opt_add add;
16095+ struct au_opt_del del;
16096+ struct au_opt_mod mod;
16097+ int dirwh;
16098+ int rdcache;
16099+ unsigned int rdblk;
16100+ unsigned int rdhash;
16101+ int udba;
16102+ struct au_opt_wbr_create wbr_create;
16103+ int wbr_copyup;
16104+ };
16105+};
16106+
16107+/* opts flags */
16108+#define AuOpts_REMOUNT 1
16109+#define AuOpts_REFRESH_DIR (1 << 1)
16110+#define AuOpts_REFRESH_NONDIR (1 << 2)
16111+#define AuOpts_TRUNC_XIB (1 << 3)
16112+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
16113+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
16114+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
16115+
16116+struct au_opts {
16117+ struct au_opt *opt;
16118+ int max_opt;
16119+
16120+ unsigned int given_udba;
16121+ unsigned int flags;
16122+ unsigned long sb_flags;
16123+};
16124+
16125+/* ---------------------------------------------------------------------- */
16126+
16127+const char *au_optstr_br_perm(int brperm);
16128+const char *au_optstr_udba(int udba);
16129+const char *au_optstr_wbr_copyup(int wbr_copyup);
16130+const char *au_optstr_wbr_create(int wbr_create);
16131+
16132+void au_opts_free(struct au_opts *opts);
16133+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
16134+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
16135+ unsigned int pending);
16136+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
16137+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
16138+
16139+unsigned int au_opt_udba(struct super_block *sb);
16140+
16141+/* ---------------------------------------------------------------------- */
16142+
16143+#endif /* __KERNEL__ */
16144+#endif /* __AUFS_OPTS_H__ */
dece6358
AM
16145diff -urN linux-2.6.30.org/fs/aufs/plink.c linux-2.6.30/fs/aufs/plink.c
16146--- linux-2.6.30.org/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
16147+++ linux-2.6.30/fs/aufs/plink.c 2009-07-21 08:54:19.000000000 +0200
16148@@ -0,0 +1,354 @@
1facf9fc 16149+/*
16150+ * Copyright (C) 2005-2009 Junjiro R. Okajima
16151+ *
16152+ * This program, aufs is free software; you can redistribute it and/or modify
16153+ * it under the terms of the GNU General Public License as published by
16154+ * the Free Software Foundation; either version 2 of the License, or
16155+ * (at your option) any later version.
dece6358
AM
16156+ *
16157+ * This program is distributed in the hope that it will be useful,
16158+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16159+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16160+ * GNU General Public License for more details.
16161+ *
16162+ * You should have received a copy of the GNU General Public License
16163+ * along with this program; if not, write to the Free Software
16164+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16165+ */
16166+
16167+/*
16168+ * pseudo-link
16169+ */
16170+
16171+#include "aufs.h"
16172+
16173+/*
16174+ * during a user process maintains the pseudo-links,
16175+ * prohibit adding a new plink and branch manipulation.
16176+ */
16177+void au_plink_block_maintain(struct super_block *sb)
16178+{
16179+ struct au_sbinfo *sbi = au_sbi(sb);
dece6358
AM
16180+
16181+ SiMustAnyLock(sb);
16182+
1facf9fc 16183+ /* gave up wake_up_bit() */
16184+ wait_event(sbi->si_plink_wq, !au_ftest_si(sbi, MAINTAIN_PLINK));
16185+}
16186+
16187+/* ---------------------------------------------------------------------- */
16188+
16189+struct pseudo_link {
16190+ struct list_head list;
16191+ struct inode *inode;
16192+};
16193+
16194+#ifdef CONFIG_AUFS_DEBUG
16195+void au_plink_list(struct super_block *sb)
16196+{
16197+ struct au_sbinfo *sbinfo;
16198+ struct list_head *plink_list;
16199+ struct pseudo_link *plink;
16200+
dece6358
AM
16201+ SiMustAnyLock(sb);
16202+
1facf9fc 16203+ sbinfo = au_sbi(sb);
16204+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
16205+
16206+ plink_list = &sbinfo->si_plink.head;
16207+ spin_lock(&sbinfo->si_plink.spin);
16208+ list_for_each_entry(plink, plink_list, list)
16209+ AuDbg("%lu\n", plink->inode->i_ino);
16210+ spin_unlock(&sbinfo->si_plink.spin);
16211+}
16212+#endif
16213+
16214+/* is the inode pseudo-linked? */
16215+int au_plink_test(struct inode *inode)
16216+{
16217+ int found;
16218+ struct au_sbinfo *sbinfo;
16219+ struct list_head *plink_list;
16220+ struct pseudo_link *plink;
16221+
16222+ sbinfo = au_sbi(inode->i_sb);
dece6358 16223+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 16224+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
16225+
16226+ found = 0;
16227+ plink_list = &sbinfo->si_plink.head;
16228+ spin_lock(&sbinfo->si_plink.spin);
16229+ list_for_each_entry(plink, plink_list, list)
16230+ if (plink->inode == inode) {
16231+ found = 1;
16232+ break;
16233+ }
16234+ spin_unlock(&sbinfo->si_plink.spin);
16235+ return found;
16236+}
16237+
16238+/* ---------------------------------------------------------------------- */
16239+
16240+/*
16241+ * generate a name for plink.
16242+ * the file will be stored under AUFS_WH_PLINKDIR.
16243+ */
16244+/* 20 is max digits length of ulong 64 */
16245+#define PLINK_NAME_LEN ((20 + 1) * 2)
16246+
16247+static int plink_name(char *name, int len, struct inode *inode,
16248+ aufs_bindex_t bindex)
16249+{
16250+ int rlen;
16251+ struct inode *h_inode;
16252+
16253+ h_inode = au_h_iptr(inode, bindex);
16254+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
16255+ return rlen;
16256+}
16257+
16258+/* lookup the plink-ed @inode under the branch at @bindex */
16259+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
16260+{
16261+ struct dentry *h_dentry, *h_parent;
16262+ struct au_branch *br;
16263+ struct inode *h_dir;
16264+ char a[PLINK_NAME_LEN];
16265+ struct qstr tgtname = {
16266+ .name = a
16267+ };
16268+
16269+ br = au_sbr(inode->i_sb, bindex);
16270+ h_parent = br->br_wbr->wbr_plink;
16271+ h_dir = h_parent->d_inode;
16272+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
16273+
16274+ /* always superio. */
16275+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
16276+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
16277+ mutex_unlock(&h_dir->i_mutex);
16278+ return h_dentry;
16279+}
16280+
16281+/* create a pseudo-link */
16282+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
16283+ struct dentry *h_dentry, struct au_branch *br)
16284+{
16285+ int err;
16286+ struct path h_path = {
16287+ .mnt = br->br_mnt
16288+ };
16289+ struct inode *h_dir;
16290+
16291+ h_dir = h_parent->d_inode;
16292+ again:
16293+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
16294+ err = PTR_ERR(h_path.dentry);
16295+ if (IS_ERR(h_path.dentry))
16296+ goto out;
16297+
16298+ err = 0;
16299+ /* wh.plink dir is not monitored */
16300+ if (h_path.dentry->d_inode
16301+ && h_path.dentry->d_inode != h_dentry->d_inode) {
16302+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
16303+ dput(h_path.dentry);
16304+ h_path.dentry = NULL;
16305+ if (!err)
16306+ goto again;
16307+ }
16308+ if (!err && !h_path.dentry->d_inode)
16309+ err = vfsub_link(h_dentry, h_dir, &h_path);
16310+ dput(h_path.dentry);
16311+
16312+ out:
16313+ return err;
16314+}
16315+
16316+struct do_whplink_args {
16317+ int *errp;
16318+ struct qstr *tgt;
16319+ struct dentry *h_parent;
16320+ struct dentry *h_dentry;
16321+ struct au_branch *br;
16322+};
16323+
16324+static void call_do_whplink(void *args)
16325+{
16326+ struct do_whplink_args *a = args;
16327+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
16328+}
16329+
16330+static int whplink(struct dentry *h_dentry, struct inode *inode,
16331+ aufs_bindex_t bindex, struct au_branch *br)
16332+{
16333+ int err, wkq_err;
16334+ struct au_wbr *wbr;
16335+ struct dentry *h_parent;
16336+ struct inode *h_dir;
16337+ char a[PLINK_NAME_LEN];
16338+ struct qstr tgtname = {
16339+ .name = a
16340+ };
16341+
16342+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
16343+ h_parent = wbr->wbr_plink;
16344+ h_dir = h_parent->d_inode;
16345+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
16346+
16347+ /* always superio. */
16348+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
16349+ if (!au_test_wkq(current)) {
16350+ struct do_whplink_args args = {
16351+ .errp = &err,
16352+ .tgt = &tgtname,
16353+ .h_parent = h_parent,
16354+ .h_dentry = h_dentry,
16355+ .br = br
16356+ };
16357+ wkq_err = au_wkq_wait(call_do_whplink, &args);
16358+ if (unlikely(wkq_err))
16359+ err = wkq_err;
16360+ } else
16361+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
16362+ mutex_unlock(&h_dir->i_mutex);
16363+
16364+ return err;
16365+}
16366+
16367+/* free a single plink */
16368+static void do_put_plink(struct pseudo_link *plink, int do_del)
16369+{
16370+ iput(plink->inode);
16371+ if (do_del)
16372+ list_del(&plink->list);
16373+ kfree(plink);
16374+}
16375+
16376+/*
16377+ * create a new pseudo-link for @h_dentry on @bindex.
16378+ * the linked inode is held in aufs @inode.
16379+ */
16380+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
16381+ struct dentry *h_dentry)
16382+{
16383+ struct super_block *sb;
16384+ struct au_sbinfo *sbinfo;
16385+ struct list_head *plink_list;
16386+ struct pseudo_link *plink;
16387+ int found, err, cnt;
16388+
16389+ sb = inode->i_sb;
16390+ sbinfo = au_sbi(sb);
16391+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
16392+
16393+ err = 0;
16394+ cnt = 0;
16395+ found = 0;
16396+ plink_list = &sbinfo->si_plink.head;
16397+ spin_lock(&sbinfo->si_plink.spin);
16398+ list_for_each_entry(plink, plink_list, list) {
16399+ cnt++;
16400+ if (plink->inode == inode) {
16401+ found = 1;
16402+ break;
16403+ }
16404+ }
16405+ if (found) {
16406+ spin_unlock(&sbinfo->si_plink.spin);
16407+ return;
16408+ }
16409+
16410+ plink = NULL;
16411+ if (!found) {
16412+ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
16413+ if (plink) {
16414+ plink->inode = au_igrab(inode);
16415+ list_add(&plink->list, plink_list);
16416+ cnt++;
16417+ } else
16418+ err = -ENOMEM;
16419+ }
16420+ spin_unlock(&sbinfo->si_plink.spin);
16421+
16422+ if (!err) {
16423+ au_plink_block_maintain(sb);
16424+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
16425+ }
16426+
16427+ if (unlikely(cnt > AUFS_PLINK_WARN))
16428+ AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
16429+ if (unlikely(err)) {
16430+ AuWarn("err %d, damaged pseudo link.\n", err);
16431+ if (!found && plink)
16432+ do_put_plink(plink, /*do_del*/1);
16433+ }
16434+}
16435+
16436+/* free all plinks */
16437+void au_plink_put(struct super_block *sb)
16438+{
16439+ struct au_sbinfo *sbinfo;
16440+ struct list_head *plink_list;
16441+ struct pseudo_link *plink, *tmp;
16442+
dece6358
AM
16443+ SiMustWriteLock(sb);
16444+
1facf9fc 16445+ sbinfo = au_sbi(sb);
16446+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
16447+
16448+ plink_list = &sbinfo->si_plink.head;
16449+ /* no spin_lock since sbinfo is write-locked */
16450+ list_for_each_entry_safe(plink, tmp, plink_list, list)
16451+ do_put_plink(plink, 0);
16452+ INIT_LIST_HEAD(plink_list);
16453+}
16454+
16455+/* free the plinks on a branch specified by @br_id */
16456+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
16457+{
16458+ struct au_sbinfo *sbinfo;
16459+ struct list_head *plink_list;
16460+ struct pseudo_link *plink, *tmp;
16461+ struct inode *inode;
16462+ aufs_bindex_t bstart, bend, bindex;
16463+ unsigned char do_put;
16464+
dece6358
AM
16465+ SiMustWriteLock(sb);
16466+
1facf9fc 16467+ sbinfo = au_sbi(sb);
16468+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
16469+
16470+ plink_list = &sbinfo->si_plink.head;
16471+ /* no spin_lock since sbinfo is write-locked */
16472+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
16473+ do_put = 0;
16474+ inode = au_igrab(plink->inode);
16475+ ii_write_lock_child(inode);
16476+ bstart = au_ibstart(inode);
16477+ bend = au_ibend(inode);
16478+ if (bstart >= 0) {
16479+ for (bindex = bstart; bindex <= bend; bindex++) {
16480+ if (!au_h_iptr(inode, bindex)
16481+ || au_ii_br_id(inode, bindex) != br_id)
16482+ continue;
16483+ au_set_h_iptr(inode, bindex, NULL, 0);
16484+ do_put = 1;
16485+ break;
16486+ }
16487+ } else
16488+ do_put_plink(plink, 1);
16489+
dece6358
AM
16490+ if (do_put) {
16491+ for (bindex = bstart; bindex <= bend; bindex++)
16492+ if (au_h_iptr(inode, bindex)) {
16493+ do_put = 0;
16494+ break;
16495+ }
16496+ if (do_put)
16497+ do_put_plink(plink, 1);
16498+ }
16499+ ii_write_unlock(inode);
16500+ iput(inode);
16501+ }
16502+}
16503diff -urN linux-2.6.30.org/fs/aufs/poll.c linux-2.6.30/fs/aufs/poll.c
16504--- linux-2.6.30.org/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
16505+++ linux-2.6.30/fs/aufs/poll.c 2009-07-21 08:54:19.000000000 +0200
16506@@ -0,0 +1,56 @@
16507+/*
16508+ * Copyright (C) 2005-2009 Junjiro R. Okajima
16509+ *
16510+ * This program, aufs is free software; you can redistribute it and/or modify
16511+ * it under the terms of the GNU General Public License as published by
16512+ * the Free Software Foundation; either version 2 of the License, or
16513+ * (at your option) any later version.
16514+ *
16515+ * This program is distributed in the hope that it will be useful,
16516+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16517+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16518+ * GNU General Public License for more details.
16519+ *
16520+ * You should have received a copy of the GNU General Public License
16521+ * along with this program; if not, write to the Free Software
16522+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16523+ */
16524+
16525+/*
16526+ * poll operation
16527+ * There is only one filesystem which implements ->poll operation, currently.
16528+ */
16529+
16530+#include "aufs.h"
16531+
16532+unsigned int aufs_poll(struct file *file, poll_table *wait)
16533+{
16534+ unsigned int mask;
16535+ int err;
16536+ struct file *h_file;
16537+ struct dentry *dentry;
16538+ struct super_block *sb;
16539+
16540+ /* We should pretend an error happened. */
16541+ mask = POLLERR /* | POLLIN | POLLOUT */;
16542+ dentry = file->f_dentry;
16543+ sb = dentry->d_sb;
16544+ si_read_lock(sb, AuLock_FLUSH);
16545+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
16546+ if (unlikely(err))
16547+ goto out;
16548+
16549+ /* it is not an error if h_file has no operation */
16550+ mask = DEFAULT_POLLMASK;
16551+ h_file = au_h_fptr(file, au_fbstart(file));
16552+ if (h_file->f_op && h_file->f_op->poll)
16553+ mask = h_file->f_op->poll(h_file, wait);
16554+
16555+ di_read_unlock(dentry, AuLock_IR);
16556+ fi_read_unlock(file);
16557+
16558+ out:
16559+ si_read_unlock(sb);
16560+ AuTraceErr((int)mask);
16561+ return mask;
1facf9fc 16562+}
dece6358
AM
16563diff -urN linux-2.6.30.org/fs/aufs/rwsem.h linux-2.6.30/fs/aufs/rwsem.h
16564--- linux-2.6.30.org/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
16565+++ linux-2.6.30/fs/aufs/rwsem.h 2009-07-21 08:54:19.000000000 +0200
16566@@ -0,0 +1,186 @@
1facf9fc 16567+/*
16568+ * Copyright (C) 2005-2009 Junjiro R. Okajima
16569+ *
16570+ * This program, aufs is free software; you can redistribute it and/or modify
16571+ * it under the terms of the GNU General Public License as published by
16572+ * the Free Software Foundation; either version 2 of the License, or
16573+ * (at your option) any later version.
dece6358
AM
16574+ *
16575+ * This program is distributed in the hope that it will be useful,
16576+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16577+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16578+ * GNU General Public License for more details.
16579+ *
16580+ * You should have received a copy of the GNU General Public License
16581+ * along with this program; if not, write to the Free Software
16582+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16583+ */
16584+
16585+/*
16586+ * simple read-write semaphore wrappers
16587+ */
16588+
16589+#ifndef __AUFS_RWSEM_H__
16590+#define __AUFS_RWSEM_H__
16591+
16592+#ifdef __KERNEL__
16593+
dece6358
AM
16594+#include <linux/rwsem.h>
16595+
16596+struct au_rwsem {
16597+ struct rw_semaphore rwsem;
16598+#ifdef CONFIG_AUFS_DEBUG
16599+ /* just for debugging, not almighty counter */
16600+ atomic_t rcnt, wcnt;
16601+#endif
16602+};
16603+
16604+#ifdef CONFIG_AUFS_DEBUG
16605+#define AuDbgCntInit(rw) do { \
16606+ atomic_set(&(rw)->rcnt, 0); \
16607+ atomic_set(&(rw)->wcnt, 0); \
16608+ smp_mb(); /* atomic set */ \
16609+} while (0)
16610+
16611+#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt)
16612+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
16613+#define AuDbgWcntInc(rw) WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
16614+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
16615+#else
16616+#define AuDbgCntInit(rw) do {} while (0)
16617+#define AuDbgRcntInc(rw) do {} while (0)
16618+#define AuDbgRcntDec(rw) do {} while (0)
16619+#define AuDbgWcntInc(rw) do {} while (0)
16620+#define AuDbgWcntDec(rw) do {} while (0)
16621+#endif /* CONFIG_AUFS_DEBUG */
16622+
16623+/* to debug easier, do not make them inlined functions */
16624+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
16625+/* rwsem_is_locked() is unusable */
16626+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
16627+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
16628+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
16629+ && atomic_read(&(rw)->wcnt) <= 0)
16630+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
16631+ || atomic_read(&(rw)->wcnt))
16632+
16633+static inline void au_rw_init(struct au_rwsem *rw)
16634+{
16635+ AuDbgCntInit(rw);
16636+ init_rwsem(&rw->rwsem);
16637+}
16638+
16639+static inline void au_rw_init_wlock(struct au_rwsem *rw)
16640+{
16641+ au_rw_init(rw);
16642+ down_write(&rw->rwsem);
16643+ AuDbgWcntInc(rw);
16644+}
16645+
16646+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
16647+ unsigned int lsc)
16648+{
16649+ au_rw_init(rw);
16650+ down_write_nested(&rw->rwsem, lsc);
16651+ AuDbgWcntInc(rw);
16652+}
16653+
16654+static inline void au_rw_read_lock(struct au_rwsem *rw)
16655+{
16656+ down_read(&rw->rwsem);
16657+ AuDbgRcntInc(rw);
16658+}
16659+
16660+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
16661+{
16662+ down_read_nested(&rw->rwsem, lsc);
16663+ AuDbgRcntInc(rw);
16664+}
16665+
16666+static inline void au_rw_read_unlock(struct au_rwsem *rw)
16667+{
16668+ AuRwMustReadLock(rw);
16669+ AuDbgRcntDec(rw);
16670+ up_read(&rw->rwsem);
16671+}
16672+
16673+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
16674+{
16675+ AuRwMustWriteLock(rw);
16676+ AuDbgRcntInc(rw);
16677+ AuDbgWcntDec(rw);
16678+ downgrade_write(&rw->rwsem);
16679+}
16680+
16681+static inline void au_rw_write_lock(struct au_rwsem *rw)
16682+{
16683+ down_write(&rw->rwsem);
16684+ AuDbgWcntInc(rw);
16685+}
16686+
16687+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
16688+ unsigned int lsc)
16689+{
16690+ down_write_nested(&rw->rwsem, lsc);
16691+ AuDbgWcntInc(rw);
16692+}
1facf9fc 16693+
dece6358
AM
16694+static inline void au_rw_write_unlock(struct au_rwsem *rw)
16695+{
16696+ AuRwMustWriteLock(rw);
16697+ AuDbgWcntDec(rw);
16698+ up_write(&rw->rwsem);
16699+}
16700+
16701+/* why is not _nested version defined */
16702+static inline int au_rw_read_trylock(struct au_rwsem *rw)
16703+{
16704+ int ret = down_read_trylock(&rw->rwsem);
16705+ if (ret)
16706+ AuDbgRcntInc(rw);
16707+ return ret;
16708+}
16709+
16710+static inline int au_rw_write_trylock(struct au_rwsem *rw)
16711+{
16712+ int ret = down_write_trylock(&rw->rwsem);
16713+ if (ret)
16714+ AuDbgWcntInc(rw);
16715+ return ret;
16716+}
16717+
16718+#undef AuDbgCntInit
16719+#undef AuDbgRcntInc
16720+#undef AuDbgRcntDec
16721+#undef AuDbgWcntInc
16722+#undef AuDbgWcntDec
1facf9fc 16723+
16724+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
16725+static inline void prefix##_read_lock(param) \
dece6358 16726+{ au_rw_read_lock(rwsem); } \
1facf9fc 16727+static inline void prefix##_write_lock(param) \
dece6358 16728+{ au_rw_write_lock(rwsem); } \
1facf9fc 16729+static inline int prefix##_read_trylock(param) \
dece6358 16730+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 16731+static inline int prefix##_write_trylock(param) \
dece6358 16732+{ return au_rw_write_trylock(rwsem); }
1facf9fc 16733+/* why is not _nested version defined */
16734+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 16735+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 16736+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 16737+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 16738+
16739+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
16740+static inline void prefix##_read_unlock(param) \
dece6358 16741+{ au_rw_read_unlock(rwsem); } \
1facf9fc 16742+static inline void prefix##_write_unlock(param) \
dece6358 16743+{ au_rw_write_unlock(rwsem); } \
1facf9fc 16744+static inline void prefix##_downgrade_lock(param) \
dece6358 16745+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 16746+
16747+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
16748+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
16749+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
16750+
16751+#endif /* __KERNEL__ */
16752+#endif /* __AUFS_RWSEM_H__ */
dece6358
AM
16753diff -urN linux-2.6.30.org/fs/aufs/sbinfo.c linux-2.6.30/fs/aufs/sbinfo.c
16754--- linux-2.6.30.org/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
16755+++ linux-2.6.30/fs/aufs/sbinfo.c 2009-07-21 08:54:19.000000000 +0200
16756@@ -0,0 +1,208 @@
1facf9fc 16757+/*
16758+ * Copyright (C) 2005-2009 Junjiro R. Okajima
16759+ *
16760+ * This program, aufs is free software; you can redistribute it and/or modify
16761+ * it under the terms of the GNU General Public License as published by
16762+ * the Free Software Foundation; either version 2 of the License, or
16763+ * (at your option) any later version.
dece6358
AM
16764+ *
16765+ * This program is distributed in the hope that it will be useful,
16766+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16767+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16768+ * GNU General Public License for more details.
16769+ *
16770+ * You should have received a copy of the GNU General Public License
16771+ * along with this program; if not, write to the Free Software
16772+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16773+ */
16774+
16775+/*
16776+ * superblock private data
16777+ */
16778+
16779+#include "aufs.h"
16780+
16781+/*
16782+ * they are necessary regardless sysfs is disabled.
16783+ */
16784+void au_si_free(struct kobject *kobj)
16785+{
16786+ struct au_sbinfo *sbinfo;
16787+ struct super_block *sb;
16788+
16789+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
16790+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
16791+
16792+ sb = sbinfo->si_sb;
16793+ si_write_lock(sb);
16794+ au_xino_clr(sb);
16795+ au_br_free(sbinfo);
16796+ kfree(sbinfo->si_branch);
16797+ mutex_destroy(&sbinfo->si_xib_mtx);
16798+ si_write_unlock(sb);
dece6358 16799+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 16800+
16801+ kfree(sbinfo);
16802+}
16803+
16804+int au_si_alloc(struct super_block *sb)
16805+{
16806+ int err;
16807+ struct au_sbinfo *sbinfo;
16808+
16809+ err = -ENOMEM;
16810+ sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
16811+ if (unlikely(!sbinfo))
16812+ goto out;
16813+
16814+ /* will be reallocated separately */
16815+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
16816+ if (unlikely(!sbinfo->si_branch))
16817+ goto out_sbinfo;
16818+
16819+ memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
16820+ err = sysaufs_si_init(sbinfo);
16821+ if (unlikely(err))
16822+ goto out_br;
16823+
16824+ au_nwt_init(&sbinfo->si_nowait);
dece6358 16825+ au_rw_init_wlock(&sbinfo->si_rwsem);
1facf9fc 16826+ sbinfo->si_generation = 0;
16827+ sbinfo->au_si_status = 0;
16828+ sbinfo->si_bend = -1;
16829+ sbinfo->si_last_br_id = 0;
16830+
16831+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
16832+ sbinfo->si_wbr_create = AuWbrCreate_Def;
16833+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
16834+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
16835+
16836+ sbinfo->si_mntflags = AuOpt_Def;
16837+
16838+ sbinfo->si_xread = NULL;
16839+ sbinfo->si_xwrite = NULL;
16840+ sbinfo->si_xib = NULL;
16841+ mutex_init(&sbinfo->si_xib_mtx);
16842+ sbinfo->si_xib_buf = NULL;
16843+ sbinfo->si_xino_brid = -1;
16844+ /* leave si_xib_last_pindex and si_xib_next_bit */
16845+
16846+ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
16847+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
16848+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
16849+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
16850+
16851+ au_spl_init(&sbinfo->si_plink);
16852+ init_waitqueue_head(&sbinfo->si_plink_wq);
16853+
16854+ /* leave other members for sysaufs and si_mnt. */
16855+ sbinfo->si_sb = sb;
16856+ sb->s_fs_info = sbinfo;
16857+ au_debug_sbinfo_init(sbinfo);
16858+ return 0; /* success */
16859+
16860+ out_br:
16861+ kfree(sbinfo->si_branch);
16862+ out_sbinfo:
16863+ kfree(sbinfo);
16864+ out:
16865+ return err;
16866+}
16867+
16868+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
16869+{
16870+ int err, sz;
16871+ struct au_branch **brp;
16872+
dece6358
AM
16873+ AuRwMustWriteLock(&sbinfo->si_rwsem);
16874+
1facf9fc 16875+ err = -ENOMEM;
16876+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
16877+ if (unlikely(!sz))
16878+ sz = sizeof(*brp);
16879+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
16880+ if (brp) {
16881+ sbinfo->si_branch = brp;
16882+ err = 0;
16883+ }
16884+
16885+ return err;
16886+}
16887+
16888+/* ---------------------------------------------------------------------- */
16889+
16890+unsigned int au_sigen_inc(struct super_block *sb)
16891+{
16892+ unsigned int gen;
16893+
dece6358
AM
16894+ SiMustWriteLock(sb);
16895+
1facf9fc 16896+ gen = ++au_sbi(sb)->si_generation;
16897+ au_update_digen(sb->s_root);
16898+ au_update_iigen(sb->s_root->d_inode);
16899+ sb->s_root->d_inode->i_version++;
16900+ return gen;
16901+}
16902+
16903+aufs_bindex_t au_new_br_id(struct super_block *sb)
16904+{
16905+ aufs_bindex_t br_id;
16906+ int i;
16907+ struct au_sbinfo *sbinfo;
16908+
dece6358
AM
16909+ SiMustWriteLock(sb);
16910+
1facf9fc 16911+ sbinfo = au_sbi(sb);
16912+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
16913+ br_id = ++sbinfo->si_last_br_id;
16914+ if (br_id && au_br_index(sb, br_id) < 0)
16915+ return br_id;
16916+ }
16917+
16918+ return -1;
16919+}
16920+
16921+/* ---------------------------------------------------------------------- */
16922+
16923+/* dentry and super_block lock. call at entry point */
16924+void aufs_read_lock(struct dentry *dentry, int flags)
16925+{
16926+ si_read_lock(dentry->d_sb, flags);
16927+ if (au_ftest_lock(flags, DW))
16928+ di_write_lock_child(dentry);
16929+ else
16930+ di_read_lock_child(dentry, flags);
16931+}
16932+
16933+void aufs_read_unlock(struct dentry *dentry, int flags)
16934+{
16935+ if (au_ftest_lock(flags, DW))
16936+ di_write_unlock(dentry);
16937+ else
16938+ di_read_unlock(dentry, flags);
16939+ si_read_unlock(dentry->d_sb);
16940+}
16941+
16942+void aufs_write_lock(struct dentry *dentry)
16943+{
16944+ si_write_lock(dentry->d_sb);
16945+ di_write_lock_child(dentry);
16946+}
16947+
16948+void aufs_write_unlock(struct dentry *dentry)
16949+{
16950+ di_write_unlock(dentry);
16951+ si_write_unlock(dentry->d_sb);
16952+}
16953+
16954+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
16955+{
16956+ si_read_lock(d1->d_sb, flags);
16957+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
16958+}
16959+
16960+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
16961+{
16962+ di_write_unlock2(d1, d2);
16963+ si_read_unlock(d1->d_sb);
16964+}
dece6358
AM
16965diff -urN linux-2.6.30.org/fs/aufs/spl.h linux-2.6.30/fs/aufs/spl.h
16966--- linux-2.6.30.org/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
16967+++ linux-2.6.30/fs/aufs/spl.h 2009-07-21 08:54:19.000000000 +0200
16968@@ -0,0 +1,57 @@
1facf9fc 16969+/*
16970+ * Copyright (C) 2005-2009 Junjiro R. Okajima
16971+ *
16972+ * This program, aufs is free software; you can redistribute it and/or modify
16973+ * it under the terms of the GNU General Public License as published by
16974+ * the Free Software Foundation; either version 2 of the License, or
16975+ * (at your option) any later version.
dece6358
AM
16976+ *
16977+ * This program is distributed in the hope that it will be useful,
16978+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16979+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16980+ * GNU General Public License for more details.
16981+ *
16982+ * You should have received a copy of the GNU General Public License
16983+ * along with this program; if not, write to the Free Software
16984+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16985+ */
16986+
16987+/*
16988+ * simple list protected by a spinlock
16989+ */
16990+
16991+#ifndef __AUFS_SPL_H__
16992+#define __AUFS_SPL_H__
16993+
16994+#ifdef __KERNEL__
16995+
dece6358
AM
16996+#include <linux/spinlock.h>
16997+#include <linux/list.h>
1facf9fc 16998+
16999+struct au_splhead {
17000+ spinlock_t spin;
17001+ struct list_head head;
17002+};
17003+
17004+static inline void au_spl_init(struct au_splhead *spl)
17005+{
17006+ spin_lock_init(&spl->spin);
17007+ INIT_LIST_HEAD(&spl->head);
17008+}
17009+
17010+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
17011+{
17012+ spin_lock(&spl->spin);
17013+ list_add(list, &spl->head);
17014+ spin_unlock(&spl->spin);
17015+}
17016+
17017+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
17018+{
17019+ spin_lock(&spl->spin);
17020+ list_del(list);
17021+ spin_unlock(&spl->spin);
17022+}
17023+
17024+#endif /* __KERNEL__ */
17025+#endif /* __AUFS_SPL_H__ */
dece6358
AM
17026diff -urN linux-2.6.30.org/fs/aufs/super.c linux-2.6.30/fs/aufs/super.c
17027--- linux-2.6.30.org/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
17028+++ linux-2.6.30/fs/aufs/super.c 2009-07-21 08:54:19.000000000 +0200
17029@@ -0,0 +1,874 @@
1facf9fc 17030+/*
17031+ * Copyright (C) 2005-2009 Junjiro R. Okajima
17032+ *
17033+ * This program, aufs is free software; you can redistribute it and/or modify
17034+ * it under the terms of the GNU General Public License as published by
17035+ * the Free Software Foundation; either version 2 of the License, or
17036+ * (at your option) any later version.
dece6358
AM
17037+ *
17038+ * This program is distributed in the hope that it will be useful,
17039+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17040+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17041+ * GNU General Public License for more details.
17042+ *
17043+ * You should have received a copy of the GNU General Public License
17044+ * along with this program; if not, write to the Free Software
17045+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17046+ */
17047+
17048+/*
17049+ * mount and super_block operations
17050+ */
17051+
17052+#include <linux/buffer_head.h>
dece6358 17053+#include <linux/module.h>
1facf9fc 17054+#include <linux/seq_file.h>
17055+#include <linux/statfs.h>
17056+#include "aufs.h"
17057+
17058+/*
17059+ * super_operations
17060+ */
17061+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
17062+{
17063+ struct au_icntnr *c;
17064+
17065+ c = au_cache_alloc_icntnr();
17066+ if (c) {
17067+ inode_init_once(&c->vfs_inode);
17068+ c->vfs_inode.i_version = 1; /* sigen(sb); */
17069+ c->iinfo.ii_hinode = NULL;
17070+ return &c->vfs_inode;
17071+ }
17072+ return NULL;
17073+}
17074+
17075+static void aufs_destroy_inode(struct inode *inode)
17076+{
17077+ au_iinfo_fin(inode);
17078+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
17079+}
17080+
17081+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
17082+{
17083+ struct inode *inode;
17084+ int err;
17085+
17086+ inode = iget_locked(sb, ino);
17087+ if (unlikely(!inode)) {
17088+ inode = ERR_PTR(-ENOMEM);
17089+ goto out;
17090+ }
17091+ if (!(inode->i_state & I_NEW))
17092+ goto out;
17093+
17094+ err = au_xigen_new(inode);
17095+ if (!err)
17096+ err = au_iinfo_init(inode);
17097+ if (!err)
17098+ inode->i_version++;
17099+ else {
17100+ iget_failed(inode);
17101+ inode = ERR_PTR(err);
17102+ }
17103+
17104+ out:
17105+ /* never return NULL */
17106+ AuDebugOn(!inode);
17107+ AuTraceErrPtr(inode);
17108+ return inode;
17109+}
17110+
17111+/* lock free root dinfo */
17112+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
17113+{
17114+ int err;
17115+ aufs_bindex_t bindex, bend;
17116+ struct path path;
17117+ struct au_hdentry *hd;
17118+ struct au_branch *br;
17119+
17120+ err = 0;
17121+ bend = au_sbend(sb);
17122+ hd = au_di(sb->s_root)->di_hdentry;
17123+ for (bindex = 0; !err && bindex <= bend; bindex++) {
17124+ br = au_sbr(sb, bindex);
17125+ path.mnt = br->br_mnt;
17126+ path.dentry = hd[bindex].hd_dentry;
17127+ err = au_seq_path(seq, &path);
17128+ if (err > 0)
17129+ err = seq_printf(seq, "=%s",
17130+ au_optstr_br_perm(br->br_perm));
17131+ if (!err && bindex != bend)
17132+ err = seq_putc(seq, ':');
17133+ }
17134+
17135+ return err;
17136+}
17137+
17138+static void au_show_wbr_create(struct seq_file *m, int v,
17139+ struct au_sbinfo *sbinfo)
17140+{
17141+ const char *pat;
17142+
dece6358
AM
17143+ AuRwMustAnyLock(&sbinfo->si_rwsem);
17144+
1facf9fc 17145+ seq_printf(m, ",create=");
17146+ pat = au_optstr_wbr_create(v);
17147+ switch (v) {
17148+ case AuWbrCreate_TDP:
17149+ case AuWbrCreate_RR:
17150+ case AuWbrCreate_MFS:
17151+ case AuWbrCreate_PMFS:
17152+ seq_printf(m, pat);
17153+ break;
17154+ case AuWbrCreate_MFSV:
17155+ seq_printf(m, /*pat*/"mfs:%lu",
17156+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
17157+ break;
17158+ case AuWbrCreate_PMFSV:
17159+ seq_printf(m, /*pat*/"pmfs:%lu",
17160+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
17161+ break;
17162+ case AuWbrCreate_MFSRR:
17163+ seq_printf(m, /*pat*/"mfsrr:%llu",
17164+ sbinfo->si_wbr_mfs.mfsrr_watermark);
17165+ break;
17166+ case AuWbrCreate_MFSRRV:
17167+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
17168+ sbinfo->si_wbr_mfs.mfsrr_watermark,
17169+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
17170+ break;
17171+ }
17172+}
17173+
17174+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
17175+{
17176+#ifdef CONFIG_SYSFS
17177+ return 0;
17178+#else
17179+ int err;
17180+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
17181+ aufs_bindex_t bindex, brid;
17182+ struct super_block *sb;
17183+ struct qstr *name;
17184+ struct file *f;
17185+ struct dentry *d, *h_root;
17186+
dece6358
AM
17187+ AuRwMustAnyLock(&sbinfo->si_rwsem);
17188+
1facf9fc 17189+ err = 0;
17190+ sb = mnt->mnt_sb;
17191+ f = au_sbi(sb)->si_xib;
17192+ if (!f)
17193+ goto out;
17194+
17195+ /* stop printing the default xino path on the first writable branch */
17196+ h_root = NULL;
17197+ brid = au_xino_brid(sb);
17198+ if (brid >= 0) {
17199+ bindex = au_br_index(sb, brid);
17200+ h_root = au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
17201+ }
17202+ d = f->f_dentry;
17203+ name = &d->d_name;
17204+ /* safe ->d_parent because the file is unlinked */
17205+ if (d->d_parent == h_root
17206+ && name->len == len
17207+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
17208+ goto out;
17209+
17210+ seq_puts(seq, ",xino=");
17211+ err = au_xino_path(seq, f);
17212+
17213+ out:
17214+ return err;
17215+#endif
17216+}
17217+
17218+/* seq_file will re-call me in case of too long string */
17219+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
17220+{
17221+ int err, n;
17222+ unsigned int mnt_flags, v;
17223+ struct super_block *sb;
17224+ struct au_sbinfo *sbinfo;
17225+
17226+#define AuBool(name, str) do { \
17227+ v = au_opt_test(mnt_flags, name); \
17228+ if (v != au_opt_test(AuOpt_Def, name)) \
17229+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
17230+} while (0)
17231+
17232+#define AuStr(name, str) do { \
17233+ v = mnt_flags & AuOptMask_##name; \
17234+ if (v != (AuOpt_Def & AuOptMask_##name)) \
17235+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
17236+} while (0)
17237+
17238+#define AuUInt(name, str, val) do { \
17239+ if (val != AUFS_##name##_DEF) \
17240+ seq_printf(m, "," #str "=%u", val); \
17241+} while (0)
17242+
17243+ /* lock free root dinfo */
17244+ sb = mnt->mnt_sb;
17245+ si_noflush_read_lock(sb);
17246+ sbinfo = au_sbi(sb);
17247+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
17248+
17249+ mnt_flags = au_mntflags(sb);
17250+ if (au_opt_test(mnt_flags, XINO)) {
17251+ err = au_show_xino(m, mnt);
17252+ if (unlikely(err))
17253+ goto out;
17254+ } else
17255+ seq_puts(m, ",noxino");
17256+
17257+ AuBool(TRUNC_XINO, trunc_xino);
17258+ AuStr(UDBA, udba);
dece6358 17259+ AuBool(SHWH, shwh);
1facf9fc 17260+ AuBool(PLINK, plink);
17261+ /* AuBool(DIRPERM1, dirperm1); */
17262+ /* AuBool(REFROF, refrof); */
17263+
17264+ v = sbinfo->si_wbr_create;
17265+ if (v != AuWbrCreate_Def)
17266+ au_show_wbr_create(m, v, sbinfo);
17267+
17268+ v = sbinfo->si_wbr_copyup;
17269+ if (v != AuWbrCopyup_Def)
17270+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
17271+
17272+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
17273+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
17274+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
17275+
17276+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
17277+
17278+ n = sbinfo->si_rdcache / HZ;
17279+ AuUInt(RDCACHE, rdcache, n);
17280+
17281+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
17282+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
17283+
17284+ AuBool(SUM, sum);
17285+ /* AuBool(SUM_W, wsum); */
17286+ AuBool(WARN_PERM, warn_perm);
17287+ AuBool(VERBOSE, verbose);
17288+
17289+ out:
17290+ /* be sure to print "br:" last */
17291+ if (!sysaufs_brs) {
17292+ seq_puts(m, ",br:");
17293+ au_show_brs(m, sb);
17294+ }
17295+ si_read_unlock(sb);
17296+ return 0;
17297+
17298+#undef Deleted
17299+#undef AuBool
17300+#undef AuStr
17301+}
17302+
17303+/* ---------------------------------------------------------------------- */
17304+
17305+/* sum mode which returns the summation for statfs(2) */
17306+
17307+static u64 au_add_till_max(u64 a, u64 b)
17308+{
17309+ u64 old;
17310+
17311+ old = a;
17312+ a += b;
17313+ if (old < a)
17314+ return a;
17315+ return ULLONG_MAX;
17316+}
17317+
17318+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
17319+{
17320+ int err;
17321+ u64 blocks, bfree, bavail, files, ffree;
17322+ aufs_bindex_t bend, bindex, i;
17323+ unsigned char shared;
17324+ struct vfsmount *h_mnt;
17325+ struct super_block *h_sb;
17326+
17327+ blocks = 0;
17328+ bfree = 0;
17329+ bavail = 0;
17330+ files = 0;
17331+ ffree = 0;
17332+
17333+ err = 0;
17334+ bend = au_sbend(sb);
17335+ for (bindex = bend; bindex >= 0; bindex--) {
17336+ h_mnt = au_sbr_mnt(sb, bindex);
17337+ h_sb = h_mnt->mnt_sb;
17338+ shared = 0;
17339+ for (i = bindex + 1; !shared && i <= bend; i++)
17340+ shared = (au_sbr_sb(sb, i) == h_sb);
17341+ if (shared)
17342+ continue;
17343+
17344+ /* sb->s_root for NFS is unreliable */
17345+ err = vfs_statfs(h_mnt->mnt_root, buf);
17346+ if (unlikely(err))
17347+ goto out;
17348+
17349+ blocks = au_add_till_max(blocks, buf->f_blocks);
17350+ bfree = au_add_till_max(bfree, buf->f_bfree);
17351+ bavail = au_add_till_max(bavail, buf->f_bavail);
17352+ files = au_add_till_max(files, buf->f_files);
17353+ ffree = au_add_till_max(ffree, buf->f_ffree);
17354+ }
17355+
17356+ buf->f_blocks = blocks;
17357+ buf->f_bfree = bfree;
17358+ buf->f_bavail = bavail;
17359+ buf->f_files = files;
17360+ buf->f_ffree = ffree;
17361+
17362+ out:
17363+ return err;
17364+}
17365+
17366+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
17367+{
17368+ int err;
17369+ struct super_block *sb;
17370+
17371+ /* lock free root dinfo */
17372+ sb = dentry->d_sb;
17373+ si_noflush_read_lock(sb);
17374+ if (!au_opt_test(au_mntflags(sb), SUM))
17375+ /* sb->s_root for NFS is unreliable */
17376+ err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
17377+ else
17378+ err = au_statfs_sum(sb, buf);
17379+ si_read_unlock(sb);
17380+
17381+ if (!err) {
17382+ buf->f_type = AUFS_SUPER_MAGIC;
17383+ buf->f_namelen -= AUFS_WH_PFX_LEN;
17384+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
17385+ }
17386+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
17387+
17388+ return err;
17389+}
17390+
17391+/* ---------------------------------------------------------------------- */
17392+
17393+/* try flushing the lower fs at aufs remount/unmount time */
17394+
17395+static void au_fsync_br(struct super_block *sb)
17396+{
17397+ aufs_bindex_t bend, bindex;
17398+ int brperm;
17399+ struct au_branch *br;
17400+ struct super_block *h_sb;
17401+
17402+ bend = au_sbend(sb);
17403+ for (bindex = 0; bindex < bend; bindex++) {
17404+ br = au_sbr(sb, bindex);
17405+ brperm = br->br_perm;
17406+ if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
17407+ continue;
17408+ h_sb = br->br_mnt->mnt_sb;
17409+ if (bdev_read_only(h_sb->s_bdev))
17410+ continue;
17411+
17412+ lockdep_off();
17413+ down_write(&h_sb->s_umount);
17414+ shrink_dcache_sb(h_sb);
17415+ fsync_super(h_sb);
17416+ up_write(&h_sb->s_umount);
17417+ lockdep_on();
17418+ }
17419+}
17420+
17421+/*
17422+ * this IS NOT for super_operations.
17423+ * I guess it will be reverted someday.
17424+ */
17425+static void aufs_umount_begin(struct super_block *sb)
17426+{
17427+ struct au_sbinfo *sbinfo;
17428+
17429+ sbinfo = au_sbi(sb);
17430+ if (!sbinfo)
17431+ return;
17432+
17433+ si_write_lock(sb);
17434+ au_fsync_br(sb);
17435+ if (au_opt_test(au_mntflags(sb), PLINK))
17436+ au_plink_put(sb);
17437+ if (sbinfo->si_wbr_create_ops->fin)
17438+ sbinfo->si_wbr_create_ops->fin(sb);
17439+ si_write_unlock(sb);
17440+}
17441+
17442+/* final actions when unmounting a file system */
17443+static void aufs_put_super(struct super_block *sb)
17444+{
17445+ struct au_sbinfo *sbinfo;
17446+
17447+ sbinfo = au_sbi(sb);
17448+ if (!sbinfo)
17449+ return;
17450+
17451+ aufs_umount_begin(sb);
17452+ dbgaufs_si_fin(sbinfo);
17453+ kobject_put(&sbinfo->si_kobj);
17454+}
17455+
17456+/* ---------------------------------------------------------------------- */
17457+
17458+/*
17459+ * refresh dentry and inode at remount time.
17460+ */
17461+static int do_refresh(struct dentry *dentry, mode_t type,
17462+ unsigned int dir_flags)
17463+{
17464+ int err;
17465+ struct dentry *parent;
17466+
17467+ di_write_lock_child(dentry);
17468+ parent = dget_parent(dentry);
17469+ di_read_lock_parent(parent, AuLock_IR);
17470+
17471+ /* returns the number of positive dentries */
17472+ err = au_refresh_hdentry(dentry, type);
17473+ if (err >= 0) {
17474+ struct inode *inode = dentry->d_inode;
17475+ err = au_refresh_hinode(inode, dentry);
17476+ if (!err && type == S_IFDIR)
17477+ au_reset_hinotify(inode, dir_flags);
17478+ }
17479+ if (unlikely(err))
17480+ AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
17481+
17482+ di_read_unlock(parent, AuLock_IR);
17483+ dput(parent);
17484+ di_write_unlock(dentry);
17485+
17486+ return err;
17487+}
17488+
17489+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
17490+{
17491+ return S_ISDIR(dentry->d_inode->i_mode);
17492+}
17493+
17494+/* gave up consolidating with refresh_nondir() */
17495+static int refresh_dir(struct dentry *root, unsigned int sigen)
17496+{
17497+ int err, i, j, ndentry, e;
17498+ struct au_dcsub_pages dpages;
17499+ struct au_dpage *dpage;
17500+ struct dentry **dentries;
17501+ struct inode *inode;
17502+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
17503+
17504+ err = 0;
17505+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
17506+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
17507+ ii_write_lock_child(inode);
17508+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
17509+ ii_write_unlock(inode);
17510+ if (unlikely(e)) {
17511+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
17512+ if (!err)
17513+ err = e;
17514+ /* go on even if err */
17515+ }
17516+ }
17517+
17518+ e = au_dpages_init(&dpages, GFP_NOFS);
17519+ if (unlikely(e)) {
17520+ if (!err)
17521+ err = e;
17522+ goto out;
17523+ }
17524+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
17525+ if (unlikely(e)) {
17526+ if (!err)
17527+ err = e;
17528+ goto out_dpages;
17529+ }
17530+
17531+ for (i = 0; !e && i < dpages.ndpage; i++) {
17532+ dpage = dpages.dpages + i;
17533+ dentries = dpage->dentries;
17534+ ndentry = dpage->ndentry;
17535+ for (j = 0; !e && j < ndentry; j++) {
17536+ struct dentry *d;
17537+
17538+ d = dentries[j];
17539+ au_dbg_verify_dir_parent(d, sigen);
17540+ if (au_digen(d) != sigen) {
17541+ e = do_refresh(d, S_IFDIR, flags);
17542+ if (unlikely(e && !err))
17543+ err = e;
17544+ /* break on err */
17545+ }
17546+ }
17547+ }
17548+
17549+ out_dpages:
17550+ au_dpages_free(&dpages);
17551+ out:
17552+ return err;
17553+}
17554+
17555+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
17556+{
17557+ return !S_ISDIR(dentry->d_inode->i_mode);
17558+}
17559+
17560+static int refresh_nondir(struct dentry *root, unsigned int sigen,
17561+ int do_dentry)
17562+{
17563+ int err, i, j, ndentry, e;
17564+ struct au_dcsub_pages dpages;
17565+ struct au_dpage *dpage;
17566+ struct dentry **dentries;
17567+ struct inode *inode;
17568+
17569+ err = 0;
17570+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
17571+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
17572+ ii_write_lock_child(inode);
17573+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
17574+ ii_write_unlock(inode);
17575+ if (unlikely(e)) {
17576+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
17577+ if (!err)
17578+ err = e;
17579+ /* go on even if err */
17580+ }
17581+ }
17582+
17583+ if (!do_dentry)
17584+ goto out;
17585+
17586+ e = au_dpages_init(&dpages, GFP_NOFS);
17587+ if (unlikely(e)) {
17588+ if (!err)
17589+ err = e;
17590+ goto out;
17591+ }
17592+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
17593+ if (unlikely(e)) {
17594+ if (!err)
17595+ err = e;
17596+ goto out_dpages;
17597+ }
17598+
17599+ for (i = 0; i < dpages.ndpage; i++) {
17600+ dpage = dpages.dpages + i;
17601+ dentries = dpage->dentries;
17602+ ndentry = dpage->ndentry;
17603+ for (j = 0; j < ndentry; j++) {
17604+ struct dentry *d;
17605+
17606+ d = dentries[j];
17607+ au_dbg_verify_nondir_parent(d, sigen);
17608+ inode = d->d_inode;
17609+ if (inode && au_digen(d) != sigen) {
17610+ e = do_refresh(d, inode->i_mode & S_IFMT,
17611+ /*dir_flags*/0);
17612+ if (unlikely(e && !err))
17613+ err = e;
17614+ /* go on even err */
17615+ }
17616+ }
17617+ }
17618+
17619+ out_dpages:
17620+ au_dpages_free(&dpages);
17621+ out:
17622+ return err;
17623+}
17624+
17625+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
17626+{
17627+ int err;
17628+ unsigned int sigen;
17629+ struct au_sbinfo *sbinfo;
17630+ struct dentry *root;
17631+ struct inode *inode;
17632+
17633+ au_sigen_inc(sb);
17634+ sigen = au_sigen(sb);
17635+ sbinfo = au_sbi(sb);
17636+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
17637+
17638+ root = sb->s_root;
17639+ DiMustNoWaiters(root);
17640+ inode = root->d_inode;
17641+ IiMustNoWaiters(inode);
17642+ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
17643+ di_write_unlock(root);
17644+
17645+ err = refresh_dir(root, sigen);
17646+ if (unlikely(err)) {
17647+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
17648+ AuWarn("Refreshing directories failed, ignored (%d)\n", err);
17649+ }
17650+
17651+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
17652+ err = refresh_nondir(root, sigen, !err);
17653+ if (unlikely(err))
17654+ AuWarn("Refreshing non-directories failed, ignored"
17655+ "(%d)\n", err);
17656+ }
17657+
17658+ /* aufs_write_lock() calls ..._child() */
17659+ di_write_lock_child(root);
17660+ au_cpup_attr_all(root->d_inode, /*force*/1);
17661+}
17662+
17663+/* stop extra interpretation of errno in mount(8), and strange error messages */
17664+static int cvt_err(int err)
17665+{
17666+ AuTraceErr(err);
17667+
17668+ switch (err) {
17669+ case -ENOENT:
17670+ case -ENOTDIR:
17671+ case -EEXIST:
17672+ case -EIO:
17673+ err = -EINVAL;
17674+ }
17675+ return err;
17676+}
17677+
17678+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
17679+{
17680+ int err;
17681+ struct au_opts opts;
17682+ struct dentry *root;
17683+ struct inode *inode;
17684+ struct au_sbinfo *sbinfo;
17685+
17686+ err = 0;
17687+ root = sb->s_root;
17688+ if (!data || !*data) {
17689+ aufs_write_lock(root);
17690+ err = au_opts_verify(sb, *flags, /*pending*/0);
17691+ if (!err)
17692+ au_fsync_br(sb);
17693+ aufs_write_unlock(root);
17694+ goto out;
17695+ }
17696+
17697+ err = -ENOMEM;
17698+ memset(&opts, 0, sizeof(opts));
17699+ opts.opt = (void *)__get_free_page(GFP_NOFS);
17700+ if (unlikely(!opts.opt))
17701+ goto out;
17702+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
17703+ opts.flags = AuOpts_REMOUNT;
17704+ opts.sb_flags = *flags;
17705+
17706+ /* parse it before aufs lock */
17707+ err = au_opts_parse(sb, data, &opts);
17708+ if (unlikely(err))
17709+ goto out_opts;
17710+
17711+ sbinfo = au_sbi(sb);
17712+ inode = root->d_inode;
17713+ mutex_lock(&inode->i_mutex);
17714+ aufs_write_lock(root);
17715+ au_fsync_br(sb);
17716+
17717+ /* au_opts_remount() may return an error */
17718+ err = au_opts_remount(sb, &opts);
17719+ au_opts_free(&opts);
17720+
17721+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
17722+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
17723+ au_remount_refresh(sb, opts.flags);
17724+
17725+ aufs_write_unlock(root);
17726+ mutex_unlock(&inode->i_mutex);
17727+
17728+ out_opts:
17729+ free_page((unsigned long)opts.opt);
17730+ out:
17731+ err = cvt_err(err);
17732+ AuTraceErr(err);
17733+ return err;
17734+}
17735+
17736+static struct super_operations aufs_sop = {
17737+ .alloc_inode = aufs_alloc_inode,
17738+ .destroy_inode = aufs_destroy_inode,
17739+ .drop_inode = generic_delete_inode,
17740+ .show_options = aufs_show_options,
17741+ .statfs = aufs_statfs,
17742+ .put_super = aufs_put_super,
17743+ .remount_fs = aufs_remount_fs
17744+};
17745+
17746+/* ---------------------------------------------------------------------- */
17747+
17748+static int alloc_root(struct super_block *sb)
17749+{
17750+ int err;
17751+ struct inode *inode;
17752+ struct dentry *root;
17753+
17754+ err = -ENOMEM;
17755+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
17756+ err = PTR_ERR(inode);
17757+ if (IS_ERR(inode))
17758+ goto out;
17759+
17760+ inode->i_op = &aufs_dir_iop;
17761+ inode->i_fop = &aufs_dir_fop;
17762+ inode->i_mode = S_IFDIR;
17763+ inode->i_nlink = 2;
17764+ unlock_new_inode(inode);
17765+
17766+ root = d_alloc_root(inode);
17767+ if (unlikely(!root))
17768+ goto out_iput;
17769+ err = PTR_ERR(root);
17770+ if (IS_ERR(root))
17771+ goto out_iput;
17772+
17773+ err = au_alloc_dinfo(root);
17774+ if (!err) {
17775+ sb->s_root = root;
17776+ return 0; /* success */
17777+ }
17778+ dput(root);
17779+ goto out; /* do not iput */
17780+
17781+ out_iput:
17782+ iget_failed(inode);
17783+ iput(inode);
17784+ out:
17785+ return err;
17786+
17787+}
17788+
17789+static int aufs_fill_super(struct super_block *sb, void *raw_data,
17790+ int silent __maybe_unused)
17791+{
17792+ int err;
17793+ struct au_opts opts;
17794+ struct dentry *root;
17795+ struct inode *inode;
17796+ char *arg = raw_data;
17797+
17798+ if (unlikely(!arg || !*arg)) {
17799+ err = -EINVAL;
17800+ AuErr("no arg\n");
17801+ goto out;
17802+ }
17803+
17804+ err = -ENOMEM;
17805+ memset(&opts, 0, sizeof(opts));
17806+ opts.opt = (void *)__get_free_page(GFP_NOFS);
17807+ if (unlikely(!opts.opt))
17808+ goto out;
17809+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
17810+ opts.sb_flags = sb->s_flags;
17811+
17812+ err = au_si_alloc(sb);
17813+ if (unlikely(err))
17814+ goto out_opts;
17815+
17816+ /* all timestamps always follow the ones on the branch */
17817+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
17818+ sb->s_op = &aufs_sop;
17819+ sb->s_magic = AUFS_SUPER_MAGIC;
17820+ sb->s_maxbytes = 0;
17821+ au_export_init(sb);
17822+
17823+ err = alloc_root(sb);
17824+ if (unlikely(err)) {
17825+ si_write_unlock(sb);
17826+ goto out_info;
17827+ }
17828+ root = sb->s_root;
17829+ inode = root->d_inode;
17830+
17831+ /*
17832+ * actually we can parse options regardless aufs lock here.
17833+ * but at remount time, parsing must be done before aufs lock.
17834+ * so we follow the same rule.
17835+ */
17836+ ii_write_lock_parent(inode);
17837+ aufs_write_unlock(root);
17838+ err = au_opts_parse(sb, arg, &opts);
17839+ if (unlikely(err))
17840+ goto out_root;
17841+
17842+ /* lock vfs_inode first, then aufs. */
17843+ mutex_lock(&inode->i_mutex);
17844+ inode->i_op = &aufs_dir_iop;
17845+ inode->i_fop = &aufs_dir_fop;
17846+ aufs_write_lock(root);
17847+ err = au_opts_mount(sb, &opts);
17848+ au_opts_free(&opts);
17849+ if (unlikely(err))
17850+ goto out_unlock;
17851+ aufs_write_unlock(root);
17852+ mutex_unlock(&inode->i_mutex);
17853+ goto out_opts; /* success */
17854+
17855+ out_unlock:
17856+ aufs_write_unlock(root);
17857+ mutex_unlock(&inode->i_mutex);
17858+ out_root:
17859+ dput(root);
17860+ sb->s_root = NULL;
17861+ out_info:
17862+ kobject_put(&au_sbi(sb)->si_kobj);
17863+ sb->s_fs_info = NULL;
17864+ out_opts:
17865+ free_page((unsigned long)opts.opt);
17866+ out:
17867+ AuTraceErr(err);
17868+ err = cvt_err(err);
17869+ AuTraceErr(err);
17870+ return err;
17871+}
17872+
17873+/* ---------------------------------------------------------------------- */
17874+
17875+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
17876+ const char *dev_name __maybe_unused, void *raw_data,
17877+ struct vfsmount *mnt)
17878+{
17879+ int err;
17880+ struct super_block *sb;
17881+
17882+ /* all timestamps always follow the ones on the branch */
17883+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
17884+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
17885+ if (!err) {
17886+ sb = mnt->mnt_sb;
17887+ si_write_lock(sb);
17888+ sysaufs_brs_add(sb, 0);
17889+ si_write_unlock(sb);
17890+ }
17891+ return err;
17892+}
17893+
17894+struct file_system_type aufs_fs_type = {
17895+ .name = AUFS_FSTYPE,
17896+ .fs_flags =
17897+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
17898+ | FS_REVAL_DOT, /* for NFS branch and udba */
17899+ .get_sb = aufs_get_sb,
17900+ .kill_sb = generic_shutdown_super,
17901+ /* no need to __module_get() and module_put(). */
17902+ .owner = THIS_MODULE,
17903+};
dece6358
AM
17904diff -urN linux-2.6.30.org/fs/aufs/super.h linux-2.6.30/fs/aufs/super.h
17905--- linux-2.6.30.org/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
17906+++ linux-2.6.30/fs/aufs/super.h 2009-07-21 08:54:19.000000000 +0200
17907@@ -0,0 +1,384 @@
1facf9fc 17908+/*
17909+ * Copyright (C) 2005-2009 Junjiro R. Okajima
17910+ *
17911+ * This program, aufs is free software; you can redistribute it and/or modify
17912+ * it under the terms of the GNU General Public License as published by
17913+ * the Free Software Foundation; either version 2 of the License, or
17914+ * (at your option) any later version.
dece6358
AM
17915+ *
17916+ * This program is distributed in the hope that it will be useful,
17917+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17918+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17919+ * GNU General Public License for more details.
17920+ *
17921+ * You should have received a copy of the GNU General Public License
17922+ * along with this program; if not, write to the Free Software
17923+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17924+ */
17925+
17926+/*
17927+ * super_block operations
17928+ */
17929+
17930+#ifndef __AUFS_SUPER_H__
17931+#define __AUFS_SUPER_H__
17932+
17933+#ifdef __KERNEL__
17934+
17935+#include <linux/fs.h>
1facf9fc 17936+#include <linux/aufs_type.h>
17937+#include "rwsem.h"
17938+#include "spl.h"
17939+#include "wkq.h"
17940+
17941+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
17942+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
17943+ loff_t *);
17944+
17945+/* policies to select one among multiple writable branches */
17946+struct au_wbr_copyup_operations {
17947+ int (*copyup)(struct dentry *dentry);
17948+};
17949+
17950+struct au_wbr_create_operations {
17951+ int (*create)(struct dentry *dentry, int isdir);
17952+ int (*init)(struct super_block *sb);
17953+ int (*fin)(struct super_block *sb);
17954+};
17955+
17956+struct au_wbr_mfs {
17957+ struct mutex mfs_lock; /* protect this structure */
17958+ unsigned long mfs_jiffy;
17959+ unsigned long mfs_expire;
17960+ aufs_bindex_t mfs_bindex;
17961+
17962+ unsigned long long mfsrr_bytes;
17963+ unsigned long long mfsrr_watermark;
17964+};
17965+
1facf9fc 17966+struct au_branch;
17967+struct au_sbinfo {
17968+ /* nowait tasks in the system-wide workqueue */
17969+ struct au_nowait_tasks si_nowait;
17970+
dece6358 17971+ struct au_rwsem si_rwsem;
1facf9fc 17972+
17973+ /* branch management */
17974+ unsigned int si_generation;
17975+
17976+ /* see above flags */
17977+ unsigned char au_si_status;
17978+
17979+ aufs_bindex_t si_bend;
17980+ aufs_bindex_t si_last_br_id;
17981+ struct au_branch **si_branch;
17982+
17983+ /* policy to select a writable branch */
17984+ unsigned char si_wbr_copyup;
17985+ unsigned char si_wbr_create;
17986+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
17987+ struct au_wbr_create_operations *si_wbr_create_ops;
17988+
17989+ /* round robin */
17990+ atomic_t si_wbr_rr_next;
17991+
17992+ /* most free space */
17993+ struct au_wbr_mfs si_wbr_mfs;
17994+
17995+ /* mount flags */
17996+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
17997+ unsigned int si_mntflags;
17998+
17999+ /* external inode number (bitmap and translation table) */
18000+ au_readf_t si_xread;
18001+ au_writef_t si_xwrite;
18002+ struct file *si_xib;
18003+ struct mutex si_xib_mtx; /* protect xib members */
18004+ unsigned long *si_xib_buf;
18005+ unsigned long si_xib_last_pindex;
18006+ int si_xib_next_bit;
18007+ aufs_bindex_t si_xino_brid;
18008+ /* reserved for future use */
18009+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
18010+
18011+#ifdef CONFIG_AUFS_EXPORT
18012+ /* i_generation */
18013+ struct file *si_xigen;
18014+ atomic_t si_xigen_next;
18015+#endif
18016+
18017+ /* vdir parameters */
18018+ unsigned long si_rdcache; /* max cache time in HZ */
18019+ unsigned int si_rdblk; /* deblk size */
18020+ unsigned int si_rdhash; /* hash size */
18021+
18022+ /*
18023+ * If the number of whiteouts are larger than si_dirwh, leave all of
18024+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
18025+ * future fsck.aufs or kernel thread will remove them later.
18026+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
18027+ */
18028+ unsigned int si_dirwh;
18029+
18030+ /*
18031+ * rename(2) a directory with all children.
18032+ */
18033+ /* reserved for future use */
18034+ /* int si_rendir; */
18035+
18036+ /* pseudo_link list */
18037+ struct au_splhead si_plink;
18038+ wait_queue_head_t si_plink_wq;
18039+
18040+ /*
18041+ * sysfs and lifetime management.
18042+ * this is not a small structure and it may be a waste of memory in case
18043+ * of sysfs is disabled, particulary when many aufs-es are mounted.
18044+ * but using sysfs is majority.
18045+ */
18046+ struct kobject si_kobj;
18047+#ifdef CONFIG_DEBUG_FS
18048+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
18049+#ifdef CONFIG_AUFS_EXPORT
18050+ struct dentry *si_dbgaufs_xigen;
18051+#endif
18052+#endif
18053+
18054+ /* dirty, necessary for unmounting, sysfs and sysrq */
18055+ struct super_block *si_sb;
18056+};
18057+
dece6358
AM
18058+/* sbinfo status flags */
18059+/*
18060+ * set true when refresh_dirs() failed at remount time.
18061+ * then try refreshing dirs at access time again.
18062+ * if it is false, refreshing dirs at access time is unnecesary
18063+ */
18064+#define AuSi_FAILED_REFRESH_DIRS 1
18065+#define AuSi_MAINTAIN_PLINK (1 << 1) /* ioctl */
18066+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
18067+ unsigned int flag)
18068+{
18069+ AuRwMustAnyLock(&sbi->si_rwsem);
18070+ return sbi->au_si_status & flag;
18071+}
18072+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
18073+#define au_fset_si(sbinfo, name) do { \
18074+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
18075+ (sbinfo)->au_si_status |= AuSi_##name; \
18076+} while (0)
18077+#define au_fclr_si(sbinfo, name) do { \
18078+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
18079+ (sbinfo)->au_si_status &= ~AuSi_##name; \
18080+} while (0)
18081+
1facf9fc 18082+/* ---------------------------------------------------------------------- */
18083+
18084+/* policy to select one among writable branches */
18085+#define AuWbrCopyup(sbinfo, args...) \
18086+ ((sbinfo)->si_wbr_copyup_ops->copyup(args))
18087+#define AuWbrCreate(sbinfo, args...) \
18088+ ((sbinfo)->si_wbr_create_ops->create(args))
18089+
18090+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
18091+#define AuLock_DW 1 /* write-lock dentry */
18092+#define AuLock_IR (1 << 1) /* read-lock inode */
18093+#define AuLock_IW (1 << 2) /* write-lock inode */
18094+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
18095+#define AuLock_DIR (1 << 4) /* target is a dir */
18096+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
18097+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
18098+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
18099+
18100+/* ---------------------------------------------------------------------- */
18101+
18102+/* super.c */
18103+extern struct file_system_type aufs_fs_type;
18104+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
18105+
18106+/* sbinfo.c */
18107+void au_si_free(struct kobject *kobj);
18108+int au_si_alloc(struct super_block *sb);
18109+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
18110+
18111+unsigned int au_sigen_inc(struct super_block *sb);
18112+aufs_bindex_t au_new_br_id(struct super_block *sb);
18113+
18114+void aufs_read_lock(struct dentry *dentry, int flags);
18115+void aufs_read_unlock(struct dentry *dentry, int flags);
18116+void aufs_write_lock(struct dentry *dentry);
18117+void aufs_write_unlock(struct dentry *dentry);
18118+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
18119+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
18120+
18121+/* wbr_policy.c */
18122+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
18123+extern struct au_wbr_create_operations au_wbr_create_ops[];
18124+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
18125+
18126+/* ---------------------------------------------------------------------- */
18127+
18128+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
18129+{
18130+ return sb->s_fs_info;
18131+}
18132+
18133+/* ---------------------------------------------------------------------- */
18134+
18135+#ifdef CONFIG_AUFS_EXPORT
18136+void au_export_init(struct super_block *sb);
18137+
18138+static inline int au_test_nfsd(struct task_struct *tsk)
18139+{
18140+ return !tsk->mm && !strcmp(tsk->comm, "nfsd");
18141+}
18142+
18143+int au_xigen_inc(struct inode *inode);
18144+int au_xigen_new(struct inode *inode);
18145+int au_xigen_set(struct super_block *sb, struct file *base);
18146+void au_xigen_clr(struct super_block *sb);
18147+
18148+static inline int au_busy_or_stale(void)
18149+{
18150+ if (!au_test_nfsd(current))
18151+ return -EBUSY;
18152+ return -ESTALE;
18153+}
18154+#else
18155+static inline void au_export_init(struct super_block *sb)
18156+{
18157+ /* nothing */
18158+}
18159+
18160+static inline int au_test_nfsd(struct task_struct *tsk)
18161+{
18162+ return 0;
18163+}
18164+
18165+static inline int au_xigen_inc(struct inode *inode)
18166+{
18167+ return 0;
18168+}
18169+
18170+static inline int au_xigen_new(struct inode *inode)
18171+{
18172+ return 0;
18173+}
18174+
18175+static inline int au_xigen_set(struct super_block *sb, struct file *base)
18176+{
18177+ return 0;
18178+}
18179+
18180+static inline void au_xigen_clr(struct super_block *sb)
18181+{
18182+ /* empty */
18183+}
18184+
18185+static inline int au_busy_or_stale(void)
18186+{
18187+ return -EBUSY;
18188+}
18189+#endif /* CONFIG_AUFS_EXPORT */
18190+
18191+/* ---------------------------------------------------------------------- */
18192+
18193+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
18194+{
dece6358
AM
18195+ /*
18196+ * This function is a dynamic '__init' fucntion actually,
18197+ * so the tiny check for si_rwsem is unnecessary.
18198+ */
18199+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 18200+#ifdef CONFIG_DEBUG_FS
18201+ sbinfo->si_dbgaufs = NULL;
18202+ sbinfo->si_dbgaufs_xib = NULL;
18203+#ifdef CONFIG_AUFS_EXPORT
18204+ sbinfo->si_dbgaufs_xigen = NULL;
18205+#endif
18206+#endif
18207+}
18208+
18209+/* ---------------------------------------------------------------------- */
18210+
18211+/* lock superblock. mainly for entry point functions */
18212+/*
18213+ * si_noflush_read_lock, si_noflush_write_lock,
18214+ * si_read_unlock, si_write_unlock, si_downgrade_lock
18215+ */
18216+AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
18217+ &au_sbi(sb)->si_rwsem);
18218+AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
18219+
dece6358
AM
18220+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
18221+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
18222+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
18223+
1facf9fc 18224+static inline void si_read_lock(struct super_block *sb, int flags)
18225+{
18226+ if (au_ftest_lock(flags, FLUSH))
18227+ au_nwt_flush(&au_sbi(sb)->si_nowait);
18228+ si_noflush_read_lock(sb);
18229+}
18230+
18231+static inline void si_write_lock(struct super_block *sb)
18232+{
18233+ au_nwt_flush(&au_sbi(sb)->si_nowait);
18234+ si_noflush_write_lock(sb);
18235+}
18236+
18237+static inline int si_read_trylock(struct super_block *sb, int flags)
18238+{
18239+ if (au_ftest_lock(flags, FLUSH))
18240+ au_nwt_flush(&au_sbi(sb)->si_nowait);
18241+ return si_noflush_read_trylock(sb);
18242+}
18243+
18244+static inline int si_write_trylock(struct super_block *sb, int flags)
18245+{
18246+ if (au_ftest_lock(flags, FLUSH))
18247+ au_nwt_flush(&au_sbi(sb)->si_nowait);
18248+ return si_noflush_write_trylock(sb);
18249+}
18250+
18251+/* ---------------------------------------------------------------------- */
18252+
18253+static inline aufs_bindex_t au_sbend(struct super_block *sb)
18254+{
dece6358 18255+ SiMustAnyLock(sb);
1facf9fc 18256+ return au_sbi(sb)->si_bend;
18257+}
18258+
18259+static inline unsigned int au_mntflags(struct super_block *sb)
18260+{
dece6358 18261+ SiMustAnyLock(sb);
1facf9fc 18262+ return au_sbi(sb)->si_mntflags;
18263+}
18264+
18265+static inline unsigned int au_sigen(struct super_block *sb)
18266+{
dece6358 18267+ SiMustAnyLock(sb);
1facf9fc 18268+ return au_sbi(sb)->si_generation;
18269+}
18270+
18271+static inline struct au_branch *au_sbr(struct super_block *sb,
18272+ aufs_bindex_t bindex)
18273+{
dece6358 18274+ SiMustAnyLock(sb);
1facf9fc 18275+ return au_sbi(sb)->si_branch[0 + bindex];
18276+}
18277+
18278+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
18279+{
dece6358 18280+ SiMustWriteLock(sb);
1facf9fc 18281+ au_sbi(sb)->si_xino_brid = brid;
18282+}
18283+
18284+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
18285+{
dece6358 18286+ SiMustAnyLock(sb);
1facf9fc 18287+ return au_sbi(sb)->si_xino_brid;
18288+}
18289+
18290+#endif /* __KERNEL__ */
18291+#endif /* __AUFS_SUPER_H__ */
dece6358
AM
18292diff -urN linux-2.6.30.org/fs/aufs/sysaufs.c linux-2.6.30/fs/aufs/sysaufs.c
18293--- linux-2.6.30.org/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
18294+++ linux-2.6.30/fs/aufs/sysaufs.c 2009-07-21 08:54:19.000000000 +0200
18295@@ -0,0 +1,104 @@
1facf9fc 18296+/*
18297+ * Copyright (C) 2005-2009 Junjiro R. Okajima
18298+ *
18299+ * This program, aufs is free software; you can redistribute it and/or modify
18300+ * it under the terms of the GNU General Public License as published by
18301+ * the Free Software Foundation; either version 2 of the License, or
18302+ * (at your option) any later version.
dece6358
AM
18303+ *
18304+ * This program is distributed in the hope that it will be useful,
18305+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18306+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18307+ * GNU General Public License for more details.
18308+ *
18309+ * You should have received a copy of the GNU General Public License
18310+ * along with this program; if not, write to the Free Software
18311+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18312+ */
18313+
18314+/*
18315+ * sysfs interface and lifetime management
18316+ * they are necessary regardless sysfs is disabled.
18317+ */
18318+
18319+#include <linux/fs.h>
18320+#include <linux/random.h>
18321+#include <linux/sysfs.h>
18322+#include "aufs.h"
18323+
18324+unsigned long sysaufs_si_mask;
18325+struct kset *sysaufs_ket;
18326+
18327+#define AuSiAttr(_name) { \
18328+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
18329+ .show = sysaufs_si_##_name, \
18330+}
18331+
18332+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
18333+struct attribute *sysaufs_si_attrs[] = {
18334+ &sysaufs_si_attr_xi_path.attr,
18335+ NULL,
18336+};
18337+
18338+static struct sysfs_ops au_sbi_ops = {
18339+ .show = sysaufs_si_show
18340+};
18341+
18342+static struct kobj_type au_sbi_ktype = {
18343+ .release = au_si_free,
18344+ .sysfs_ops = &au_sbi_ops,
18345+ .default_attrs = sysaufs_si_attrs
18346+};
18347+
18348+/* ---------------------------------------------------------------------- */
18349+
18350+int sysaufs_si_init(struct au_sbinfo *sbinfo)
18351+{
18352+ int err;
18353+
18354+ sbinfo->si_kobj.kset = sysaufs_ket;
18355+ /* cf. sysaufs_name() */
18356+ err = kobject_init_and_add
18357+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
18358+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
18359+
18360+ dbgaufs_si_null(sbinfo);
18361+ if (!err) {
18362+ err = dbgaufs_si_init(sbinfo);
18363+ if (unlikely(err))
18364+ kobject_put(&sbinfo->si_kobj);
18365+ }
18366+ return err;
18367+}
18368+
18369+void sysaufs_fin(void)
18370+{
18371+ dbgaufs_fin();
18372+ sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
18373+ kset_unregister(sysaufs_ket);
18374+}
18375+
18376+int __init sysaufs_init(void)
18377+{
18378+ int err;
18379+
18380+ do {
18381+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
18382+ } while (!sysaufs_si_mask);
18383+
18384+ sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
18385+ err = PTR_ERR(sysaufs_ket);
18386+ if (IS_ERR(sysaufs_ket))
18387+ goto out;
18388+ err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
18389+ if (unlikely(err)) {
18390+ kset_unregister(sysaufs_ket);
18391+ goto out;
18392+ }
18393+
18394+ err = dbgaufs_init();
18395+ if (unlikely(err))
18396+ sysaufs_fin();
18397+ out:
18398+ return err;
18399+}
dece6358
AM
18400diff -urN linux-2.6.30.org/fs/aufs/sysaufs.h linux-2.6.30/fs/aufs/sysaufs.h
18401--- linux-2.6.30.org/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
18402+++ linux-2.6.30/fs/aufs/sysaufs.h 2009-07-21 08:54:19.000000000 +0200
18403@@ -0,0 +1,120 @@
1facf9fc 18404+/*
18405+ * Copyright (C) 2005-2009 Junjiro R. Okajima
18406+ *
18407+ * This program, aufs is free software; you can redistribute it and/or modify
18408+ * it under the terms of the GNU General Public License as published by
18409+ * the Free Software Foundation; either version 2 of the License, or
18410+ * (at your option) any later version.
dece6358
AM
18411+ *
18412+ * This program is distributed in the hope that it will be useful,
18413+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18414+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18415+ * GNU General Public License for more details.
18416+ *
18417+ * You should have received a copy of the GNU General Public License
18418+ * along with this program; if not, write to the Free Software
18419+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18420+ */
18421+
18422+/*
18423+ * sysfs interface and mount lifetime management
18424+ */
18425+
18426+#ifndef __SYSAUFS_H__
18427+#define __SYSAUFS_H__
18428+
18429+#ifdef __KERNEL__
18430+
1facf9fc 18431+#include <linux/sysfs.h>
18432+#include <linux/aufs_type.h>
18433+#include "module.h"
18434+
dece6358
AM
18435+struct super_block;
18436+struct au_sbinfo;
18437+
1facf9fc 18438+struct sysaufs_si_attr {
18439+ struct attribute attr;
18440+ int (*show)(struct seq_file *seq, struct super_block *sb);
18441+};
18442+
18443+/* ---------------------------------------------------------------------- */
18444+
18445+/* sysaufs.c */
18446+extern unsigned long sysaufs_si_mask;
18447+extern struct kset *sysaufs_ket;
18448+extern struct attribute *sysaufs_si_attrs[];
18449+int sysaufs_si_init(struct au_sbinfo *sbinfo);
18450+int __init sysaufs_init(void);
18451+void sysaufs_fin(void);
18452+
18453+/* ---------------------------------------------------------------------- */
18454+
18455+/* some people doesn't like to show a pointer in kernel */
18456+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
18457+{
18458+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
18459+}
18460+
18461+#define SysaufsSiNamePrefix "si_"
18462+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
18463+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
18464+{
18465+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
18466+ sysaufs_si_id(sbinfo));
18467+}
18468+
18469+struct au_branch;
18470+#ifdef CONFIG_SYSFS
18471+/* sysfs.c */
18472+extern struct attribute_group *sysaufs_attr_group;
18473+
18474+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
18475+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
18476+ char *buf);
18477+
18478+void sysaufs_br_init(struct au_branch *br);
18479+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
18480+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
18481+
18482+#define sysaufs_brs_init() do {} while (0)
18483+
18484+#else
18485+#define sysaufs_attr_group NULL
18486+
18487+static inline
18488+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
18489+{
18490+ return 0;
18491+}
18492+
18493+static inline
18494+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
18495+ char *buf)
18496+{
18497+ return 0;
18498+}
18499+
18500+static inline void sysaufs_br_init(struct au_branch *br)
18501+{
18502+ /* empty */
18503+}
18504+
18505+static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
18506+{
18507+ /* nothing */
18508+}
18509+
18510+static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
18511+{
18512+ /* nothing */
18513+}
18514+
18515+static inline void sysaufs_brs_init(void)
18516+{
18517+ sysaufs_brs = 0;
18518+}
18519+
18520+#endif /* CONFIG_SYSFS */
18521+
18522+#endif /* __KERNEL__ */
18523+#endif /* __SYSAUFS_H__ */
dece6358
AM
18524diff -urN linux-2.6.30.org/fs/aufs/sysfs.c linux-2.6.30/fs/aufs/sysfs.c
18525--- linux-2.6.30.org/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
18526+++ linux-2.6.30/fs/aufs/sysfs.c 2009-07-21 08:54:19.000000000 +0200
18527@@ -0,0 +1,210 @@
1facf9fc 18528+/*
18529+ * Copyright (C) 2005-2009 Junjiro R. Okajima
18530+ *
18531+ * This program, aufs is free software; you can redistribute it and/or modify
18532+ * it under the terms of the GNU General Public License as published by
18533+ * the Free Software Foundation; either version 2 of the License, or
18534+ * (at your option) any later version.
dece6358
AM
18535+ *
18536+ * This program is distributed in the hope that it will be useful,
18537+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18538+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18539+ * GNU General Public License for more details.
18540+ *
18541+ * You should have received a copy of the GNU General Public License
18542+ * along with this program; if not, write to the Free Software
18543+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18544+ */
18545+
18546+/*
18547+ * sysfs interface
18548+ */
18549+
18550+#include <linux/fs.h>
dece6358 18551+#include <linux/module.h>
1facf9fc 18552+#include <linux/seq_file.h>
18553+#include <linux/sysfs.h>
18554+#include "aufs.h"
18555+
18556+static struct attribute *au_attr[] = {
18557+ NULL, /* need to NULL terminate the list of attributes */
18558+};
18559+
18560+static struct attribute_group sysaufs_attr_group_body = {
18561+ .attrs = au_attr
18562+};
18563+
18564+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
18565+
18566+/* ---------------------------------------------------------------------- */
18567+
18568+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
18569+{
18570+ int err;
18571+
dece6358
AM
18572+ SiMustAnyLock(sb);
18573+
1facf9fc 18574+ err = 0;
18575+ if (au_opt_test(au_mntflags(sb), XINO)) {
18576+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
18577+ seq_putc(seq, '\n');
18578+ }
18579+ return err;
18580+}
18581+
18582+/*
18583+ * the lifetime of branch is independent from the entry under sysfs.
18584+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
18585+ * unlinked.
18586+ */
18587+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
18588+ aufs_bindex_t bindex)
18589+{
18590+ struct path path;
18591+ struct dentry *root;
18592+ struct au_branch *br;
18593+
18594+ AuDbg("b%d\n", bindex);
18595+
18596+ root = sb->s_root;
18597+ di_read_lock_parent(root, !AuLock_IR);
18598+ br = au_sbr(sb, bindex);
18599+ path.mnt = br->br_mnt;
18600+ path.dentry = au_h_dptr(root, bindex);
18601+ au_seq_path(seq, &path);
18602+ di_read_unlock(root, !AuLock_IR);
18603+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
18604+ return 0;
18605+}
18606+
18607+/* ---------------------------------------------------------------------- */
18608+
18609+static struct seq_file *au_seq(char *p, ssize_t len)
18610+{
18611+ struct seq_file *seq;
18612+
18613+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
18614+ if (seq) {
18615+ /* mutex_init(&seq.lock); */
18616+ seq->buf = p;
18617+ seq->size = len;
18618+ return seq; /* success */
18619+ }
18620+
18621+ seq = ERR_PTR(-ENOMEM);
18622+ return seq;
18623+}
18624+
18625+#define SysaufsBr_PREFIX "br"
18626+
18627+/* todo: file size may exceed PAGE_SIZE */
18628+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
18629+ char *buf)
18630+{
18631+ ssize_t err;
18632+ long l;
18633+ aufs_bindex_t bend;
18634+ struct au_sbinfo *sbinfo;
18635+ struct super_block *sb;
18636+ struct seq_file *seq;
18637+ char *name;
18638+ struct attribute **cattr;
18639+
18640+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
18641+ sb = sbinfo->si_sb;
18642+ si_noflush_read_lock(sb);
18643+
18644+ seq = au_seq(buf, PAGE_SIZE);
18645+ err = PTR_ERR(seq);
18646+ if (IS_ERR(seq))
18647+ goto out;
18648+
18649+ name = (void *)attr->name;
18650+ cattr = sysaufs_si_attrs;
18651+ while (*cattr) {
18652+ if (!strcmp(name, (*cattr)->name)) {
18653+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
18654+ ->show(seq, sb);
18655+ goto out_seq;
18656+ }
18657+ cattr++;
18658+ }
18659+
18660+ bend = au_sbend(sb);
18661+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
18662+ name += sizeof(SysaufsBr_PREFIX) - 1;
18663+ err = strict_strtol(name, 10, &l);
18664+ if (!err) {
18665+ if (l <= bend)
18666+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
18667+ else
18668+ err = -ENOENT;
18669+ }
18670+ goto out_seq;
18671+ }
18672+ BUG();
18673+
18674+ out_seq:
18675+ if (!err) {
18676+ err = seq->count;
18677+ /* sysfs limit */
18678+ if (unlikely(err == PAGE_SIZE))
18679+ err = -EFBIG;
18680+ }
18681+ kfree(seq);
18682+ out:
18683+ si_read_unlock(sb);
18684+ return err;
18685+}
18686+
18687+/* ---------------------------------------------------------------------- */
18688+
18689+void sysaufs_br_init(struct au_branch *br)
18690+{
18691+ br->br_attr.name = br->br_name;
18692+ br->br_attr.mode = S_IRUGO;
18693+ br->br_attr.owner = THIS_MODULE;
18694+}
18695+
18696+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
18697+{
18698+ struct au_branch *br;
18699+ struct kobject *kobj;
18700+ aufs_bindex_t bend;
18701+
18702+ dbgaufs_brs_del(sb, bindex);
18703+
18704+ if (!sysaufs_brs)
18705+ return;
18706+
18707+ kobj = &au_sbi(sb)->si_kobj;
18708+ bend = au_sbend(sb);
18709+ for (; bindex <= bend; bindex++) {
18710+ br = au_sbr(sb, bindex);
18711+ sysfs_remove_file(kobj, &br->br_attr);
18712+ }
18713+}
18714+
18715+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
18716+{
18717+ int err;
18718+ aufs_bindex_t bend;
18719+ struct kobject *kobj;
18720+ struct au_branch *br;
18721+
18722+ dbgaufs_brs_add(sb, bindex);
18723+
18724+ if (!sysaufs_brs)
18725+ return;
18726+
18727+ kobj = &au_sbi(sb)->si_kobj;
18728+ bend = au_sbend(sb);
18729+ for (; bindex <= bend; bindex++) {
18730+ br = au_sbr(sb, bindex);
18731+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
18732+ "%d", bindex);
18733+ err = sysfs_create_file(kobj, &br->br_attr);
18734+ if (unlikely(err))
18735+ AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
18736+ }
18737+}
dece6358
AM
18738diff -urN linux-2.6.30.org/fs/aufs/sysrq.c linux-2.6.30/fs/aufs/sysrq.c
18739--- linux-2.6.30.org/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
18740+++ linux-2.6.30/fs/aufs/sysrq.c 2009-07-21 08:54:19.000000000 +0200
18741@@ -0,0 +1,115 @@
1facf9fc 18742+/*
18743+ * Copyright (C) 2005-2009 Junjiro R. Okajima
18744+ *
18745+ * This program, aufs is free software; you can redistribute it and/or modify
18746+ * it under the terms of the GNU General Public License as published by
18747+ * the Free Software Foundation; either version 2 of the License, or
18748+ * (at your option) any later version.
dece6358
AM
18749+ *
18750+ * This program is distributed in the hope that it will be useful,
18751+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18752+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18753+ * GNU General Public License for more details.
18754+ *
18755+ * You should have received a copy of the GNU General Public License
18756+ * along with this program; if not, write to the Free Software
18757+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18758+ */
18759+
18760+/*
18761+ * magic sysrq hanlder
18762+ */
18763+
18764+#include <linux/fs.h>
18765+#include <linux/module.h>
18766+#include <linux/moduleparam.h>
18767+/* #include <linux/sysrq.h> */
18768+#include "aufs.h"
18769+
18770+/* ---------------------------------------------------------------------- */
18771+
18772+static void sysrq_sb(struct super_block *sb)
18773+{
18774+ char *plevel;
18775+ struct au_sbinfo *sbinfo;
18776+ struct file *file;
18777+
18778+ plevel = au_plevel;
18779+ au_plevel = KERN_WARNING;
18780+ au_debug(1);
18781+
18782+ sbinfo = au_sbi(sb);
18783+ pr_warning("si=%lx\n", sysaufs_si_id(sbinfo));
18784+ pr_warning(AUFS_NAME ": superblock\n");
18785+ au_dpri_sb(sb);
18786+ pr_warning(AUFS_NAME ": root dentry\n");
18787+ au_dpri_dentry(sb->s_root);
18788+ pr_warning(AUFS_NAME ": root inode\n");
18789+ au_dpri_inode(sb->s_root->d_inode);
18790+#if 0
18791+ struct inode *i;
18792+ pr_warning(AUFS_NAME ": isolated inode\n");
18793+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
18794+ if (list_empty(&i->i_dentry))
18795+ au_dpri_inode(i);
18796+#endif
18797+ pr_warning(AUFS_NAME ": files\n");
18798+ list_for_each_entry(file, &sb->s_files, f_u.fu_list)
18799+ if (!special_file(file->f_dentry->d_inode->i_mode))
18800+ au_dpri_file(file);
18801+
18802+ au_plevel = plevel;
18803+ au_debug(0);
18804+}
18805+
18806+/* ---------------------------------------------------------------------- */
18807+
18808+/* module parameter */
18809+static char *aufs_sysrq_key = "a";
18810+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
18811+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
18812+
18813+static void au_sysrq(int key __maybe_unused,
18814+ struct tty_struct *tty __maybe_unused)
18815+{
18816+ struct kobject *kobj;
18817+ struct au_sbinfo *sbinfo;
18818+
18819+ /* spin_lock(&sysaufs_ket->list_lock); */
18820+ list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
18821+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
18822+ sysrq_sb(sbinfo->si_sb);
18823+ }
18824+ /* spin_unlock(&sysaufs_ket->list_lock); */
18825+}
18826+
18827+static struct sysrq_key_op au_sysrq_op = {
18828+ .handler = au_sysrq,
18829+ .help_msg = "Aufs",
18830+ .action_msg = "Aufs",
18831+ .enable_mask = SYSRQ_ENABLE_DUMP
18832+};
18833+
18834+/* ---------------------------------------------------------------------- */
18835+
18836+int __init au_sysrq_init(void)
18837+{
18838+ int err;
18839+ char key;
18840+
18841+ err = -1;
18842+ key = *aufs_sysrq_key;
18843+ if ('a' <= key && key <= 'z')
18844+ err = register_sysrq_key(key, &au_sysrq_op);
18845+ if (unlikely(err))
18846+ AuErr("err %d, sysrq=%c\n", err, key);
18847+ return err;
18848+}
18849+
18850+void au_sysrq_fin(void)
18851+{
18852+ int err;
18853+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
18854+ if (unlikely(err))
18855+ AuErr("err %d (ignored)\n", err);
18856+}
dece6358
AM
18857diff -urN linux-2.6.30.org/fs/aufs/vdir.c linux-2.6.30/fs/aufs/vdir.c
18858--- linux-2.6.30.org/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
18859+++ linux-2.6.30/fs/aufs/vdir.c 2009-07-21 08:54:19.000000000 +0200
18860@@ -0,0 +1,882 @@
1facf9fc 18861+/*
18862+ * Copyright (C) 2005-2009 Junjiro R. Okajima
18863+ *
18864+ * This program, aufs is free software; you can redistribute it and/or modify
18865+ * it under the terms of the GNU General Public License as published by
18866+ * the Free Software Foundation; either version 2 of the License, or
18867+ * (at your option) any later version.
dece6358
AM
18868+ *
18869+ * This program is distributed in the hope that it will be useful,
18870+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18871+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18872+ * GNU General Public License for more details.
18873+ *
18874+ * You should have received a copy of the GNU General Public License
18875+ * along with this program; if not, write to the Free Software
18876+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18877+ */
18878+
18879+/*
18880+ * virtual or vertical directory
18881+ */
18882+
dece6358 18883+#include <linux/hash.h>
1facf9fc 18884+#include "aufs.h"
18885+
dece6358 18886+static unsigned int calc_size(int nlen)
1facf9fc 18887+{
1facf9fc 18888+ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
dece6358 18889+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 18890+}
18891+
18892+static int set_deblk_end(union au_vdir_deblk_p *p,
18893+ union au_vdir_deblk_p *deblk_end)
18894+{
18895+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
18896+ p->de->de_str.len = 0;
18897+ /* smp_mb(); */
18898+ return 0;
18899+ }
18900+ return -1; /* error */
18901+}
18902+
18903+/* returns true or false */
18904+static int is_deblk_end(union au_vdir_deblk_p *p,
18905+ union au_vdir_deblk_p *deblk_end)
18906+{
18907+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
18908+ return !p->de->de_str.len;
18909+ return 1;
18910+}
18911+
18912+static unsigned char *last_deblk(struct au_vdir *vdir)
18913+{
18914+ return vdir->vd_deblk[vdir->vd_nblk - 1];
18915+}
18916+
18917+/* ---------------------------------------------------------------------- */
18918+
18919+/*
18920+ * the allocated memory has to be freed by
dece6358 18921+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 18922+ */
dece6358 18923+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 18924+{
1facf9fc 18925+ struct hlist_head *head;
dece6358 18926+ unsigned int u;
1facf9fc 18927+
dece6358
AM
18928+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
18929+ if (head) {
18930+ nhash->nh_num = num_hash;
18931+ nhash->nh_head = head;
18932+ for (u = 0; u < num_hash; u++)
1facf9fc 18933+ INIT_HLIST_HEAD(head++);
dece6358 18934+ return 0; /* success */
1facf9fc 18935+ }
1facf9fc 18936+
dece6358 18937+ return -ENOMEM;
1facf9fc 18938+}
18939+
dece6358
AM
18940+static void nhash_count(struct hlist_head *head)
18941+{
18942+#if 0
18943+ unsigned long n;
18944+ struct hlist_node *pos;
18945+
18946+ n = 0;
18947+ hlist_for_each(pos, head)
18948+ n++;
18949+ AuInfo("%lu\n", n);
18950+#endif
18951+}
18952+
18953+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 18954+{
1facf9fc 18955+ struct au_vdir_wh *tpos;
18956+ struct hlist_node *pos, *node;
18957+
dece6358
AM
18958+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
18959+ /* hlist_del(pos); */
18960+ kfree(tpos);
1facf9fc 18961+ }
18962+}
18963+
dece6358 18964+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 18965+{
dece6358
AM
18966+ struct au_vdir_dehstr *tpos;
18967+ struct hlist_node *pos, *node;
1facf9fc 18968+
dece6358
AM
18969+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
18970+ /* hlist_del(pos); */
18971+ au_cache_free_dehstr(tpos);
1facf9fc 18972+ }
1facf9fc 18973+}
18974+
dece6358
AM
18975+static void au_nhash_do_free(struct au_nhash *nhash,
18976+ void (*free)(struct hlist_head *head))
1facf9fc 18977+{
18978+ unsigned int u, n;
18979+ struct hlist_head *head;
1facf9fc 18980+
dece6358
AM
18981+ n = nhash->nh_num;
18982+ head = nhash->nh_head;
1facf9fc 18983+ for (u = 0; u < n; u++) {
dece6358
AM
18984+ nhash_count(head);
18985+ free(head++);
1facf9fc 18986+ }
dece6358 18987+ kfree(nhash->nh_head);
1facf9fc 18988+}
18989+
dece6358 18990+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 18991+{
dece6358
AM
18992+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
18993+}
1facf9fc 18994+
dece6358
AM
18995+static void au_nhash_de_free(struct au_nhash *delist)
18996+{
18997+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 18998+}
18999+
19000+/* ---------------------------------------------------------------------- */
19001+
19002+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
19003+ int limit)
19004+{
19005+ int num;
19006+ unsigned int u, n;
19007+ struct hlist_head *head;
19008+ struct au_vdir_wh *tpos;
19009+ struct hlist_node *pos;
19010+
19011+ num = 0;
19012+ n = whlist->nh_num;
19013+ head = whlist->nh_head;
19014+ for (u = 0; u < n; u++) {
19015+ hlist_for_each_entry(tpos, pos, head, wh_hash)
19016+ if (tpos->wh_bindex == btgt && ++num > limit)
19017+ return 1;
19018+ head++;
19019+ }
19020+ return 0;
19021+}
19022+
19023+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 19024+ unsigned char *name,
1facf9fc 19025+ unsigned int len)
19026+{
dece6358
AM
19027+ unsigned int v;
19028+ /* const unsigned int magic_bit = 12; */
19029+
19030+ v = 0;
19031+ while (len--)
19032+ v += *name++;
19033+ /* v = hash_long(v, magic_bit); */
19034+ v %= nhash->nh_num;
19035+ return nhash->nh_head + v;
19036+}
19037+
19038+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
19039+ int nlen)
19040+{
19041+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 19042+}
19043+
19044+/* returns found or not */
dece6358 19045+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 19046+{
19047+ struct hlist_head *head;
19048+ struct au_vdir_wh *tpos;
19049+ struct hlist_node *pos;
19050+ struct au_vdir_destr *str;
19051+
dece6358 19052+ head = au_name_hash(whlist, name, nlen);
1facf9fc 19053+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
19054+ str = &tpos->wh_str;
19055+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
19056+ if (au_nhash_test_name(str, name, nlen))
19057+ return 1;
19058+ }
19059+ return 0;
19060+}
19061+
19062+/* returns found(true) or not */
19063+static int test_known(struct au_nhash *delist, char *name, int nlen)
19064+{
19065+ struct hlist_head *head;
19066+ struct au_vdir_dehstr *tpos;
19067+ struct hlist_node *pos;
19068+ struct au_vdir_destr *str;
19069+
19070+ head = au_name_hash(delist, name, nlen);
19071+ hlist_for_each_entry(tpos, pos, head, hash) {
19072+ str = tpos->str;
19073+ AuDbg("%.*s\n", str->len, str->name);
19074+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 19075+ return 1;
19076+ }
19077+ return 0;
19078+}
19079+
dece6358
AM
19080+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
19081+ unsigned char d_type)
19082+{
19083+#ifdef CONFIG_AUFS_SHWH
19084+ wh->wh_ino = ino;
19085+ wh->wh_type = d_type;
19086+#endif
19087+}
19088+
19089+/* ---------------------------------------------------------------------- */
19090+
19091+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
19092+ unsigned int d_type, aufs_bindex_t bindex,
19093+ unsigned char shwh)
1facf9fc 19094+{
19095+ int err;
19096+ struct au_vdir_destr *str;
19097+ struct au_vdir_wh *wh;
19098+
dece6358 19099+ AuDbg("%.*s\n", nlen, name);
1facf9fc 19100+ err = -ENOMEM;
dece6358 19101+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 19102+ if (unlikely(!wh))
19103+ goto out;
19104+
19105+ err = 0;
19106+ wh->wh_bindex = bindex;
dece6358
AM
19107+ if (shwh)
19108+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 19109+ str = &wh->wh_str;
dece6358
AM
19110+ str->len = nlen;
19111+ memcpy(str->name, name, nlen);
19112+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 19113+ /* smp_mb(); */
19114+
19115+ out:
19116+ return err;
19117+}
19118+
1facf9fc 19119+static int append_deblk(struct au_vdir *vdir)
19120+{
19121+ int err;
dece6358 19122+ unsigned long ul;
1facf9fc 19123+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
19124+ union au_vdir_deblk_p p, deblk_end;
19125+ unsigned char **o;
19126+
19127+ err = -ENOMEM;
dece6358
AM
19128+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
19129+ GFP_NOFS);
1facf9fc 19130+ if (unlikely(!o))
19131+ goto out;
19132+
19133+ vdir->vd_deblk = o;
19134+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
19135+ if (p.deblk) {
19136+ ul = vdir->vd_nblk++;
19137+ vdir->vd_deblk[ul] = p.deblk;
19138+ vdir->vd_last.ul = ul;
19139+ vdir->vd_last.p.deblk = p.deblk;
19140+ deblk_end.deblk = p.deblk + deblk_sz;
19141+ err = set_deblk_end(&p, &deblk_end);
19142+ }
19143+
19144+ out:
19145+ return err;
19146+}
19147+
dece6358
AM
19148+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
19149+ unsigned int d_type, struct au_nhash *delist)
19150+{
19151+ int err;
19152+ unsigned int sz;
19153+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
19154+ union au_vdir_deblk_p p, *room, deblk_end;
19155+ struct au_vdir_dehstr *dehstr;
19156+
19157+ p.deblk = last_deblk(vdir);
19158+ deblk_end.deblk = p.deblk + deblk_sz;
19159+ room = &vdir->vd_last.p;
19160+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
19161+ || !is_deblk_end(room, &deblk_end));
19162+
19163+ sz = calc_size(nlen);
19164+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
19165+ err = append_deblk(vdir);
19166+ if (unlikely(err))
19167+ goto out;
19168+
19169+ p.deblk = last_deblk(vdir);
19170+ deblk_end.deblk = p.deblk + deblk_sz;
19171+ /* smp_mb(); */
19172+ AuDebugOn(room->deblk != p.deblk);
19173+ }
19174+
19175+ err = -ENOMEM;
19176+ dehstr = au_cache_alloc_dehstr();
19177+ if (unlikely(!dehstr))
19178+ goto out;
19179+
19180+ dehstr->str = &room->de->de_str;
19181+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
19182+ room->de->de_ino = ino;
19183+ room->de->de_type = d_type;
19184+ room->de->de_str.len = nlen;
19185+ memcpy(room->de->de_str.name, name, nlen);
19186+
19187+ err = 0;
19188+ room->deblk += sz;
19189+ if (unlikely(set_deblk_end(room, &deblk_end)))
19190+ err = append_deblk(vdir);
19191+ /* smp_mb(); */
19192+
19193+ out:
19194+ return err;
19195+}
19196+
19197+/* ---------------------------------------------------------------------- */
19198+
19199+void au_vdir_free(struct au_vdir *vdir)
19200+{
19201+ unsigned char **deblk;
19202+
19203+ deblk = vdir->vd_deblk;
19204+ while (vdir->vd_nblk--)
19205+ kfree(*deblk++);
19206+ kfree(vdir->vd_deblk);
19207+ au_cache_free_vdir(vdir);
19208+}
19209+
1facf9fc 19210+static struct au_vdir *alloc_vdir(struct super_block *sb)
19211+{
19212+ struct au_vdir *vdir;
19213+ int err;
19214+
dece6358
AM
19215+ SiMustAnyLock(sb);
19216+
1facf9fc 19217+ err = -ENOMEM;
19218+ vdir = au_cache_alloc_vdir();
19219+ if (unlikely(!vdir))
19220+ goto out;
19221+
19222+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
19223+ if (unlikely(!vdir->vd_deblk))
19224+ goto out_free;
19225+
19226+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
19227+ vdir->vd_nblk = 0;
19228+ vdir->vd_version = 0;
19229+ vdir->vd_jiffy = 0;
19230+ err = append_deblk(vdir);
19231+ if (!err)
19232+ return vdir; /* success */
19233+
19234+ kfree(vdir->vd_deblk);
19235+
19236+ out_free:
19237+ au_cache_free_vdir(vdir);
19238+ out:
19239+ vdir = ERR_PTR(err);
19240+ return vdir;
19241+}
19242+
19243+static int reinit_vdir(struct au_vdir *vdir)
19244+{
19245+ int err;
19246+ union au_vdir_deblk_p p, deblk_end;
19247+
19248+ while (vdir->vd_nblk > 1) {
19249+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
19250+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
19251+ vdir->vd_nblk--;
19252+ }
19253+ p.deblk = vdir->vd_deblk[0];
19254+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
19255+ err = set_deblk_end(&p, &deblk_end);
19256+ /* keep vd_dblk_sz */
19257+ vdir->vd_last.ul = 0;
19258+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
19259+ vdir->vd_version = 0;
19260+ vdir->vd_jiffy = 0;
19261+ /* smp_mb(); */
19262+ return err;
19263+}
19264+
19265+/* ---------------------------------------------------------------------- */
19266+
1facf9fc 19267+static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
19268+ unsigned int d_type, ino_t *ino)
19269+{
19270+ int err;
19271+ struct mutex *mtx;
19272+ const int isdir = (d_type == DT_DIR);
19273+
19274+ /* prevent hardlinks from race condition */
19275+ mtx = NULL;
19276+ if (!isdir) {
19277+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
19278+ mutex_lock(mtx);
19279+ }
19280+ err = au_xino_read(sb, bindex, h_ino, ino);
19281+ if (unlikely(err))
19282+ goto out;
19283+
19284+ if (!*ino) {
19285+ err = -EIO;
19286+ *ino = au_xino_new_ino(sb);
19287+ if (unlikely(!*ino))
19288+ goto out;
19289+ err = au_xino_write(sb, bindex, h_ino, *ino);
19290+ if (unlikely(err))
19291+ goto out;
19292+ }
19293+
19294+ out:
19295+ if (!isdir)
19296+ mutex_unlock(mtx);
19297+ return err;
19298+}
19299+
dece6358
AM
19300+static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
19301+ unsigned int d_type, ino_t *ino)
19302+{
19303+#ifdef CONFIG_AUFS_SHWH
19304+ return au_ino(sb, bindex, h_ino, d_type, ino);
19305+#else
19306+ return 0;
19307+#endif
19308+}
19309+
1facf9fc 19310+#define AuFillVdir_CALLED 1
19311+#define AuFillVdir_WHABLE (1 << 1)
dece6358 19312+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 19313+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
19314+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
19315+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
19316+
dece6358
AM
19317+#ifndef CONFIG_AUFS_SHWH
19318+#undef AuFillVdir_SHWH
19319+#define AuFillVdir_SHWH 0
19320+#endif
19321+
1facf9fc 19322+struct fillvdir_arg {
19323+ struct file *file;
19324+ struct au_vdir *vdir;
dece6358
AM
19325+ struct au_nhash delist;
19326+ struct au_nhash whlist;
1facf9fc 19327+ aufs_bindex_t bindex;
19328+ unsigned int flags;
19329+ int err;
19330+};
19331+
dece6358 19332+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 19333+ loff_t offset __maybe_unused, u64 h_ino,
19334+ unsigned int d_type)
19335+{
19336+ struct fillvdir_arg *arg = __arg;
19337+ char *name = (void *)__name;
19338+ struct super_block *sb;
1facf9fc 19339+ ino_t ino;
dece6358 19340+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 19341+
1facf9fc 19342+ arg->err = 0;
dece6358 19343+ sb = arg->file->f_dentry->d_sb;
1facf9fc 19344+ au_fset_fillvdir(arg->flags, CALLED);
19345+ /* smp_mb(); */
dece6358 19346+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 19347+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
19348+ if (test_known(&arg->delist, name, nlen)
19349+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
19350+ goto out; /* already exists or whiteouted */
1facf9fc 19351+
19352+ sb = arg->file->f_dentry->d_sb;
dece6358 19353+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
1facf9fc 19354+ if (!arg->err)
dece6358
AM
19355+ arg->err = append_de(arg->vdir, name, nlen, ino,
19356+ d_type, &arg->delist);
1facf9fc 19357+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
19358+ name += AUFS_WH_PFX_LEN;
dece6358
AM
19359+ nlen -= AUFS_WH_PFX_LEN;
19360+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
19361+ goto out; /* already whiteouted */
1facf9fc 19362+
dece6358
AM
19363+ if (shwh)
19364+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
19365+ &ino);
1facf9fc 19366+ if (!arg->err)
19367+ arg->err = au_nhash_append_wh
dece6358
AM
19368+ (&arg->whlist, name, nlen, ino, d_type,
19369+ arg->bindex, shwh);
1facf9fc 19370+ }
19371+
19372+ out:
19373+ if (!arg->err)
19374+ arg->vdir->vd_jiffy = jiffies;
19375+ /* smp_mb(); */
19376+ AuTraceErr(arg->err);
19377+ return arg->err;
19378+}
19379+
dece6358
AM
19380+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
19381+ struct au_nhash *whlist, struct au_nhash *delist)
19382+{
19383+#ifdef CONFIG_AUFS_SHWH
19384+ int err;
19385+ unsigned int nh, u;
19386+ struct hlist_head *head;
19387+ struct au_vdir_wh *tpos;
19388+ struct hlist_node *pos, *n;
19389+ char *p, *o;
19390+ struct au_vdir_destr *destr;
19391+
19392+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
19393+
19394+ err = -ENOMEM;
19395+ o = p = __getname();
19396+ if (unlikely(!p))
19397+ goto out;
19398+
19399+ err = 0;
19400+ nh = whlist->nh_num;
19401+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
19402+ p += AUFS_WH_PFX_LEN;
19403+ for (u = 0; u < nh; u++) {
19404+ head = whlist->nh_head + u;
19405+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
19406+ destr = &tpos->wh_str;
19407+ memcpy(p, destr->name, destr->len);
19408+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
19409+ tpos->wh_ino, tpos->wh_type, delist);
19410+ if (unlikely(err))
19411+ break;
19412+ }
19413+ }
19414+
19415+ __putname(o);
19416+
19417+ out:
19418+ AuTraceErr(err);
19419+ return err;
19420+#else
19421+ return 0;
19422+#endif
19423+}
19424+
1facf9fc 19425+static int au_do_read_vdir(struct fillvdir_arg *arg)
19426+{
19427+ int err;
dece6358 19428+ unsigned int rdhash;
1facf9fc 19429+ loff_t offset;
dece6358
AM
19430+ aufs_bindex_t bend, bindex, bstart;
19431+ unsigned char shwh;
1facf9fc 19432+ struct file *hf, *file;
19433+ struct super_block *sb;
19434+
1facf9fc 19435+ file = arg->file;
19436+ sb = file->f_dentry->d_sb;
dece6358
AM
19437+ SiMustAnyLock(sb);
19438+
19439+ rdhash = au_sbi(sb)->si_rdhash;
19440+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
19441+ if (unlikely(err))
1facf9fc 19442+ goto out;
dece6358
AM
19443+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
19444+ if (unlikely(err))
1facf9fc 19445+ goto out_delist;
19446+
19447+ err = 0;
19448+ arg->flags = 0;
dece6358
AM
19449+ shwh = 0;
19450+ if (au_opt_test(au_mntflags(sb), SHWH)) {
19451+ shwh = 1;
19452+ au_fset_fillvdir(arg->flags, SHWH);
19453+ }
19454+ bstart = au_fbstart(file);
19455+ bend = au_fbend(file);
19456+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
1facf9fc 19457+ hf = au_h_fptr(file, bindex);
19458+ if (!hf)
19459+ continue;
19460+
19461+ offset = vfsub_llseek(hf, 0, SEEK_SET);
19462+ err = offset;
19463+ if (unlikely(offset))
19464+ break;
19465+
19466+ arg->bindex = bindex;
19467+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
19468+ if (shwh
19469+ || (bindex != bend
19470+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 19471+ au_fset_fillvdir(arg->flags, WHABLE);
19472+ do {
19473+ arg->err = 0;
19474+ au_fclr_fillvdir(arg->flags, CALLED);
19475+ /* smp_mb(); */
19476+ err = vfsub_readdir(hf, fillvdir, arg);
19477+ if (err >= 0)
19478+ err = arg->err;
19479+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
19480+ }
dece6358
AM
19481+
19482+ if (!err && shwh)
19483+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
19484+
19485+ au_nhash_wh_free(&arg->whlist);
1facf9fc 19486+
19487+ out_delist:
dece6358 19488+ au_nhash_de_free(&arg->delist);
1facf9fc 19489+ out:
19490+ return err;
19491+}
19492+
19493+static int read_vdir(struct file *file, int may_read)
19494+{
19495+ int err;
19496+ unsigned long expire;
19497+ unsigned char do_read;
19498+ struct fillvdir_arg arg;
19499+ struct inode *inode;
19500+ struct au_vdir *vdir, *allocated;
19501+
19502+ err = 0;
19503+ inode = file->f_dentry->d_inode;
19504+ IMustLock(inode);
dece6358
AM
19505+ SiMustAnyLock(inode->i_sb);
19506+
1facf9fc 19507+ allocated = NULL;
19508+ do_read = 0;
19509+ expire = au_sbi(inode->i_sb)->si_rdcache;
19510+ vdir = au_ivdir(inode);
19511+ if (!vdir) {
19512+ do_read = 1;
19513+ vdir = alloc_vdir(inode->i_sb);
19514+ err = PTR_ERR(vdir);
19515+ if (IS_ERR(vdir))
19516+ goto out;
19517+ err = 0;
19518+ allocated = vdir;
19519+ } else if (may_read
19520+ && (inode->i_version != vdir->vd_version
19521+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
19522+ do_read = 1;
19523+ err = reinit_vdir(vdir);
19524+ if (unlikely(err))
19525+ goto out;
19526+ }
19527+
19528+ if (!do_read)
19529+ return 0; /* success */
19530+
19531+ arg.file = file;
19532+ arg.vdir = vdir;
19533+ err = au_do_read_vdir(&arg);
19534+ if (!err) {
19535+ /* file->f_pos = 0; */
19536+ vdir->vd_version = inode->i_version;
19537+ vdir->vd_last.ul = 0;
19538+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
19539+ if (allocated)
19540+ au_set_ivdir(inode, allocated);
19541+ } else if (allocated)
19542+ au_vdir_free(allocated);
19543+
19544+ out:
19545+ return err;
19546+}
19547+
19548+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
19549+{
19550+ int err, rerr;
19551+ unsigned long ul, n;
19552+ const unsigned int deblk_sz = src->vd_deblk_sz;
19553+
19554+ AuDebugOn(tgt->vd_nblk != 1);
19555+
19556+ err = -ENOMEM;
19557+ if (tgt->vd_nblk < src->vd_nblk) {
19558+ unsigned char **p;
19559+
dece6358
AM
19560+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
19561+ GFP_NOFS);
1facf9fc 19562+ if (unlikely(!p))
19563+ goto out;
19564+ tgt->vd_deblk = p;
19565+ }
19566+
19567+ tgt->vd_nblk = src->vd_nblk;
19568+ tgt->vd_deblk_sz = deblk_sz;
19569+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
19570+ /* tgt->vd_last.i = 0; */
19571+ /* tgt->vd_last.p.deblk = tgt->vd_deblk[0]; */
19572+ tgt->vd_version = src->vd_version;
19573+ tgt->vd_jiffy = src->vd_jiffy;
19574+
19575+ n = src->vd_nblk;
19576+ for (ul = 1; ul < n; ul++) {
dece6358
AM
19577+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
19578+ GFP_NOFS);
19579+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 19580+ goto out;
19581+ }
19582+ /* smp_mb(); */
19583+ return 0; /* success */
19584+
19585+ out:
19586+ rerr = reinit_vdir(tgt);
19587+ BUG_ON(rerr);
19588+ return err;
19589+}
19590+
19591+int au_vdir_init(struct file *file)
19592+{
19593+ int err;
19594+ struct inode *inode;
19595+ struct au_vdir *vdir_cache, *allocated;
19596+
19597+ err = read_vdir(file, !file->f_pos);
19598+ if (unlikely(err))
19599+ goto out;
19600+
19601+ allocated = NULL;
19602+ vdir_cache = au_fvdir_cache(file);
19603+ if (!vdir_cache) {
19604+ vdir_cache = alloc_vdir(file->f_dentry->d_sb);
19605+ err = PTR_ERR(vdir_cache);
19606+ if (IS_ERR(vdir_cache))
19607+ goto out;
19608+ allocated = vdir_cache;
19609+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
19610+ err = reinit_vdir(vdir_cache);
19611+ if (unlikely(err))
19612+ goto out;
19613+ } else
19614+ return 0; /* success */
19615+
19616+ inode = file->f_dentry->d_inode;
19617+ err = copy_vdir(vdir_cache, au_ivdir(inode));
19618+ if (!err) {
19619+ file->f_version = inode->i_version;
19620+ if (allocated)
19621+ au_set_fvdir_cache(file, allocated);
19622+ } else if (allocated)
19623+ au_vdir_free(allocated);
19624+
19625+ out:
19626+ return err;
19627+}
19628+
19629+static loff_t calc_offset(struct au_vdir *vdir)
19630+{
19631+ loff_t offset;
19632+ union au_vdir_deblk_p p;
19633+
19634+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
19635+ offset = vdir->vd_last.p.deblk - p.deblk;
19636+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
19637+ return offset;
19638+}
19639+
19640+/* returns true or false */
19641+static int seek_vdir(struct file *file)
19642+{
19643+ int valid;
19644+ unsigned int deblk_sz;
19645+ unsigned long ul, n;
19646+ loff_t offset;
19647+ union au_vdir_deblk_p p, deblk_end;
19648+ struct au_vdir *vdir_cache;
19649+
19650+ valid = 1;
19651+ vdir_cache = au_fvdir_cache(file);
19652+ offset = calc_offset(vdir_cache);
19653+ AuDbg("offset %lld\n", offset);
19654+ if (file->f_pos == offset)
19655+ goto out;
19656+
19657+ vdir_cache->vd_last.ul = 0;
19658+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
19659+ if (!file->f_pos)
19660+ goto out;
19661+
19662+ valid = 0;
19663+ deblk_sz = vdir_cache->vd_deblk_sz;
19664+ ul = div64_u64(file->f_pos, deblk_sz);
19665+ AuDbg("ul %lu\n", ul);
19666+ if (ul >= vdir_cache->vd_nblk)
19667+ goto out;
19668+
19669+ n = vdir_cache->vd_nblk;
19670+ for (; ul < n; ul++) {
19671+ p.deblk = vdir_cache->vd_deblk[ul];
19672+ deblk_end.deblk = p.deblk + deblk_sz;
19673+ offset = ul;
19674+ offset *= deblk_sz;
19675+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
19676+ unsigned int l;
19677+
19678+ l = calc_size(p.de->de_str.len);
19679+ offset += l;
19680+ p.deblk += l;
19681+ }
19682+ if (!is_deblk_end(&p, &deblk_end)) {
19683+ valid = 1;
19684+ vdir_cache->vd_last.ul = ul;
19685+ vdir_cache->vd_last.p = p;
19686+ break;
19687+ }
19688+ }
19689+
19690+ out:
19691+ /* smp_mb(); */
19692+ AuTraceErr(!valid);
19693+ return valid;
19694+}
19695+
19696+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
19697+{
19698+ int err;
19699+ unsigned int l, deblk_sz;
19700+ union au_vdir_deblk_p deblk_end;
19701+ struct au_vdir *vdir_cache;
19702+ struct au_vdir_de *de;
19703+
19704+ vdir_cache = au_fvdir_cache(file);
19705+ if (!seek_vdir(file))
19706+ return 0;
19707+
19708+ deblk_sz = vdir_cache->vd_deblk_sz;
19709+ while (1) {
19710+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
19711+ deblk_end.deblk += deblk_sz;
19712+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
19713+ de = vdir_cache->vd_last.p.de;
19714+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
19715+ de->de_str.len, de->de_str.name, file->f_pos,
19716+ (unsigned long)de->de_ino, de->de_type);
19717+ err = filldir(dirent, de->de_str.name, de->de_str.len,
19718+ file->f_pos, de->de_ino, de->de_type);
19719+ if (unlikely(err)) {
19720+ AuTraceErr(err);
19721+ /* todo: ignore the error caused by udba? */
19722+ /* return err; */
19723+ return 0;
19724+ }
19725+
19726+ l = calc_size(de->de_str.len);
19727+ vdir_cache->vd_last.p.deblk += l;
19728+ file->f_pos += l;
19729+ }
19730+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
19731+ vdir_cache->vd_last.ul++;
19732+ vdir_cache->vd_last.p.deblk
19733+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
19734+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
19735+ continue;
19736+ }
19737+ break;
19738+ }
19739+
19740+ /* smp_mb(); */
19741+ return 0;
19742+}
dece6358
AM
19743diff -urN linux-2.6.30.org/fs/aufs/vfsub.c linux-2.6.30/fs/aufs/vfsub.c
19744--- linux-2.6.30.org/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
19745+++ linux-2.6.30/fs/aufs/vfsub.c 2009-07-21 08:54:19.000000000 +0200
19746@@ -0,0 +1,736 @@
1facf9fc 19747+/*
19748+ * Copyright (C) 2005-2009 Junjiro R. Okajima
19749+ *
19750+ * This program, aufs is free software; you can redistribute it and/or modify
19751+ * it under the terms of the GNU General Public License as published by
19752+ * the Free Software Foundation; either version 2 of the License, or
19753+ * (at your option) any later version.
dece6358
AM
19754+ *
19755+ * This program is distributed in the hope that it will be useful,
19756+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19757+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19758+ * GNU General Public License for more details.
19759+ *
19760+ * You should have received a copy of the GNU General Public License
19761+ * along with this program; if not, write to the Free Software
19762+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19763+ */
19764+
19765+/*
19766+ * sub-routines for VFS
19767+ */
19768+
dece6358
AM
19769+#include <linux/namei.h>
19770+#include <linux/security.h>
19771+#include <linux/splice.h>
1facf9fc 19772+#include <linux/uaccess.h>
19773+#include "aufs.h"
19774+
19775+int vfsub_update_h_iattr(struct path *h_path, int *did)
19776+{
19777+ int err;
19778+ struct kstat st;
19779+ struct super_block *h_sb;
19780+
19781+ /* for remote fs, leave work for its getattr or d_revalidate */
19782+ /* for bad i_attr fs, handle them in aufs_getattr() */
19783+ /* still some fs may acquire i_mutex. we need to skip them */
19784+ err = 0;
19785+ if (!did)
19786+ did = &err;
19787+ h_sb = h_path->dentry->d_sb;
19788+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
19789+ if (*did)
19790+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
19791+
19792+ return err;
19793+}
19794+
19795+/* ---------------------------------------------------------------------- */
19796+
19797+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
19798+{
19799+ struct file *file;
19800+
19801+ lockdep_off();
19802+ file = filp_open(path, oflags, mode);
19803+ lockdep_on();
19804+ if (IS_ERR(file))
19805+ goto out;
19806+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
19807+
19808+ out:
19809+ return file;
19810+}
19811+
19812+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
19813+{
19814+ int err;
19815+
19816+ /* lockdep_off(); */
19817+ err = kern_path(name, flags, path);
19818+ /* lockdep_on(); */
19819+ if (!err && path->dentry->d_inode)
19820+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
19821+ return err;
19822+}
19823+
19824+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
19825+ int len)
19826+{
19827+ struct path path = {
19828+ .mnt = NULL
19829+ };
19830+
19831+ IMustLock(parent->d_inode);
19832+
19833+ path.dentry = lookup_one_len(name, parent, len);
19834+ if (IS_ERR(path.dentry))
19835+ goto out;
19836+ if (path.dentry->d_inode)
19837+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
19838+
19839+ out:
19840+ return path.dentry;
19841+}
19842+
19843+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
19844+{
19845+ struct path path = {
19846+ .mnt = nd->path.mnt
19847+ };
19848+
19849+ IMustLock(nd->path.dentry->d_inode);
19850+
19851+ path.dentry = lookup_hash(nd);
19852+ if (!IS_ERR(path.dentry) && path.dentry->d_inode)
19853+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
19854+
19855+ return path.dentry;
19856+}
19857+
19858+/* ---------------------------------------------------------------------- */
19859+
19860+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
19861+ struct dentry *d2, struct au_hinode *hdir2)
19862+{
19863+ struct dentry *d;
19864+
19865+ lockdep_off();
19866+ d = lock_rename(d1, d2);
19867+ lockdep_on();
19868+ au_hin_suspend(hdir1);
19869+ if (hdir1 != hdir2)
19870+ au_hin_suspend(hdir2);
19871+
19872+ return d;
19873+}
19874+
19875+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
19876+ struct dentry *d2, struct au_hinode *hdir2)
19877+{
19878+ au_hin_resume(hdir1);
19879+ if (hdir1 != hdir2)
19880+ au_hin_resume(hdir2);
19881+ lockdep_off();
19882+ unlock_rename(d1, d2);
19883+ lockdep_on();
19884+}
19885+
19886+/* ---------------------------------------------------------------------- */
19887+
19888+int vfsub_create(struct inode *dir, struct path *path, int mode)
19889+{
19890+ int err;
19891+ struct dentry *d;
19892+
19893+ IMustLock(dir);
19894+
19895+ d = path->dentry;
19896+ path->dentry = d->d_parent;
19897+ err = security_path_mknod(path, path->dentry, mode, 0);
19898+ path->dentry = d;
19899+ if (unlikely(err))
19900+ goto out;
19901+
19902+ if (au_test_fs_null_nd(dir->i_sb))
19903+ err = vfs_create(dir, path->dentry, mode, NULL);
19904+ else {
19905+ struct nameidata h_nd;
19906+
19907+ memset(&h_nd, 0, sizeof(h_nd));
19908+ h_nd.flags = LOOKUP_CREATE;
19909+ h_nd.intent.open.flags = O_CREAT
19910+ | vfsub_fmode_to_uint(FMODE_READ);
19911+ h_nd.intent.open.create_mode = mode;
19912+ h_nd.path.dentry = path->dentry->d_parent;
19913+ h_nd.path.mnt = path->mnt;
19914+ path_get(&h_nd.path);
19915+ err = vfs_create(dir, path->dentry, mode, &h_nd);
19916+ path_put(&h_nd.path);
19917+ }
19918+
19919+ if (!err) {
19920+ struct path tmp = *path;
19921+ int did;
19922+
19923+ vfsub_update_h_iattr(&tmp, &did);
19924+ if (did) {
19925+ tmp.dentry = path->dentry->d_parent;
19926+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
19927+ }
19928+ /*ignore*/
19929+ }
19930+
19931+ out:
19932+ return err;
19933+}
19934+
19935+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
19936+{
19937+ int err;
19938+ struct dentry *d;
19939+
19940+ IMustLock(dir);
19941+
19942+ d = path->dentry;
19943+ path->dentry = d->d_parent;
19944+ err = security_path_symlink(path, path->dentry, symname);
19945+ path->dentry = d;
19946+ if (unlikely(err))
19947+ goto out;
19948+
19949+ err = vfs_symlink(dir, path->dentry, symname);
19950+ if (!err) {
19951+ struct path tmp = *path;
19952+ int did;
19953+
19954+ vfsub_update_h_iattr(&tmp, &did);
19955+ if (did) {
19956+ tmp.dentry = path->dentry->d_parent;
19957+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
19958+ }
19959+ /*ignore*/
19960+ }
19961+
19962+ out:
19963+ return err;
19964+}
19965+
19966+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
19967+{
19968+ int err;
19969+ struct dentry *d;
19970+
19971+ IMustLock(dir);
19972+
19973+ d = path->dentry;
19974+ path->dentry = d->d_parent;
19975+ err = security_path_mknod(path, path->dentry, mode, dev);
19976+ path->dentry = d;
19977+ if (unlikely(err))
19978+ goto out;
19979+
19980+ err = vfs_mknod(dir, path->dentry, mode, dev);
19981+ if (!err) {
19982+ struct path tmp = *path;
19983+ int did;
19984+
19985+ vfsub_update_h_iattr(&tmp, &did);
19986+ if (did) {
19987+ tmp.dentry = path->dentry->d_parent;
19988+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
19989+ }
19990+ /*ignore*/
19991+ }
19992+
19993+ out:
19994+ return err;
19995+}
19996+
19997+static int au_test_nlink(struct inode *inode)
19998+{
19999+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
20000+
20001+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
20002+ || inode->i_nlink < link_max)
20003+ return 0;
20004+ return -EMLINK;
20005+}
20006+
20007+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
20008+{
20009+ int err;
20010+ struct dentry *d;
20011+
20012+ IMustLock(dir);
20013+
20014+ err = au_test_nlink(src_dentry->d_inode);
20015+ if (unlikely(err))
20016+ return err;
20017+
20018+ d = path->dentry;
20019+ path->dentry = d->d_parent;
20020+ err = security_path_link(src_dentry, path, path->dentry);
20021+ path->dentry = d;
20022+ if (unlikely(err))
20023+ goto out;
20024+
20025+ lockdep_off();
20026+ err = vfs_link(src_dentry, dir, path->dentry);
20027+ lockdep_on();
20028+ if (!err) {
20029+ struct path tmp = *path;
20030+ int did;
20031+
20032+ /* fuse has different memory inode for the same inumber */
20033+ vfsub_update_h_iattr(&tmp, &did);
20034+ if (did) {
20035+ tmp.dentry = path->dentry->d_parent;
20036+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
20037+ tmp.dentry = src_dentry;
20038+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
20039+ }
20040+ /*ignore*/
20041+ }
20042+
20043+ out:
20044+ return err;
20045+}
20046+
20047+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
20048+ struct inode *dir, struct path *path)
20049+{
20050+ int err;
20051+ struct path tmp = {
20052+ .mnt = path->mnt
20053+ };
20054+ struct dentry *d;
20055+
20056+ IMustLock(dir);
20057+ IMustLock(src_dir);
20058+
20059+ d = path->dentry;
20060+ path->dentry = d->d_parent;
20061+ tmp.dentry = src_dentry->d_parent;
20062+ err = security_path_rename(&tmp, src_dentry, path, path->dentry);
20063+ path->dentry = d;
20064+ if (unlikely(err))
20065+ goto out;
20066+
20067+ lockdep_off();
20068+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
20069+ lockdep_on();
20070+ if (!err) {
20071+ int did;
20072+
20073+ tmp.dentry = d->d_parent;
20074+ vfsub_update_h_iattr(&tmp, &did);
20075+ if (did) {
20076+ tmp.dentry = src_dentry;
20077+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
20078+ tmp.dentry = src_dentry->d_parent;
20079+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
20080+ }
20081+ /*ignore*/
20082+ }
20083+
20084+ out:
20085+ return err;
20086+}
20087+
20088+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
20089+{
20090+ int err;
20091+ struct dentry *d;
20092+
20093+ IMustLock(dir);
20094+
20095+ d = path->dentry;
20096+ path->dentry = d->d_parent;
20097+ err = security_path_mkdir(path, path->dentry, mode);
20098+ path->dentry = d;
20099+ if (unlikely(err))
20100+ goto out;
20101+
20102+ err = vfs_mkdir(dir, path->dentry, mode);
20103+ if (!err) {
20104+ struct path tmp = *path;
20105+ int did;
20106+
20107+ vfsub_update_h_iattr(&tmp, &did);
20108+ if (did) {
20109+ tmp.dentry = path->dentry->d_parent;
20110+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
20111+ }
20112+ /*ignore*/
20113+ }
20114+
20115+ out:
20116+ return err;
20117+}
20118+
20119+int vfsub_rmdir(struct inode *dir, struct path *path)
20120+{
20121+ int err;
20122+ struct dentry *d;
20123+
20124+ IMustLock(dir);
20125+
20126+ d = path->dentry;
20127+ path->dentry = d->d_parent;
20128+ err = security_path_rmdir(path, path->dentry);
20129+ path->dentry = d;
20130+ if (unlikely(err))
20131+ goto out;
20132+
20133+ lockdep_off();
20134+ err = vfs_rmdir(dir, path->dentry);
20135+ lockdep_on();
20136+ if (!err) {
20137+ struct path tmp = {
20138+ .dentry = path->dentry->d_parent,
20139+ .mnt = path->mnt
20140+ };
20141+
20142+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
20143+ }
20144+
20145+ out:
20146+ return err;
20147+}
20148+
20149+/* ---------------------------------------------------------------------- */
20150+
20151+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
20152+ loff_t *ppos)
20153+{
20154+ ssize_t err;
20155+
20156+ err = vfs_read(file, ubuf, count, ppos);
20157+ if (err >= 0)
20158+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
20159+ return err;
20160+}
20161+
20162+/* todo: kernel_read()? */
20163+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
20164+ loff_t *ppos)
20165+{
20166+ ssize_t err;
20167+ mm_segment_t oldfs;
20168+
20169+ oldfs = get_fs();
20170+ set_fs(KERNEL_DS);
20171+ err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
20172+ set_fs(oldfs);
20173+ return err;
20174+}
20175+
20176+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
20177+ loff_t *ppos)
20178+{
20179+ ssize_t err;
20180+
20181+ lockdep_off();
20182+ err = vfs_write(file, ubuf, count, ppos);
20183+ lockdep_on();
20184+ if (err >= 0)
20185+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
20186+ return err;
20187+}
20188+
20189+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
20190+{
20191+ ssize_t err;
20192+ mm_segment_t oldfs;
20193+
20194+ oldfs = get_fs();
20195+ set_fs(KERNEL_DS);
20196+ err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
20197+ set_fs(oldfs);
20198+ return err;
20199+}
20200+
20201+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
20202+{
20203+ int err;
20204+
20205+ lockdep_off();
20206+ err = vfs_readdir(file, filldir, arg);
20207+ lockdep_on();
20208+ if (err >= 0)
20209+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
20210+ return err;
20211+}
20212+
20213+long vfsub_splice_to(struct file *in, loff_t *ppos,
20214+ struct pipe_inode_info *pipe, size_t len,
20215+ unsigned int flags)
20216+{
20217+ long err;
20218+
20219+ lockdep_off();
0fc653ad 20220+ err = do_splice_to(in, ppos, pipe, len, flags);
1facf9fc 20221+ lockdep_on();
20222+ if (err >= 0)
20223+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
20224+ return err;
20225+}
20226+
20227+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
20228+ loff_t *ppos, size_t len, unsigned int flags)
20229+{
20230+ long err;
20231+
20232+ lockdep_off();
0fc653ad 20233+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 20234+ lockdep_on();
20235+ if (err >= 0)
20236+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
20237+ return err;
20238+}
20239+
20240+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
20241+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
20242+ struct file *h_file)
20243+{
20244+ int err;
20245+ struct inode *h_inode;
20246+
20247+ h_inode = h_path->dentry->d_inode;
20248+ if (!h_file) {
20249+ err = mnt_want_write(h_path->mnt);
20250+ if (err)
20251+ goto out;
20252+ err = inode_permission(h_inode, MAY_WRITE);
20253+ if (err)
20254+ goto out_mnt;
20255+ err = get_write_access(h_inode);
20256+ if (err)
20257+ goto out_mnt;
20258+ err = break_lease(h_inode, vfsub_fmode_to_uint(FMODE_WRITE));
20259+ if (err)
20260+ goto out_inode;
20261+ }
20262+
20263+ err = locks_verify_truncate(h_inode, h_file, length);
20264+ if (!err)
20265+ err = security_path_truncate(h_path, length, attr);
20266+ if (!err) {
20267+ lockdep_off();
20268+ err = do_truncate(h_path->dentry, length, attr, h_file);
20269+ lockdep_on();
20270+ }
20271+
20272+ out_inode:
20273+ if (!h_file)
20274+ put_write_access(h_inode);
20275+ out_mnt:
20276+ if (!h_file)
20277+ mnt_drop_write(h_path->mnt);
20278+ out:
20279+ return err;
20280+}
20281+
20282+/* ---------------------------------------------------------------------- */
20283+
20284+struct au_vfsub_mkdir_args {
20285+ int *errp;
20286+ struct inode *dir;
20287+ struct path *path;
20288+ int mode;
20289+};
20290+
20291+static void au_call_vfsub_mkdir(void *args)
20292+{
20293+ struct au_vfsub_mkdir_args *a = args;
20294+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
20295+}
20296+
20297+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
20298+{
20299+ int err, do_sio, wkq_err;
20300+
20301+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
20302+ if (!do_sio)
20303+ err = vfsub_mkdir(dir, path, mode);
20304+ else {
20305+ struct au_vfsub_mkdir_args args = {
20306+ .errp = &err,
20307+ .dir = dir,
20308+ .path = path,
20309+ .mode = mode
20310+ };
20311+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
20312+ if (unlikely(wkq_err))
20313+ err = wkq_err;
20314+ }
20315+
20316+ return err;
20317+}
20318+
20319+struct au_vfsub_rmdir_args {
20320+ int *errp;
20321+ struct inode *dir;
20322+ struct path *path;
20323+};
20324+
20325+static void au_call_vfsub_rmdir(void *args)
20326+{
20327+ struct au_vfsub_rmdir_args *a = args;
20328+ *a->errp = vfsub_rmdir(a->dir, a->path);
20329+}
20330+
20331+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
20332+{
20333+ int err, do_sio, wkq_err;
20334+
20335+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
20336+ if (!do_sio)
20337+ err = vfsub_rmdir(dir, path);
20338+ else {
20339+ struct au_vfsub_rmdir_args args = {
20340+ .errp = &err,
20341+ .dir = dir,
20342+ .path = path
20343+ };
20344+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
20345+ if (unlikely(wkq_err))
20346+ err = wkq_err;
20347+ }
20348+
20349+ return err;
20350+}
20351+
20352+/* ---------------------------------------------------------------------- */
20353+
20354+struct notify_change_args {
20355+ int *errp;
20356+ struct path *path;
20357+ struct iattr *ia;
20358+};
20359+
20360+static void call_notify_change(void *args)
20361+{
20362+ struct notify_change_args *a = args;
20363+ struct inode *h_inode;
20364+
20365+ h_inode = a->path->dentry->d_inode;
20366+ IMustLock(h_inode);
20367+
20368+ *a->errp = -EPERM;
20369+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
20370+ lockdep_off();
20371+ *a->errp = notify_change(a->path->dentry, a->ia);
20372+ lockdep_on();
20373+ if (!*a->errp)
20374+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
20375+ }
20376+ AuTraceErr(*a->errp);
20377+}
20378+
20379+int vfsub_notify_change(struct path *path, struct iattr *ia)
20380+{
20381+ int err;
20382+ struct notify_change_args args = {
20383+ .errp = &err,
20384+ .path = path,
20385+ .ia = ia
20386+ };
20387+
20388+ call_notify_change(&args);
20389+
20390+ return err;
20391+}
20392+
20393+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
20394+{
20395+ int err, wkq_err;
20396+ struct notify_change_args args = {
20397+ .errp = &err,
20398+ .path = path,
20399+ .ia = ia
20400+ };
20401+
20402+ wkq_err = au_wkq_wait(call_notify_change, &args);
20403+ if (unlikely(wkq_err))
20404+ err = wkq_err;
20405+
20406+ return err;
20407+}
20408+
20409+/* ---------------------------------------------------------------------- */
20410+
20411+struct unlink_args {
20412+ int *errp;
20413+ struct inode *dir;
20414+ struct path *path;
20415+};
20416+
20417+static void call_unlink(void *args)
20418+{
20419+ struct unlink_args *a = args;
20420+ struct dentry *d = a->path->dentry;
20421+ struct inode *h_inode;
20422+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
20423+ && atomic_read(&d->d_count) == 1);
20424+
20425+ IMustLock(a->dir);
20426+
20427+ a->path->dentry = d->d_parent;
20428+ *a->errp = security_path_unlink(a->path, d);
20429+ a->path->dentry = d;
20430+ if (unlikely(*a->errp))
20431+ return;
20432+
20433+ if (!stop_sillyrename)
20434+ dget(d);
20435+ h_inode = d->d_inode;
20436+ if (h_inode)
20437+ atomic_inc(&h_inode->i_count);
20438+
20439+ lockdep_off();
20440+ *a->errp = vfs_unlink(a->dir, d);
20441+ lockdep_on();
20442+ if (!*a->errp) {
20443+ struct path tmp = {
20444+ .dentry = d->d_parent,
20445+ .mnt = a->path->mnt
20446+ };
20447+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
20448+ }
20449+
20450+ if (!stop_sillyrename)
20451+ dput(d);
20452+ if (h_inode)
20453+ iput(h_inode);
20454+
20455+ AuTraceErr(*a->errp);
20456+}
20457+
20458+/*
20459+ * @dir: must be locked.
20460+ * @dentry: target dentry.
20461+ */
20462+int vfsub_unlink(struct inode *dir, struct path *path, int force)
20463+{
20464+ int err;
20465+ struct unlink_args args = {
20466+ .errp = &err,
20467+ .dir = dir,
20468+ .path = path
20469+ };
20470+
20471+ if (!force)
20472+ call_unlink(&args);
20473+ else {
20474+ int wkq_err;
20475+
20476+ wkq_err = au_wkq_wait(call_unlink, &args);
20477+ if (unlikely(wkq_err))
20478+ err = wkq_err;
20479+ }
20480+
20481+ return err;
20482+}
dece6358
AM
20483diff -urN linux-2.6.30.org/fs/aufs/vfsub.h linux-2.6.30/fs/aufs/vfsub.h
20484--- linux-2.6.30.org/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
20485+++ linux-2.6.30/fs/aufs/vfsub.h 2009-07-21 08:54:19.000000000 +0200
20486@@ -0,0 +1,172 @@
1facf9fc 20487+/*
20488+ * Copyright (C) 2005-2009 Junjiro R. Okajima
20489+ *
20490+ * This program, aufs is free software; you can redistribute it and/or modify
20491+ * it under the terms of the GNU General Public License as published by
20492+ * the Free Software Foundation; either version 2 of the License, or
20493+ * (at your option) any later version.
dece6358
AM
20494+ *
20495+ * This program is distributed in the hope that it will be useful,
20496+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20497+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20498+ * GNU General Public License for more details.
20499+ *
20500+ * You should have received a copy of the GNU General Public License
20501+ * along with this program; if not, write to the Free Software
20502+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20503+ */
20504+
20505+/*
20506+ * sub-routines for VFS
20507+ */
20508+
20509+#ifndef __AUFS_VFSUB_H__
20510+#define __AUFS_VFSUB_H__
20511+
20512+#ifdef __KERNEL__
20513+
20514+#include <linux/fs.h>
20515+#include <linux/fs_stack.h>
1facf9fc 20516+
20517+/* ---------------------------------------------------------------------- */
20518+
20519+/* lock subclass for lower inode */
20520+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
20521+/* reduce? gave up. */
20522+enum {
20523+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
20524+ AuLsc_I_PARENT, /* lower inode, parent first */
20525+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 20526+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 20527+ AuLsc_I_CHILD,
20528+ AuLsc_I_CHILD2,
20529+ AuLsc_I_End
20530+};
20531+
20532+/* to debug easier, do not make them inlined functions */
20533+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
20534+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
20535+
20536+/* ---------------------------------------------------------------------- */
20537+
20538+static inline void vfsub_copy_inode_size(struct inode *inode,
20539+ struct inode *h_inode)
20540+{
20541+ spin_lock(&inode->i_lock);
20542+ fsstack_copy_inode_size(inode, h_inode);
20543+ spin_unlock(&inode->i_lock);
20544+}
20545+
20546+int vfsub_update_h_iattr(struct path *h_path, int *did);
20547+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
20548+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
20549+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
20550+ int len);
20551+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
20552+
20553+/* ---------------------------------------------------------------------- */
20554+
20555+struct au_hinode;
20556+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
20557+ struct dentry *d2, struct au_hinode *hdir2);
20558+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
20559+ struct dentry *d2, struct au_hinode *hdir2);
20560+
20561+int vfsub_create(struct inode *dir, struct path *path, int mode);
20562+int vfsub_symlink(struct inode *dir, struct path *path,
20563+ const char *symname);
20564+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
20565+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
20566+ struct path *path);
20567+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
20568+ struct inode *hdir, struct path *path);
20569+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
20570+int vfsub_rmdir(struct inode *dir, struct path *path);
20571+
20572+/* ---------------------------------------------------------------------- */
20573+
20574+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
20575+ loff_t *ppos);
20576+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
20577+ loff_t *ppos);
20578+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
20579+ loff_t *ppos);
20580+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
20581+ loff_t *ppos);
20582+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
20583+
20584+static inline void vfsub_file_accessed(struct file *h_file)
20585+{
20586+ file_accessed(h_file);
20587+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
20588+}
20589+
20590+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
20591+ struct dentry *h_dentry)
20592+{
20593+ struct path h_path = {
20594+ .dentry = h_dentry,
20595+ .mnt = h_mnt
20596+ };
20597+ touch_atime(h_mnt, h_dentry);
20598+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
20599+}
20600+
20601+long vfsub_splice_to(struct file *in, loff_t *ppos,
20602+ struct pipe_inode_info *pipe, size_t len,
20603+ unsigned int flags);
20604+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
20605+ loff_t *ppos, size_t len, unsigned int flags);
20606+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
20607+ struct file *h_file);
20608+
20609+/* ---------------------------------------------------------------------- */
20610+
20611+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
20612+{
20613+ loff_t err;
20614+
20615+ lockdep_off();
20616+ err = vfs_llseek(file, offset, origin);
20617+ lockdep_on();
20618+ return err;
20619+}
20620+
20621+/* ---------------------------------------------------------------------- */
20622+
20623+/* dirty workaround for strict type of fmode_t */
20624+union vfsub_fmu {
20625+ fmode_t fm;
20626+ unsigned int ui;
20627+};
20628+
20629+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
20630+{
20631+ union vfsub_fmu u = {
20632+ .fm = fm
20633+ };
20634+
20635+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
20636+
20637+ return u.ui;
20638+}
20639+
20640+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
20641+{
20642+ union vfsub_fmu u = {
20643+ .ui = ui
20644+ };
20645+
20646+ return u.fm;
20647+}
20648+
20649+/* ---------------------------------------------------------------------- */
20650+
20651+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
20652+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
20653+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
20654+int vfsub_notify_change(struct path *path, struct iattr *ia);
20655+int vfsub_unlink(struct inode *dir, struct path *path, int force);
20656+
20657+#endif /* __KERNEL__ */
20658+#endif /* __AUFS_VFSUB_H__ */
dece6358
AM
20659diff -urN linux-2.6.30.org/fs/aufs/wbr_policy.c linux-2.6.30/fs/aufs/wbr_policy.c
20660--- linux-2.6.30.org/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
20661+++ linux-2.6.30/fs/aufs/wbr_policy.c 2009-07-21 08:54:19.000000000 +0200
20662@@ -0,0 +1,641 @@
1facf9fc 20663+/*
20664+ * Copyright (C) 2005-2009 Junjiro R. Okajima
20665+ *
20666+ * This program, aufs is free software; you can redistribute it and/or modify
20667+ * it under the terms of the GNU General Public License as published by
20668+ * the Free Software Foundation; either version 2 of the License, or
20669+ * (at your option) any later version.
dece6358
AM
20670+ *
20671+ * This program is distributed in the hope that it will be useful,
20672+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20673+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20674+ * GNU General Public License for more details.
20675+ *
20676+ * You should have received a copy of the GNU General Public License
20677+ * along with this program; if not, write to the Free Software
20678+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20679+ */
20680+
20681+/*
20682+ * policies for selecting one among multiple writable branches
20683+ */
20684+
20685+#include <linux/statfs.h>
20686+#include "aufs.h"
20687+
20688+/* subset of cpup_attr() */
20689+static noinline_for_stack
20690+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
20691+{
20692+ int err, sbits;
20693+ struct iattr ia;
20694+ struct inode *h_isrc;
20695+
20696+ h_isrc = h_src->d_inode;
20697+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
20698+ ia.ia_mode = h_isrc->i_mode;
20699+ ia.ia_uid = h_isrc->i_uid;
20700+ ia.ia_gid = h_isrc->i_gid;
20701+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
20702+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
20703+ err = vfsub_sio_notify_change(h_path, &ia);
20704+
20705+ /* is this nfs only? */
20706+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
20707+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
20708+ ia.ia_mode = h_isrc->i_mode;
20709+ err = vfsub_sio_notify_change(h_path, &ia);
20710+ }
20711+
20712+ return err;
20713+}
20714+
20715+#define AuCpdown_PARENT_OPQ 1
20716+#define AuCpdown_WHED (1 << 1)
20717+#define AuCpdown_MADE_DIR (1 << 2)
20718+#define AuCpdown_DIROPQ (1 << 3)
20719+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
20720+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
20721+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
20722+
20723+struct au_cpdown_dir_args {
20724+ struct dentry *parent;
20725+ unsigned int flags;
20726+};
20727+
20728+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
20729+ struct au_cpdown_dir_args *a)
20730+{
20731+ int err;
20732+ struct dentry *opq_dentry;
20733+
20734+ opq_dentry = au_diropq_create(dentry, bdst);
20735+ err = PTR_ERR(opq_dentry);
20736+ if (IS_ERR(opq_dentry))
20737+ goto out;
20738+ dput(opq_dentry);
20739+ au_fset_cpdown(a->flags, DIROPQ);
20740+
20741+ out:
20742+ return err;
20743+}
20744+
20745+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
20746+ struct inode *dir, aufs_bindex_t bdst)
20747+{
20748+ int err;
20749+ struct path h_path;
20750+ struct au_branch *br;
20751+
20752+ br = au_sbr(dentry->d_sb, bdst);
20753+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
20754+ err = PTR_ERR(h_path.dentry);
20755+ if (IS_ERR(h_path.dentry))
20756+ goto out;
20757+
20758+ err = 0;
20759+ if (h_path.dentry->d_inode) {
20760+ h_path.mnt = br->br_mnt;
20761+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
20762+ dentry);
20763+ }
20764+ dput(h_path.dentry);
20765+
20766+ out:
20767+ return err;
20768+}
20769+
20770+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
20771+ struct dentry *h_parent, void *arg)
20772+{
20773+ int err, rerr;
20774+ aufs_bindex_t bend, bopq, bstart;
20775+ unsigned char parent_opq;
20776+ struct path h_path;
20777+ struct dentry *parent;
20778+ struct inode *h_dir, *h_inode, *inode, *dir;
20779+ struct au_cpdown_dir_args *args = arg;
20780+
20781+ bstart = au_dbstart(dentry);
20782+ /* dentry is di-locked */
20783+ parent = dget_parent(dentry);
20784+ dir = parent->d_inode;
20785+ h_dir = h_parent->d_inode;
20786+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
20787+ IMustLock(h_dir);
20788+
20789+ err = au_lkup_neg(dentry, bdst);
20790+ if (unlikely(err < 0))
20791+ goto out;
20792+ h_path.dentry = au_h_dptr(dentry, bdst);
20793+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
20794+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
20795+ S_IRWXU | S_IRUGO | S_IXUGO);
20796+ if (unlikely(err))
20797+ goto out_put;
20798+ au_fset_cpdown(args->flags, MADE_DIR);
20799+
20800+ bend = au_dbend(dentry);
20801+ bopq = au_dbdiropq(dentry);
20802+ au_fclr_cpdown(args->flags, WHED);
20803+ au_fclr_cpdown(args->flags, DIROPQ);
20804+ if (au_dbwh(dentry) == bdst)
20805+ au_fset_cpdown(args->flags, WHED);
20806+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
20807+ au_fset_cpdown(args->flags, PARENT_OPQ);
20808+ parent_opq = (au_ftest_cpdown(args->flags, PARENT_OPQ)
20809+ && args->parent == dentry);
20810+ h_inode = h_path.dentry->d_inode;
20811+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
20812+ if (au_ftest_cpdown(args->flags, WHED)) {
20813+ err = au_cpdown_dir_opq(dentry, bdst, args);
20814+ if (unlikely(err)) {
20815+ mutex_unlock(&h_inode->i_mutex);
20816+ goto out_dir;
20817+ }
20818+ }
20819+
20820+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
20821+ mutex_unlock(&h_inode->i_mutex);
20822+ if (unlikely(err))
20823+ goto out_opq;
20824+
20825+ if (au_ftest_cpdown(args->flags, WHED)) {
20826+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
20827+ if (unlikely(err))
20828+ goto out_opq;
20829+ }
20830+
20831+ inode = dentry->d_inode;
20832+ if (au_ibend(inode) < bdst)
20833+ au_set_ibend(inode, bdst);
20834+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
20835+ au_hi_flags(inode, /*isdir*/1));
20836+ goto out; /* success */
20837+
20838+ /* revert */
20839+ out_opq:
20840+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
20841+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
20842+ rerr = au_diropq_remove(dentry, bdst);
20843+ mutex_unlock(&h_inode->i_mutex);
20844+ if (unlikely(rerr)) {
20845+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
20846+ AuDLNPair(dentry), bdst, rerr);
20847+ err = -EIO;
20848+ goto out;
20849+ }
20850+ }
20851+ out_dir:
20852+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
20853+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
20854+ if (unlikely(rerr)) {
20855+ AuIOErr("failed removing %.*s b%d (%d)\n",
20856+ AuDLNPair(dentry), bdst, rerr);
20857+ err = -EIO;
20858+ }
20859+ }
20860+ out_put:
20861+ au_set_h_dptr(dentry, bdst, NULL);
20862+ if (au_dbend(dentry) == bdst)
20863+ au_update_dbend(dentry);
20864+ out:
20865+ dput(parent);
20866+ return err;
20867+}
20868+
20869+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
20870+{
20871+ int err;
20872+ struct au_cpdown_dir_args args = {
20873+ .parent = dget_parent(dentry),
20874+ .flags = 0
20875+ };
20876+
20877+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
20878+ dput(args.parent);
20879+
20880+ return err;
20881+}
20882+
20883+/* ---------------------------------------------------------------------- */
20884+
20885+/* policies for create */
20886+
20887+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
20888+{
20889+ for (; bindex >= 0; bindex--)
20890+ if (!au_br_rdonly(au_sbr(sb, bindex)))
20891+ return bindex;
20892+ return -EROFS;
20893+}
20894+
20895+/* top down parent */
20896+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
20897+{
20898+ int err;
20899+ aufs_bindex_t bstart, bindex;
20900+ struct super_block *sb;
20901+ struct dentry *parent, *h_parent;
20902+
20903+ sb = dentry->d_sb;
20904+ bstart = au_dbstart(dentry);
20905+ err = bstart;
20906+ if (!au_br_rdonly(au_sbr(sb, bstart)))
20907+ goto out;
20908+
20909+ err = -EROFS;
20910+ parent = dget_parent(dentry);
20911+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
20912+ h_parent = au_h_dptr(parent, bindex);
20913+ if (!h_parent || !h_parent->d_inode)
20914+ continue;
20915+
20916+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
20917+ err = bindex;
20918+ break;
20919+ }
20920+ }
20921+ dput(parent);
20922+
20923+ /* bottom up here */
20924+ if (unlikely(err < 0))
20925+ err = au_wbr_bu(sb, bstart - 1);
20926+
20927+ out:
20928+ AuDbg("b%d\n", err);
20929+ return err;
20930+}
20931+
20932+/* ---------------------------------------------------------------------- */
20933+
20934+/* an exception for the policy other than tdp */
20935+static int au_wbr_create_exp(struct dentry *dentry)
20936+{
20937+ int err;
20938+ aufs_bindex_t bwh, bdiropq;
20939+ struct dentry *parent;
20940+
20941+ err = -1;
20942+ bwh = au_dbwh(dentry);
20943+ parent = dget_parent(dentry);
20944+ bdiropq = au_dbdiropq(parent);
20945+ if (bwh >= 0) {
20946+ if (bdiropq >= 0)
20947+ err = min(bdiropq, bwh);
20948+ else
20949+ err = bwh;
20950+ AuDbg("%d\n", err);
20951+ } else if (bdiropq >= 0) {
20952+ err = bdiropq;
20953+ AuDbg("%d\n", err);
20954+ }
20955+ dput(parent);
20956+
20957+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
20958+ err = -1;
20959+
20960+ AuDbg("%d\n", err);
20961+ return err;
20962+}
20963+
20964+/* ---------------------------------------------------------------------- */
20965+
20966+/* round robin */
20967+static int au_wbr_create_init_rr(struct super_block *sb)
20968+{
20969+ int err;
20970+
20971+ err = au_wbr_bu(sb, au_sbend(sb));
20972+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 20973+ /* smp_mb(); */
1facf9fc 20974+
20975+ AuDbg("b%d\n", err);
20976+ return err;
20977+}
20978+
20979+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
20980+{
20981+ int err, nbr;
20982+ unsigned int u;
20983+ aufs_bindex_t bindex, bend;
20984+ struct super_block *sb;
20985+ atomic_t *next;
20986+
20987+ err = au_wbr_create_exp(dentry);
20988+ if (err >= 0)
20989+ goto out;
20990+
20991+ sb = dentry->d_sb;
20992+ next = &au_sbi(sb)->si_wbr_rr_next;
20993+ bend = au_sbend(sb);
20994+ nbr = bend + 1;
20995+ for (bindex = 0; bindex <= bend; bindex++) {
20996+ if (!isdir) {
20997+ err = atomic_dec_return(next) + 1;
20998+ /* modulo for 0 is meaningless */
20999+ if (unlikely(!err))
21000+ err = atomic_dec_return(next) + 1;
21001+ } else
21002+ err = atomic_read(next);
21003+ AuDbg("%d\n", err);
21004+ u = err;
21005+ err = u % nbr;
21006+ AuDbg("%d\n", err);
21007+ if (!au_br_rdonly(au_sbr(sb, err)))
21008+ break;
21009+ err = -EROFS;
21010+ }
21011+
21012+ out:
21013+ AuDbg("%d\n", err);
21014+ return err;
21015+}
21016+
21017+/* ---------------------------------------------------------------------- */
21018+
21019+/* most free space */
21020+static void au_mfs(struct dentry *dentry)
21021+{
21022+ struct super_block *sb;
21023+ struct au_branch *br;
21024+ struct au_wbr_mfs *mfs;
21025+ aufs_bindex_t bindex, bend;
21026+ int err;
21027+ unsigned long long b, bavail;
21028+ /* reduce the stack usage */
21029+ struct kstatfs *st;
21030+
21031+ st = kmalloc(sizeof(*st), GFP_NOFS);
21032+ if (unlikely(!st)) {
21033+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
21034+ return;
21035+ }
21036+
21037+ bavail = 0;
21038+ sb = dentry->d_sb;
21039+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 21040+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 21041+ mfs->mfs_bindex = -EROFS;
21042+ mfs->mfsrr_bytes = 0;
21043+ bend = au_sbend(sb);
21044+ for (bindex = 0; bindex <= bend; bindex++) {
21045+ br = au_sbr(sb, bindex);
21046+ if (au_br_rdonly(br))
21047+ continue;
21048+
21049+ /* sb->s_root for NFS is unreliable */
21050+ err = vfs_statfs(br->br_mnt->mnt_root, st);
21051+ if (unlikely(err)) {
21052+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
21053+ continue;
21054+ }
21055+
21056+ /* when the available size is equal, select the lower one */
21057+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
21058+ || sizeof(b) < sizeof(st->f_bsize));
21059+ b = st->f_bavail * st->f_bsize;
21060+ br->br_wbr->wbr_bytes = b;
21061+ if (b >= bavail) {
21062+ bavail = b;
21063+ mfs->mfs_bindex = bindex;
21064+ mfs->mfs_jiffy = jiffies;
21065+ }
21066+ }
21067+
21068+ mfs->mfsrr_bytes = bavail;
21069+ AuDbg("b%d\n", mfs->mfs_bindex);
21070+ kfree(st);
21071+}
21072+
21073+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
21074+{
21075+ int err;
21076+ struct super_block *sb;
21077+ struct au_wbr_mfs *mfs;
21078+
21079+ err = au_wbr_create_exp(dentry);
21080+ if (err >= 0)
21081+ goto out;
21082+
21083+ sb = dentry->d_sb;
21084+ mfs = &au_sbi(sb)->si_wbr_mfs;
21085+ mutex_lock(&mfs->mfs_lock);
21086+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
21087+ || mfs->mfs_bindex < 0
21088+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
21089+ au_mfs(dentry);
21090+ mutex_unlock(&mfs->mfs_lock);
21091+ err = mfs->mfs_bindex;
21092+
21093+ out:
21094+ AuDbg("b%d\n", err);
21095+ return err;
21096+}
21097+
21098+static int au_wbr_create_init_mfs(struct super_block *sb)
21099+{
21100+ struct au_wbr_mfs *mfs;
21101+
21102+ mfs = &au_sbi(sb)->si_wbr_mfs;
21103+ mutex_init(&mfs->mfs_lock);
21104+ mfs->mfs_jiffy = 0;
21105+ mfs->mfs_bindex = -EROFS;
21106+
21107+ return 0;
21108+}
21109+
21110+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
21111+{
21112+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
21113+ return 0;
21114+}
21115+
21116+/* ---------------------------------------------------------------------- */
21117+
21118+/* most free space and then round robin */
21119+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
21120+{
21121+ int err;
21122+ struct au_wbr_mfs *mfs;
21123+
21124+ err = au_wbr_create_mfs(dentry, isdir);
21125+ if (err >= 0) {
21126+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 21127+ mutex_lock(&mfs->mfs_lock);
1facf9fc 21128+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
21129+ err = au_wbr_create_rr(dentry, isdir);
dece6358 21130+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 21131+ }
21132+
21133+ AuDbg("b%d\n", err);
21134+ return err;
21135+}
21136+
21137+static int au_wbr_create_init_mfsrr(struct super_block *sb)
21138+{
21139+ int err;
21140+
21141+ au_wbr_create_init_mfs(sb); /* ignore */
21142+ err = au_wbr_create_init_rr(sb);
21143+
21144+ return err;
21145+}
21146+
21147+/* ---------------------------------------------------------------------- */
21148+
21149+/* top down parent and most free space */
21150+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
21151+{
21152+ int err, e2;
21153+ unsigned long long b;
21154+ aufs_bindex_t bindex, bstart, bend;
21155+ struct super_block *sb;
21156+ struct dentry *parent, *h_parent;
21157+ struct au_branch *br;
21158+
21159+ err = au_wbr_create_tdp(dentry, isdir);
21160+ if (unlikely(err < 0))
21161+ goto out;
21162+ parent = dget_parent(dentry);
21163+ bstart = au_dbstart(parent);
21164+ bend = au_dbtaildir(parent);
21165+ if (bstart == bend)
21166+ goto out_parent; /* success */
21167+
21168+ e2 = au_wbr_create_mfs(dentry, isdir);
21169+ if (e2 < 0)
21170+ goto out_parent; /* success */
21171+
21172+ /* when the available size is equal, select upper one */
21173+ sb = dentry->d_sb;
21174+ br = au_sbr(sb, err);
21175+ b = br->br_wbr->wbr_bytes;
21176+ AuDbg("b%d, %llu\n", err, b);
21177+
21178+ for (bindex = bstart; bindex <= bend; bindex++) {
21179+ h_parent = au_h_dptr(parent, bindex);
21180+ if (!h_parent || !h_parent->d_inode)
21181+ continue;
21182+
21183+ br = au_sbr(sb, bindex);
21184+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
21185+ b = br->br_wbr->wbr_bytes;
21186+ err = bindex;
21187+ AuDbg("b%d, %llu\n", err, b);
21188+ }
21189+ }
21190+
21191+ out_parent:
21192+ dput(parent);
21193+ out:
21194+ AuDbg("b%d\n", err);
21195+ return err;
21196+}
21197+
21198+/* ---------------------------------------------------------------------- */
21199+
21200+/* policies for copyup */
21201+
21202+/* top down parent */
21203+static int au_wbr_copyup_tdp(struct dentry *dentry)
21204+{
21205+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
21206+}
21207+
21208+/* bottom up parent */
21209+static int au_wbr_copyup_bup(struct dentry *dentry)
21210+{
21211+ int err;
21212+ aufs_bindex_t bindex, bstart;
21213+ struct dentry *parent, *h_parent;
21214+ struct super_block *sb;
21215+
21216+ err = -EROFS;
21217+ sb = dentry->d_sb;
21218+ parent = dget_parent(dentry);
21219+ bstart = au_dbstart(parent);
21220+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
21221+ h_parent = au_h_dptr(parent, bindex);
21222+ if (!h_parent || !h_parent->d_inode)
21223+ continue;
21224+
21225+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
21226+ err = bindex;
21227+ break;
21228+ }
21229+ }
21230+ dput(parent);
21231+
21232+ /* bottom up here */
21233+ if (unlikely(err < 0))
21234+ err = au_wbr_bu(sb, bstart - 1);
21235+
21236+ AuDbg("b%d\n", err);
21237+ return err;
21238+}
21239+
21240+/* bottom up */
21241+static int au_wbr_copyup_bu(struct dentry *dentry)
21242+{
21243+ int err;
21244+
21245+ err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
21246+
21247+ AuDbg("b%d\n", err);
21248+ return err;
21249+}
21250+
21251+/* ---------------------------------------------------------------------- */
21252+
21253+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
21254+ [AuWbrCopyup_TDP] = {
21255+ .copyup = au_wbr_copyup_tdp
21256+ },
21257+ [AuWbrCopyup_BUP] = {
21258+ .copyup = au_wbr_copyup_bup
21259+ },
21260+ [AuWbrCopyup_BU] = {
21261+ .copyup = au_wbr_copyup_bu
21262+ }
21263+};
21264+
21265+struct au_wbr_create_operations au_wbr_create_ops[] = {
21266+ [AuWbrCreate_TDP] = {
21267+ .create = au_wbr_create_tdp
21268+ },
21269+ [AuWbrCreate_RR] = {
21270+ .create = au_wbr_create_rr,
21271+ .init = au_wbr_create_init_rr
21272+ },
21273+ [AuWbrCreate_MFS] = {
21274+ .create = au_wbr_create_mfs,
21275+ .init = au_wbr_create_init_mfs,
21276+ .fin = au_wbr_create_fin_mfs
21277+ },
21278+ [AuWbrCreate_MFSV] = {
21279+ .create = au_wbr_create_mfs,
21280+ .init = au_wbr_create_init_mfs,
21281+ .fin = au_wbr_create_fin_mfs
21282+ },
21283+ [AuWbrCreate_MFSRR] = {
21284+ .create = au_wbr_create_mfsrr,
21285+ .init = au_wbr_create_init_mfsrr,
21286+ .fin = au_wbr_create_fin_mfs
21287+ },
21288+ [AuWbrCreate_MFSRRV] = {
21289+ .create = au_wbr_create_mfsrr,
21290+ .init = au_wbr_create_init_mfsrr,
21291+ .fin = au_wbr_create_fin_mfs
21292+ },
21293+ [AuWbrCreate_PMFS] = {
21294+ .create = au_wbr_create_pmfs,
21295+ .init = au_wbr_create_init_mfs,
21296+ .fin = au_wbr_create_fin_mfs
21297+ },
21298+ [AuWbrCreate_PMFSV] = {
21299+ .create = au_wbr_create_pmfs,
21300+ .init = au_wbr_create_init_mfs,
21301+ .fin = au_wbr_create_fin_mfs
21302+ }
21303+};
dece6358
AM
21304diff -urN linux-2.6.30.org/fs/aufs/whout.c linux-2.6.30/fs/aufs/whout.c
21305--- linux-2.6.30.org/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
21306+++ linux-2.6.30/fs/aufs/whout.c 2009-07-21 08:54:19.000000000 +0200
21307@@ -0,0 +1,1044 @@
1facf9fc 21308+/*
21309+ * Copyright (C) 2005-2009 Junjiro R. Okajima
21310+ *
21311+ * This program, aufs is free software; you can redistribute it and/or modify
21312+ * it under the terms of the GNU General Public License as published by
21313+ * the Free Software Foundation; either version 2 of the License, or
21314+ * (at your option) any later version.
dece6358
AM
21315+ *
21316+ * This program is distributed in the hope that it will be useful,
21317+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21318+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21319+ * GNU General Public License for more details.
21320+ *
21321+ * You should have received a copy of the GNU General Public License
21322+ * along with this program; if not, write to the Free Software
21323+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21324+ */
21325+
21326+/*
21327+ * whiteout for logical deletion and opaque directory
21328+ */
21329+
21330+#include <linux/fs.h>
21331+#include "aufs.h"
21332+
21333+#define WH_MASK S_IRUGO
21334+
21335+/*
21336+ * If a directory contains this file, then it is opaque. We start with the
21337+ * .wh. flag so that it is blocked by lookup.
21338+ */
21339+static struct qstr diropq_name = {
21340+ .name = AUFS_WH_DIROPQ,
21341+ .len = sizeof(AUFS_WH_DIROPQ) - 1
21342+};
21343+
21344+/*
21345+ * generate whiteout name, which is NOT terminated by NULL.
21346+ * @name: original d_name.name
21347+ * @len: original d_name.len
21348+ * @wh: whiteout qstr
21349+ * returns zero when succeeds, otherwise error.
21350+ * succeeded value as wh->name should be freed by kfree().
21351+ */
21352+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
21353+{
21354+ char *p;
21355+
21356+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
21357+ return -ENAMETOOLONG;
21358+
21359+ wh->len = name->len + AUFS_WH_PFX_LEN;
21360+ p = kmalloc(wh->len, GFP_NOFS);
21361+ wh->name = p;
21362+ if (p) {
21363+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
21364+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
21365+ /* smp_mb(); */
21366+ return 0;
21367+ }
21368+ return -ENOMEM;
21369+}
21370+
21371+/* ---------------------------------------------------------------------- */
21372+
21373+/*
21374+ * test if the @wh_name exists under @h_parent.
21375+ * @try_sio specifies the necessary of super-io.
21376+ */
21377+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
21378+ struct au_branch *br, int try_sio)
21379+{
21380+ int err;
21381+ struct dentry *wh_dentry;
21382+ struct inode *h_dir;
21383+
21384+ h_dir = h_parent->d_inode;
21385+ if (!try_sio)
21386+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
21387+ else
21388+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
21389+ err = PTR_ERR(wh_dentry);
21390+ if (IS_ERR(wh_dentry))
21391+ goto out;
21392+
21393+ err = 0;
21394+ if (!wh_dentry->d_inode)
21395+ goto out_wh; /* success */
21396+
21397+ err = 1;
21398+ if (S_ISREG(wh_dentry->d_inode->i_mode))
21399+ goto out_wh; /* success */
21400+
21401+ err = -EIO;
21402+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
21403+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
21404+
21405+ out_wh:
21406+ dput(wh_dentry);
21407+ out:
21408+ return err;
21409+}
21410+
21411+/*
21412+ * test if the @h_dentry sets opaque or not.
21413+ */
21414+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
21415+{
21416+ int err;
21417+ struct inode *h_dir;
21418+
21419+ h_dir = h_dentry->d_inode;
21420+ err = au_wh_test(h_dentry, &diropq_name, br,
21421+ au_test_h_perm_sio(h_dir, MAY_EXEC));
21422+ return err;
21423+}
21424+
21425+/*
21426+ * returns a negative dentry whose name is unique and temporary.
21427+ */
21428+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
21429+ struct qstr *prefix)
21430+{
21431+#define HEX_LEN 4
21432+ struct dentry *dentry;
21433+ int i;
21434+ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
21435+ + HEX_LEN + 1], *name, *p;
21436+ static unsigned short cnt;
21437+ struct qstr qs;
21438+
21439+ name = defname;
21440+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
21441+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
21442+ dentry = ERR_PTR(-ENAMETOOLONG);
21443+ if (unlikely(qs.len >= PATH_MAX))
21444+ goto out;
21445+ dentry = ERR_PTR(-ENOMEM);
21446+ name = kmalloc(qs.len + 1, GFP_NOFS);
21447+ if (unlikely(!name))
21448+ goto out;
21449+ }
21450+
21451+ /* doubly whiteout-ed */
21452+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
21453+ p = name + AUFS_WH_PFX_LEN * 2;
21454+ memcpy(p, prefix->name, prefix->len);
21455+ p += prefix->len;
21456+ *p++ = '.';
21457+ AuDebugOn(name + qs.len + 1 - p <= HEX_LEN);
21458+
21459+ qs.name = name;
21460+ for (i = 0; i < 3; i++) {
21461+ sprintf(p, "%.*d", HEX_LEN, cnt++);
21462+ dentry = au_sio_lkup_one(&qs, h_parent, br);
21463+ if (IS_ERR(dentry) || !dentry->d_inode)
21464+ goto out_name;
21465+ dput(dentry);
21466+ }
21467+ /* AuWarn("could not get random name\n"); */
21468+ dentry = ERR_PTR(-EEXIST);
21469+ AuDbg("%.*s\n", AuLNPair(&qs));
21470+ BUG();
21471+
21472+ out_name:
21473+ if (name != defname)
21474+ kfree(name);
21475+ out:
21476+ return dentry;
21477+#undef HEX_LEN
21478+}
21479+
21480+/*
21481+ * rename the @h_dentry on @br to the whiteouted temporary name.
21482+ */
21483+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
21484+{
21485+ int err;
21486+ struct path h_path = {
21487+ .mnt = br->br_mnt
21488+ };
21489+ struct inode *h_dir;
21490+ struct dentry *h_parent;
21491+
21492+ h_parent = h_dentry->d_parent; /* dir inode is locked */
21493+ h_dir = h_parent->d_inode;
21494+ IMustLock(h_dir);
21495+
21496+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
21497+ err = PTR_ERR(h_path.dentry);
21498+ if (IS_ERR(h_path.dentry))
21499+ goto out;
21500+
21501+ /* under the same dir, no need to lock_rename() */
21502+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
21503+ AuTraceErr(err);
21504+ dput(h_path.dentry);
21505+
21506+ out:
21507+ return err;
21508+}
21509+
21510+/* ---------------------------------------------------------------------- */
21511+/*
21512+ * functions for removing a whiteout
21513+ */
21514+
21515+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
21516+{
21517+ int force;
21518+
21519+ /*
21520+ * forces superio when the dir has a sticky bit.
21521+ * this may be a violation of unix fs semantics.
21522+ */
21523+ force = (h_dir->i_mode & S_ISVTX)
21524+ && h_path->dentry->d_inode->i_uid != current_fsuid();
21525+ return vfsub_unlink(h_dir, h_path, force);
21526+}
21527+
21528+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
21529+ struct dentry *dentry)
21530+{
21531+ int err;
21532+
21533+ err = do_unlink_wh(h_dir, h_path);
21534+ if (!err && dentry)
21535+ au_set_dbwh(dentry, -1);
21536+
21537+ return err;
21538+}
21539+
21540+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
21541+ struct au_branch *br)
21542+{
21543+ int err;
21544+ struct path h_path = {
21545+ .mnt = br->br_mnt
21546+ };
21547+
21548+ err = 0;
21549+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
21550+ if (IS_ERR(h_path.dentry))
21551+ err = PTR_ERR(h_path.dentry);
21552+ else {
21553+ if (h_path.dentry->d_inode
21554+ && S_ISREG(h_path.dentry->d_inode->i_mode))
21555+ err = do_unlink_wh(h_parent->d_inode, &h_path);
21556+ dput(h_path.dentry);
21557+ }
21558+
21559+ return err;
21560+}
21561+
21562+/* ---------------------------------------------------------------------- */
21563+/*
21564+ * initialize/clean whiteout for a branch
21565+ */
21566+
21567+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
21568+ const int isdir)
21569+{
21570+ int err;
21571+
21572+ if (!whpath->dentry->d_inode)
21573+ return;
21574+
21575+ err = mnt_want_write(whpath->mnt);
21576+ if (!err) {
21577+ if (isdir)
21578+ err = vfsub_rmdir(h_dir, whpath);
21579+ else
21580+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
21581+ mnt_drop_write(whpath->mnt);
21582+ }
21583+ if (unlikely(err))
21584+ AuWarn("failed removing %.*s (%d), ignored.\n",
21585+ AuDLNPair(whpath->dentry), err);
21586+}
21587+
21588+static int test_linkable(struct dentry *h_root)
21589+{
21590+ struct inode *h_dir = h_root->d_inode;
21591+
21592+ if (h_dir->i_op->link)
21593+ return 0;
21594+
21595+ AuErr("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
21596+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
21597+ return -ENOSYS;
21598+}
21599+
21600+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
21601+static int au_whdir(struct inode *h_dir, struct path *path)
21602+{
21603+ int err;
21604+
21605+ err = -EEXIST;
21606+ if (!path->dentry->d_inode) {
21607+ int mode = S_IRWXU;
21608+
21609+ if (au_test_nfs(path->dentry->d_sb))
21610+ mode |= S_IXUGO;
21611+ err = mnt_want_write(path->mnt);
21612+ if (!err) {
21613+ err = vfsub_mkdir(h_dir, path, mode);
21614+ mnt_drop_write(path->mnt);
21615+ }
21616+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
21617+ err = 0;
21618+ else
21619+ AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
21620+
21621+ return err;
21622+}
21623+
21624+struct au_wh_base {
21625+ const struct qstr *name;
21626+ struct dentry *dentry;
21627+};
21628+
21629+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
21630+ struct path *h_path)
21631+{
21632+ h_path->dentry = base[AuBrWh_BASE].dentry;
21633+ au_wh_clean(h_dir, h_path, /*isdir*/0);
21634+ h_path->dentry = base[AuBrWh_PLINK].dentry;
21635+ au_wh_clean(h_dir, h_path, /*isdir*/1);
21636+ h_path->dentry = base[AuBrWh_ORPH].dentry;
21637+ au_wh_clean(h_dir, h_path, /*isdir*/1);
21638+}
21639+
21640+/*
21641+ * returns tri-state,
21642+ * minus: error, caller should print the mesage
21643+ * zero: succuess
21644+ * plus: error, caller should NOT print the mesage
21645+ */
21646+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
21647+ int do_plink, struct au_wh_base base[],
21648+ struct path *h_path)
21649+{
21650+ int err;
21651+ struct inode *h_dir;
21652+
21653+ h_dir = h_root->d_inode;
21654+ h_path->dentry = base[AuBrWh_BASE].dentry;
21655+ au_wh_clean(h_dir, h_path, /*isdir*/0);
21656+ h_path->dentry = base[AuBrWh_PLINK].dentry;
21657+ if (do_plink) {
21658+ err = test_linkable(h_root);
21659+ if (unlikely(err)) {
21660+ err = 1;
21661+ goto out;
21662+ }
21663+
21664+ err = au_whdir(h_dir, h_path);
21665+ if (unlikely(err))
21666+ goto out;
21667+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
21668+ } else
21669+ au_wh_clean(h_dir, h_path, /*isdir*/1);
21670+ h_path->dentry = base[AuBrWh_ORPH].dentry;
21671+ err = au_whdir(h_dir, h_path);
21672+ if (unlikely(err))
21673+ goto out;
21674+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
21675+
21676+ out:
21677+ return err;
21678+}
21679+
21680+/*
21681+ * for the moment, aufs supports the branch filesystem which does not support
21682+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
21683+ * copyup failed. finally, such filesystem will not be used as the writable
21684+ * branch.
21685+ *
21686+ * returns tri-state, see above.
21687+ */
21688+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
21689+ int do_plink, struct au_wh_base base[],
21690+ struct path *h_path)
21691+{
21692+ int err;
21693+ struct inode *h_dir;
21694+
21695+ err = test_linkable(h_root);
21696+ if (unlikely(err)) {
21697+ err = 1;
21698+ goto out;
21699+ }
21700+
21701+ /*
21702+ * todo: should this create be done in /sbin/mount.aufs helper?
21703+ */
21704+ err = -EEXIST;
21705+ h_dir = h_root->d_inode;
21706+ if (!base[AuBrWh_BASE].dentry->d_inode) {
21707+ err = mnt_want_write(h_path->mnt);
21708+ if (!err) {
21709+ h_path->dentry = base[AuBrWh_BASE].dentry;
21710+ err = vfsub_create(h_dir, h_path, WH_MASK);
21711+ mnt_drop_write(h_path->mnt);
21712+ }
21713+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
21714+ err = 0;
21715+ else
21716+ AuErr("unknown %.*s/%.*s exists\n",
21717+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
21718+ if (unlikely(err))
21719+ goto out;
21720+
21721+ h_path->dentry = base[AuBrWh_PLINK].dentry;
21722+ if (do_plink) {
21723+ err = au_whdir(h_dir, h_path);
21724+ if (unlikely(err))
21725+ goto out;
21726+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
21727+ } else
21728+ au_wh_clean(h_dir, h_path, /*isdir*/1);
21729+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
21730+
21731+ h_path->dentry = base[AuBrWh_ORPH].dentry;
21732+ err = au_whdir(h_dir, h_path);
21733+ if (unlikely(err))
21734+ goto out;
21735+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
21736+
21737+ out:
21738+ return err;
21739+}
21740+
21741+/*
21742+ * initialize the whiteout base file/dir for @br.
21743+ */
21744+int au_wh_init(struct dentry *h_root, struct au_branch *br,
21745+ struct super_block *sb)
21746+{
21747+ int err, i;
21748+ const unsigned char do_plink
21749+ = !!au_opt_test(au_mntflags(sb), PLINK);
21750+ struct path path = {
21751+ .mnt = br->br_mnt
21752+ };
21753+ struct inode *h_dir;
21754+ struct au_wbr *wbr = br->br_wbr;
21755+ static const struct qstr base_name[] = {
21756+ [AuBrWh_BASE] = {
21757+ .name = AUFS_BASE_NAME,
21758+ .len = sizeof(AUFS_BASE_NAME) - 1
21759+ },
21760+ [AuBrWh_PLINK] = {
21761+ .name = AUFS_PLINKDIR_NAME,
21762+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
21763+ },
21764+ [AuBrWh_ORPH] = {
21765+ .name = AUFS_ORPHDIR_NAME,
21766+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
21767+ }
21768+ };
21769+ struct au_wh_base base[] = {
21770+ [AuBrWh_BASE] = {
21771+ .name = base_name + AuBrWh_BASE,
21772+ .dentry = NULL
21773+ },
21774+ [AuBrWh_PLINK] = {
21775+ .name = base_name + AuBrWh_PLINK,
21776+ .dentry = NULL
21777+ },
21778+ [AuBrWh_ORPH] = {
21779+ .name = base_name + AuBrWh_ORPH,
21780+ .dentry = NULL
21781+ }
21782+ };
21783+
21784+
21785+ h_dir = h_root->d_inode;
21786+ for (i = 0; i < AuBrWh_Last; i++) {
21787+ /* doubly whiteouted */
21788+ struct dentry *d;
21789+
21790+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
21791+ err = PTR_ERR(d);
21792+ if (IS_ERR(d))
21793+ goto out;
21794+
21795+ base[i].dentry = d;
21796+ AuDebugOn(wbr
21797+ && wbr->wbr_wh[i]
21798+ && wbr->wbr_wh[i] != base[i].dentry);
21799+ }
21800+
21801+ if (wbr)
21802+ for (i = 0; i < AuBrWh_Last; i++) {
21803+ dput(wbr->wbr_wh[i]);
21804+ wbr->wbr_wh[i] = NULL;
21805+ }
21806+
21807+ err = 0;
21808+
21809+ switch (br->br_perm) {
21810+ case AuBrPerm_RO:
21811+ case AuBrPerm_ROWH:
21812+ case AuBrPerm_RR:
21813+ case AuBrPerm_RRWH:
21814+ au_wh_init_ro(h_dir, base, &path);
21815+ break;
21816+
21817+ case AuBrPerm_RWNoLinkWH:
21818+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
21819+ if (err > 0)
21820+ goto out;
21821+ else if (err)
21822+ goto out_err;
21823+ break;
21824+
21825+ case AuBrPerm_RW:
21826+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
21827+ if (err > 0)
21828+ goto out;
21829+ else if (err)
21830+ goto out_err;
21831+ break;
21832+
21833+ default:
21834+ BUG();
21835+ }
21836+ goto out; /* success */
21837+
21838+ out_err:
21839+ AuErr("an error(%d) on the writable branch %.*s(%s)\n",
21840+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
21841+ out:
21842+ for (i = 0; i < AuBrWh_Last; i++)
21843+ dput(base[i].dentry);
21844+ return err;
21845+}
21846+
21847+/* ---------------------------------------------------------------------- */
21848+/*
21849+ * whiteouts are all hard-linked usually.
21850+ * when its link count reaches a ceiling, we create a new whiteout base
21851+ * asynchronously.
21852+ */
21853+
21854+struct reinit_br_wh {
21855+ struct super_block *sb;
21856+ struct au_branch *br;
21857+};
21858+
21859+static void reinit_br_wh(void *arg)
21860+{
21861+ int err;
21862+ aufs_bindex_t bindex;
21863+ struct path h_path;
21864+ struct reinit_br_wh *a = arg;
21865+ struct au_wbr *wbr;
21866+ struct inode *dir;
21867+ struct dentry *h_root;
21868+ struct au_hinode *hdir;
21869+
21870+ err = 0;
21871+ wbr = a->br->br_wbr;
21872+ /* big aufs lock */
21873+ si_noflush_write_lock(a->sb);
21874+ if (!au_br_writable(a->br->br_perm))
21875+ goto out;
21876+ bindex = au_br_index(a->sb, a->br->br_id);
21877+ if (unlikely(bindex < 0))
21878+ goto out;
21879+
21880+ dir = a->sb->s_root->d_inode;
21881+ /* ii_read_lock_parent(dir); */
21882+ hdir = au_hi(dir, bindex);
21883+ h_root = au_h_dptr(a->sb->s_root, bindex);
21884+
21885+ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
21886+ wbr_wh_write_lock(wbr);
21887+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
21888+ h_root, a->br);
21889+ if (!err) {
21890+ err = mnt_want_write(a->br->br_mnt);
21891+ if (!err) {
21892+ h_path.dentry = wbr->wbr_whbase;
21893+ h_path.mnt = a->br->br_mnt;
21894+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
21895+ mnt_drop_write(a->br->br_mnt);
21896+ }
21897+ } else {
21898+ AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
21899+ err = 0;
21900+ }
21901+ dput(wbr->wbr_whbase);
21902+ wbr->wbr_whbase = NULL;
21903+ if (!err)
21904+ err = au_wh_init(h_root, a->br, a->sb);
21905+ wbr_wh_write_unlock(wbr);
21906+ au_hin_imtx_unlock(hdir);
21907+ /* ii_read_unlock(dir); */
21908+
21909+ out:
21910+ if (wbr)
21911+ atomic_dec(&wbr->wbr_wh_running);
21912+ atomic_dec(&a->br->br_count);
21913+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
21914+ si_write_unlock(a->sb);
21915+ kfree(arg);
21916+ if (unlikely(err))
21917+ AuIOErr("err %d\n", err);
21918+}
21919+
21920+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
21921+{
21922+ int do_dec, wkq_err;
21923+ struct reinit_br_wh *arg;
21924+
21925+ do_dec = 1;
21926+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
21927+ goto out;
21928+
21929+ /* ignore ENOMEM */
21930+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
21931+ if (arg) {
21932+ /*
21933+ * dec(wh_running), kfree(arg) and dec(br_count)
21934+ * in reinit function
21935+ */
21936+ arg->sb = sb;
21937+ arg->br = br;
21938+ atomic_inc(&br->br_count);
21939+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
21940+ if (unlikely(wkq_err)) {
21941+ atomic_dec(&br->br_wbr->wbr_wh_running);
21942+ atomic_dec(&br->br_count);
21943+ kfree(arg);
21944+ }
21945+ do_dec = 0;
21946+ }
21947+
21948+ out:
21949+ if (do_dec)
21950+ atomic_dec(&br->br_wbr->wbr_wh_running);
21951+}
21952+
21953+/* ---------------------------------------------------------------------- */
21954+
21955+/*
21956+ * create the whiteout @wh.
21957+ */
21958+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
21959+ struct dentry *wh)
21960+{
21961+ int err;
21962+ struct path h_path = {
21963+ .dentry = wh
21964+ };
21965+ struct au_branch *br;
21966+ struct au_wbr *wbr;
21967+ struct dentry *h_parent;
21968+ struct inode *h_dir;
21969+
21970+ h_parent = wh->d_parent; /* dir inode is locked */
21971+ h_dir = h_parent->d_inode;
21972+ IMustLock(h_dir);
21973+
21974+ br = au_sbr(sb, bindex);
21975+ h_path.mnt = br->br_mnt;
21976+ wbr = br->br_wbr;
21977+ wbr_wh_read_lock(wbr);
21978+ if (wbr->wbr_whbase) {
21979+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
21980+ if (!err || err != -EMLINK)
21981+ goto out;
21982+
21983+ /* link count full. re-initialize br_whbase. */
21984+ kick_reinit_br_wh(sb, br);
21985+ }
21986+
21987+ /* return this error in this context */
21988+ err = vfsub_create(h_dir, &h_path, WH_MASK);
21989+
21990+ out:
21991+ wbr_wh_read_unlock(wbr);
21992+ return err;
21993+}
21994+
21995+/* ---------------------------------------------------------------------- */
21996+
21997+/*
21998+ * create or remove the diropq.
21999+ */
22000+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
22001+ unsigned int flags)
22002+{
22003+ struct dentry *opq_dentry, *h_dentry;
22004+ struct super_block *sb;
22005+ struct au_branch *br;
22006+ int err;
22007+
22008+ sb = dentry->d_sb;
22009+ br = au_sbr(sb, bindex);
22010+ h_dentry = au_h_dptr(dentry, bindex);
22011+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
22012+ if (IS_ERR(opq_dentry))
22013+ goto out;
22014+
22015+ if (au_ftest_diropq(flags, CREATE)) {
22016+ err = link_or_create_wh(sb, bindex, opq_dentry);
22017+ if (!err) {
22018+ au_set_dbdiropq(dentry, bindex);
22019+ goto out; /* success */
22020+ }
22021+ } else {
22022+ struct path tmp = {
22023+ .dentry = opq_dentry,
22024+ .mnt = br->br_mnt
22025+ };
22026+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
22027+ if (!err)
22028+ au_set_dbdiropq(dentry, -1);
22029+ }
22030+ dput(opq_dentry);
22031+ opq_dentry = ERR_PTR(err);
22032+
22033+ out:
22034+ return opq_dentry;
22035+}
22036+
22037+struct do_diropq_args {
22038+ struct dentry **errp;
22039+ struct dentry *dentry;
22040+ aufs_bindex_t bindex;
22041+ unsigned int flags;
22042+};
22043+
22044+static void call_do_diropq(void *args)
22045+{
22046+ struct do_diropq_args *a = args;
22047+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
22048+}
22049+
22050+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
22051+ unsigned int flags)
22052+{
22053+ struct dentry *diropq, *h_dentry;
22054+
22055+ h_dentry = au_h_dptr(dentry, bindex);
22056+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
22057+ diropq = do_diropq(dentry, bindex, flags);
22058+ else {
22059+ int wkq_err;
22060+ struct do_diropq_args args = {
22061+ .errp = &diropq,
22062+ .dentry = dentry,
22063+ .bindex = bindex,
22064+ .flags = flags
22065+ };
22066+
22067+ wkq_err = au_wkq_wait(call_do_diropq, &args);
22068+ if (unlikely(wkq_err))
22069+ diropq = ERR_PTR(wkq_err);
22070+ }
22071+
22072+ return diropq;
22073+}
22074+
22075+/* ---------------------------------------------------------------------- */
22076+
22077+/*
22078+ * lookup whiteout dentry.
22079+ * @h_parent: lower parent dentry which must exist and be locked
22080+ * @base_name: name of dentry which will be whiteouted
22081+ * returns dentry for whiteout.
22082+ */
22083+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
22084+ struct au_branch *br)
22085+{
22086+ int err;
22087+ struct qstr wh_name;
22088+ struct dentry *wh_dentry;
22089+
22090+ err = au_wh_name_alloc(&wh_name, base_name);
22091+ wh_dentry = ERR_PTR(err);
22092+ if (!err) {
22093+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
22094+ kfree(wh_name.name);
22095+ }
22096+ return wh_dentry;
22097+}
22098+
22099+/*
22100+ * link/create a whiteout for @dentry on @bindex.
22101+ */
22102+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
22103+ struct dentry *h_parent)
22104+{
22105+ struct dentry *wh_dentry;
22106+ struct super_block *sb;
22107+ int err;
22108+
22109+ sb = dentry->d_sb;
22110+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
22111+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
22112+ err = link_or_create_wh(sb, bindex, wh_dentry);
22113+ if (!err)
22114+ au_set_dbwh(dentry, bindex);
22115+ else {
22116+ dput(wh_dentry);
22117+ wh_dentry = ERR_PTR(err);
22118+ }
22119+ }
22120+
22121+ return wh_dentry;
22122+}
22123+
22124+/* ---------------------------------------------------------------------- */
22125+
22126+/* Delete all whiteouts in this directory on branch bindex. */
22127+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
22128+ aufs_bindex_t bindex, struct au_branch *br)
22129+{
22130+ int err;
22131+ unsigned long ul, n;
22132+ struct qstr wh_name;
22133+ char *p;
22134+ struct hlist_head *head;
22135+ struct au_vdir_wh *tpos;
22136+ struct hlist_node *pos;
22137+ struct au_vdir_destr *str;
22138+
22139+ err = -ENOMEM;
22140+ p = __getname();
22141+ wh_name.name = p;
22142+ if (unlikely(!wh_name.name))
22143+ goto out;
22144+
22145+ err = 0;
22146+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
22147+ p += AUFS_WH_PFX_LEN;
22148+ n = whlist->nh_num;
22149+ head = whlist->nh_head;
22150+ for (ul = 0; !err && ul < n; ul++, head++) {
22151+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
22152+ if (tpos->wh_bindex != bindex)
22153+ continue;
22154+
22155+ str = &tpos->wh_str;
22156+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
22157+ memcpy(p, str->name, str->len);
22158+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
22159+ err = unlink_wh_name(h_dentry, &wh_name, br);
22160+ if (!err)
22161+ continue;
22162+ break;
22163+ }
22164+ AuIOErr("whiteout name too long %.*s\n",
22165+ str->len, str->name);
22166+ err = -EIO;
22167+ break;
22168+ }
22169+ }
22170+ __putname(wh_name.name);
22171+
22172+ out:
22173+ return err;
22174+}
22175+
22176+struct del_wh_children_args {
22177+ int *errp;
22178+ struct dentry *h_dentry;
dece6358 22179+ struct au_nhash whlist;
1facf9fc 22180+ aufs_bindex_t bindex;
22181+ struct au_branch *br;
22182+};
22183+
22184+static void call_del_wh_children(void *args)
22185+{
22186+ struct del_wh_children_args *a = args;
dece6358 22187+ *a->errp = del_wh_children(a->h_dentry, &a->whlist, a->bindex, a->br);
1facf9fc 22188+}
22189+
22190+/* ---------------------------------------------------------------------- */
22191+
22192+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
22193+{
22194+ struct au_whtmp_rmdir *whtmp;
dece6358
AM
22195+ int err;
22196+
22197+ SiMustAnyLock(sb);
1facf9fc 22198+
22199+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
22200+ if (unlikely(!whtmp)) {
22201+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 22202+ goto out;
dece6358 22203+ }
1facf9fc 22204+
22205+ whtmp->dir = NULL;
22206+ whtmp->wh_dentry = NULL;
dece6358
AM
22207+ err = au_nhash_alloc(&whtmp->whlist, au_sbi(sb)->si_rdhash, gfp);
22208+ if (!err)
22209+ return whtmp; /* success */
1facf9fc 22210+
1facf9fc 22211+ kfree(whtmp);
dece6358
AM
22212+ whtmp = ERR_PTR(err);
22213+
1facf9fc 22214+ out:
dece6358 22215+ return whtmp;
1facf9fc 22216+}
22217+
22218+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
22219+{
22220+ dput(whtmp->wh_dentry);
22221+ iput(whtmp->dir);
dece6358 22222+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 22223+ kfree(whtmp);
22224+}
22225+
22226+/*
22227+ * rmdir the whiteouted temporary named dir @h_dentry.
22228+ * @whlist: whiteouted children.
22229+ */
22230+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
22231+ struct dentry *wh_dentry, struct au_nhash *whlist)
22232+{
22233+ int err;
22234+ struct path h_tmp;
22235+ struct inode *wh_inode, *h_dir;
22236+ struct au_branch *br;
22237+
22238+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
22239+ IMustLock(h_dir);
22240+
22241+ br = au_sbr(dir->i_sb, bindex);
22242+ wh_inode = wh_dentry->d_inode;
22243+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
22244+
22245+ /*
22246+ * someone else might change some whiteouts while we were sleeping.
22247+ * it means this whlist may have an obsoleted entry.
22248+ */
22249+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
22250+ err = del_wh_children(wh_dentry, whlist, bindex, br);
22251+ else {
22252+ int wkq_err;
22253+ struct del_wh_children_args args = {
22254+ .errp = &err,
22255+ .h_dentry = wh_dentry,
dece6358 22256+ .whlist = *whlist,
1facf9fc 22257+ .bindex = bindex,
22258+ .br = br
22259+ };
22260+
22261+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
22262+ if (unlikely(wkq_err))
22263+ err = wkq_err;
22264+ }
22265+ mutex_unlock(&wh_inode->i_mutex);
22266+
22267+ if (!err) {
22268+ h_tmp.dentry = wh_dentry;
22269+ h_tmp.mnt = br->br_mnt;
22270+ err = vfsub_rmdir(h_dir, &h_tmp);
22271+ /* d_drop(h_dentry); */
22272+ }
22273+
22274+ if (!err) {
22275+ if (au_ibstart(dir) == bindex) {
22276+ au_cpup_attr_timesizes(dir);
22277+ drop_nlink(dir);
22278+ }
22279+ return 0; /* success */
22280+ }
22281+
22282+ AuWarn("failed removing %.*s(%d), ignored\n",
22283+ AuDLNPair(wh_dentry), err);
22284+ return err;
22285+}
22286+
22287+static void call_rmdir_whtmp(void *args)
22288+{
22289+ int err;
22290+ struct au_whtmp_rmdir *a = args;
22291+ struct super_block *sb;
22292+ struct dentry *h_parent;
22293+ struct inode *h_dir;
22294+ struct au_branch *br;
22295+ struct au_hinode *hdir;
22296+
22297+ /* rmdir by nfsd may cause deadlock with this i_mutex */
22298+ /* mutex_lock(&a->dir->i_mutex); */
22299+ sb = a->dir->i_sb;
22300+ si_noflush_read_lock(sb);
22301+ err = au_test_ro(sb, a->bindex, NULL);
22302+ if (unlikely(err))
22303+ goto out;
22304+
22305+ err = -EIO;
22306+ br = au_sbr(sb, a->bindex);
22307+ ii_write_lock_parent(a->dir);
22308+ h_parent = dget_parent(a->wh_dentry);
22309+ h_dir = h_parent->d_inode;
22310+ hdir = au_hi(a->dir, a->bindex);
22311+ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
22312+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
22313+ if (!err) {
22314+ err = mnt_want_write(br->br_mnt);
22315+ if (!err) {
22316+ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
dece6358 22317+ &a->whlist);
1facf9fc 22318+ mnt_drop_write(br->br_mnt);
22319+ }
22320+ }
22321+ au_hin_imtx_unlock(hdir);
22322+ dput(h_parent);
22323+ ii_write_unlock(a->dir);
22324+
22325+ out:
22326+ /* mutex_unlock(&a->dir->i_mutex); */
22327+ au_nwt_done(&au_sbi(sb)->si_nowait);
22328+ si_read_unlock(sb);
22329+ au_whtmp_rmdir_free(a);
22330+ if (unlikely(err))
22331+ AuIOErr("err %d\n", err);
22332+}
22333+
22334+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
22335+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
22336+{
22337+ int wkq_err;
22338+
22339+ IMustLock(dir);
22340+
22341+ /* all post-process will be done in do_rmdir_whtmp(). */
22342+ args->dir = au_igrab(dir);
22343+ args->bindex = bindex;
22344+ args->wh_dentry = dget(wh_dentry);
22345+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
22346+ if (unlikely(wkq_err)) {
22347+ AuWarn("rmdir error %.*s (%d), ignored\n",
22348+ AuDLNPair(wh_dentry), wkq_err);
22349+ au_whtmp_rmdir_free(args);
22350+ }
22351+}
dece6358
AM
22352diff -urN linux-2.6.30.org/fs/aufs/whout.h linux-2.6.30/fs/aufs/whout.h
22353--- linux-2.6.30.org/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
22354+++ linux-2.6.30/fs/aufs/whout.h 2009-07-21 08:54:19.000000000 +0200
22355@@ -0,0 +1,87 @@
1facf9fc 22356+/*
22357+ * Copyright (C) 2005-2009 Junjiro R. Okajima
22358+ *
22359+ * This program, aufs is free software; you can redistribute it and/or modify
22360+ * it under the terms of the GNU General Public License as published by
22361+ * the Free Software Foundation; either version 2 of the License, or
22362+ * (at your option) any later version.
dece6358
AM
22363+ *
22364+ * This program is distributed in the hope that it will be useful,
22365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22367+ * GNU General Public License for more details.
22368+ *
22369+ * You should have received a copy of the GNU General Public License
22370+ * along with this program; if not, write to the Free Software
22371+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22372+ */
22373+
22374+/*
22375+ * whiteout for logical deletion and opaque directory
22376+ */
22377+
22378+#ifndef __AUFS_WHOUT_H__
22379+#define __AUFS_WHOUT_H__
22380+
22381+#ifdef __KERNEL__
22382+
1facf9fc 22383+#include <linux/aufs_type.h>
22384+#include "dir.h"
22385+
22386+/* whout.c */
22387+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
22388+struct au_branch;
22389+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
22390+ struct au_branch *br, int try_sio);
22391+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
22392+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
22393+ struct qstr *prefix);
22394+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
22395+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
22396+ struct dentry *dentry);
22397+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
22398+ struct super_block *sb);
22399+
22400+/* diropq flags */
22401+#define AuDiropq_CREATE 1
22402+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
22403+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
22404+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
22405+
22406+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
22407+ unsigned int flags);
22408+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
22409+ struct au_branch *br);
22410+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
22411+ struct dentry *h_parent);
22412+
22413+/* real rmdir for the whiteout-ed dir */
22414+struct au_whtmp_rmdir {
22415+ struct inode *dir;
22416+ aufs_bindex_t bindex;
22417+ struct dentry *wh_dentry;
dece6358 22418+ struct au_nhash whlist;
1facf9fc 22419+};
22420+
22421+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
22422+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
22423+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
22424+ struct dentry *wh_dentry, struct au_nhash *whlist);
22425+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
22426+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
22427+
22428+/* ---------------------------------------------------------------------- */
22429+
22430+static inline struct dentry *au_diropq_create(struct dentry *dentry,
22431+ aufs_bindex_t bindex)
22432+{
22433+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
22434+}
22435+
22436+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
22437+{
22438+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
22439+}
22440+
22441+#endif /* __KERNEL__ */
22442+#endif /* __AUFS_WHOUT_H__ */
dece6358
AM
22443diff -urN linux-2.6.30.org/fs/aufs/wkq.c linux-2.6.30/fs/aufs/wkq.c
22444--- linux-2.6.30.org/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
22445+++ linux-2.6.30/fs/aufs/wkq.c 2009-07-21 08:54:19.000000000 +0200
22446@@ -0,0 +1,259 @@
1facf9fc 22447+/*
22448+ * Copyright (C) 2005-2009 Junjiro R. Okajima
22449+ *
22450+ * This program, aufs is free software; you can redistribute it and/or modify
22451+ * it under the terms of the GNU General Public License as published by
22452+ * the Free Software Foundation; either version 2 of the License, or
22453+ * (at your option) any later version.
dece6358
AM
22454+ *
22455+ * This program is distributed in the hope that it will be useful,
22456+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22457+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22458+ * GNU General Public License for more details.
22459+ *
22460+ * You should have received a copy of the GNU General Public License
22461+ * along with this program; if not, write to the Free Software
22462+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22463+ */
22464+
22465+/*
22466+ * workqueue for asynchronous/super-io operations
22467+ * todo: try new dredential scheme
22468+ */
22469+
dece6358 22470+#include <linux/module.h>
1facf9fc 22471+#include "aufs.h"
22472+
22473+/* internal workqueue named AUFS_WKQ_NAME */
22474+static struct au_wkq {
22475+ struct workqueue_struct *q;
22476+
22477+ /* balancing */
22478+ atomic_t busy;
22479+} *au_wkq;
22480+
22481+struct au_wkinfo {
22482+ struct work_struct wk;
22483+ struct super_block *sb;
22484+
22485+ unsigned int flags; /* see wkq.h */
22486+
22487+ au_wkq_func_t func;
22488+ void *args;
22489+
22490+ atomic_t *busyp;
22491+ struct completion *comp;
22492+};
22493+
22494+/* ---------------------------------------------------------------------- */
22495+
22496+static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
22497+{
22498+ wkinfo->busyp = &wkq->busy;
22499+ if (au_ftest_wkq(wkinfo->flags, WAIT))
22500+ return !queue_work(wkq->q, &wkinfo->wk);
22501+ else
22502+ return !schedule_work(&wkinfo->wk);
22503+}
22504+
22505+static void do_wkq(struct au_wkinfo *wkinfo)
22506+{
22507+ unsigned int idle, n;
22508+ int i, idle_idx;
22509+
22510+ while (1) {
22511+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
22512+ idle_idx = 0;
22513+ idle = UINT_MAX;
22514+ for (i = 0; i < aufs_nwkq; i++) {
22515+ n = atomic_inc_return(&au_wkq[i].busy);
22516+ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
22517+ return; /* success */
22518+
22519+ if (n < idle) {
22520+ idle_idx = i;
22521+ idle = n;
22522+ }
22523+ atomic_dec(&au_wkq[i].busy);
22524+ }
22525+ } else
22526+ idle_idx = aufs_nwkq;
22527+
22528+ atomic_inc(&au_wkq[idle_idx].busy);
22529+ if (!enqueue(au_wkq + idle_idx, wkinfo))
22530+ return; /* success */
22531+
22532+ /* impossible? */
22533+ AuWarn1("failed to queue_work()\n");
22534+ yield();
22535+ }
22536+}
22537+
22538+static void wkq_func(struct work_struct *wk)
22539+{
22540+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
22541+
22542+ wkinfo->func(wkinfo->args);
dece6358 22543+ atomic_dec_return(wkinfo->busyp);
1facf9fc 22544+ if (au_ftest_wkq(wkinfo->flags, WAIT))
22545+ complete(wkinfo->comp);
22546+ else {
22547+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
22548+ module_put(THIS_MODULE);
22549+ kfree(wkinfo);
22550+ }
22551+}
22552+
22553+/*
22554+ * Since struct completion is large, try allocating it dynamically.
22555+ */
22556+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
22557+#define AuWkqCompDeclare(name) struct completion *comp = NULL
22558+
22559+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
22560+{
22561+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
22562+ if (*comp) {
22563+ init_completion(*comp);
22564+ wkinfo->comp = *comp;
22565+ return 0;
22566+ }
22567+ return -ENOMEM;
22568+}
22569+
22570+static void au_wkq_comp_free(struct completion *comp)
22571+{
22572+ kfree(comp);
22573+}
22574+
22575+#else
22576+
22577+/* no braces */
22578+#define AuWkqCompDeclare(name) \
22579+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
22580+ struct completion *comp = &_ ## name
22581+
22582+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
22583+{
22584+ wkinfo->comp = *comp;
22585+ return 0;
22586+}
22587+
22588+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
22589+{
22590+ /* empty */
22591+}
22592+#endif /* 4KSTACKS */
22593+
22594+static void au_wkq_run(struct au_wkinfo *wkinfo)
22595+{
22596+ au_dbg_verify_kthread();
22597+ INIT_WORK(&wkinfo->wk, wkq_func);
22598+ do_wkq(wkinfo);
22599+}
22600+
22601+int au_wkq_wait(au_wkq_func_t func, void *args)
22602+{
22603+ int err;
22604+ AuWkqCompDeclare(comp);
22605+ struct au_wkinfo wkinfo = {
22606+ .flags = AuWkq_WAIT,
22607+ .func = func,
22608+ .args = args
22609+ };
22610+
22611+ err = au_wkq_comp_alloc(&wkinfo, &comp);
22612+ if (!err) {
22613+ au_wkq_run(&wkinfo);
22614+ /* no timeout, no interrupt */
22615+ wait_for_completion(wkinfo.comp);
22616+ au_wkq_comp_free(comp);
22617+ }
22618+
22619+ return err;
22620+
22621+}
22622+
22623+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
22624+{
22625+ int err;
22626+ struct au_wkinfo *wkinfo;
22627+
22628+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
22629+
22630+ /*
22631+ * wkq_func() must free this wkinfo.
22632+ * it highly depends upon the implementation of workqueue.
22633+ */
22634+ err = 0;
22635+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
22636+ if (wkinfo) {
22637+ wkinfo->sb = sb;
22638+ wkinfo->flags = !AuWkq_WAIT;
22639+ wkinfo->func = func;
22640+ wkinfo->args = args;
22641+ wkinfo->comp = NULL;
22642+ kobject_get(&au_sbi(sb)->si_kobj);
22643+ __module_get(THIS_MODULE);
22644+
22645+ au_wkq_run(wkinfo);
22646+ } else {
22647+ err = -ENOMEM;
22648+ atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
22649+ }
22650+
22651+ return err;
22652+}
22653+
22654+/* ---------------------------------------------------------------------- */
22655+
22656+void au_nwt_init(struct au_nowait_tasks *nwt)
22657+{
22658+ atomic_set(&nwt->nw_len, 0);
22659+ /* smp_mb();*/ /* atomic_set */
22660+ init_waitqueue_head(&nwt->nw_wq);
22661+}
22662+
22663+void au_wkq_fin(void)
22664+{
22665+ int i;
22666+
22667+ for (i = 0; i < aufs_nwkq; i++)
22668+ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
22669+ destroy_workqueue(au_wkq[i].q);
22670+ kfree(au_wkq);
22671+}
22672+
22673+int __init au_wkq_init(void)
22674+{
22675+ int err, i;
22676+ struct au_wkq *nowaitq;
22677+
22678+ /* '+1' is for accounting of nowait queue */
22679+ err = -ENOMEM;
22680+ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
22681+ if (unlikely(!au_wkq))
22682+ goto out;
22683+
22684+ err = 0;
22685+ for (i = 0; i < aufs_nwkq; i++) {
22686+ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
22687+ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
22688+ atomic_set(&au_wkq[i].busy, 0);
22689+ continue;
22690+ }
22691+
22692+ err = PTR_ERR(au_wkq[i].q);
22693+ au_wkq_fin();
22694+ goto out;
22695+ }
22696+
22697+ /* nowait accounting */
22698+ nowaitq = au_wkq + aufs_nwkq;
22699+ atomic_set(&nowaitq->busy, 0);
22700+ nowaitq->q = NULL;
22701+ /* smp_mb(); */ /* atomic_set */
22702+
22703+ out:
22704+ return err;
22705+}
dece6358
AM
22706diff -urN linux-2.6.30.org/fs/aufs/wkq.h linux-2.6.30/fs/aufs/wkq.h
22707--- linux-2.6.30.org/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
22708+++ linux-2.6.30/fs/aufs/wkq.h 2009-07-21 08:54:19.000000000 +0200
22709@@ -0,0 +1,82 @@
1facf9fc 22710+/*
22711+ * Copyright (C) 2005-2009 Junjiro R. Okajima
22712+ *
22713+ * This program, aufs is free software; you can redistribute it and/or modify
22714+ * it under the terms of the GNU General Public License as published by
22715+ * the Free Software Foundation; either version 2 of the License, or
22716+ * (at your option) any later version.
dece6358
AM
22717+ *
22718+ * This program is distributed in the hope that it will be useful,
22719+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22720+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22721+ * GNU General Public License for more details.
22722+ *
22723+ * You should have received a copy of the GNU General Public License
22724+ * along with this program; if not, write to the Free Software
22725+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22726+ */
22727+
22728+/*
22729+ * workqueue for asynchronous/super-io operations
22730+ * todo: try new credentials management scheme
22731+ */
22732+
22733+#ifndef __AUFS_WKQ_H__
22734+#define __AUFS_WKQ_H__
22735+
22736+#ifdef __KERNEL__
22737+
1facf9fc 22738+#include <linux/sched.h>
dece6358 22739+#include <linux/wait.h>
1facf9fc 22740+#include <linux/aufs_type.h>
22741+
dece6358
AM
22742+struct super_block;
22743+
1facf9fc 22744+/* ---------------------------------------------------------------------- */
22745+
22746+/*
22747+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
22748+ */
22749+struct au_nowait_tasks {
22750+ atomic_t nw_len;
22751+ wait_queue_head_t nw_wq;
22752+};
22753+
22754+/* ---------------------------------------------------------------------- */
22755+
22756+typedef void (*au_wkq_func_t)(void *args);
22757+
22758+/* wkq flags */
22759+#define AuWkq_WAIT 1
22760+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
22761+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
22762+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
22763+
22764+/* wkq.c */
22765+int au_wkq_wait(au_wkq_func_t func, void *args);
22766+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
22767+void au_nwt_init(struct au_nowait_tasks *nwt);
22768+int __init au_wkq_init(void);
22769+void au_wkq_fin(void);
22770+
22771+/* ---------------------------------------------------------------------- */
22772+
22773+static inline int au_test_wkq(struct task_struct *tsk)
22774+{
22775+ return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
22776+}
22777+
22778+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
22779+{
22780+ if (!atomic_dec_return(&nwt->nw_len))
22781+ wake_up_all(&nwt->nw_wq);
22782+}
22783+
22784+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
22785+{
22786+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
22787+ return 0;
22788+}
22789+
22790+#endif /* __KERNEL__ */
22791+#endif /* __AUFS_WKQ_H__ */
dece6358
AM
22792diff -urN linux-2.6.30.org/fs/aufs/xino.c linux-2.6.30/fs/aufs/xino.c
22793--- linux-2.6.30.org/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
22794+++ linux-2.6.30/fs/aufs/xino.c 2009-07-21 08:54:19.000000000 +0200
22795@@ -0,0 +1,1200 @@
1facf9fc 22796+/*
22797+ * Copyright (C) 2005-2009 Junjiro R. Okajima
22798+ *
22799+ * This program, aufs is free software; you can redistribute it and/or modify
22800+ * it under the terms of the GNU General Public License as published by
22801+ * the Free Software Foundation; either version 2 of the License, or
22802+ * (at your option) any later version.
dece6358
AM
22803+ *
22804+ * This program is distributed in the hope that it will be useful,
22805+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22806+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22807+ * GNU General Public License for more details.
22808+ *
22809+ * You should have received a copy of the GNU General Public License
22810+ * along with this program; if not, write to the Free Software
22811+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22812+ */
22813+
22814+/*
22815+ * external inode number translation table and bitmap
22816+ */
22817+
dece6358 22818+#include <linux/file.h>
1facf9fc 22819+#include <linux/seq_file.h>
22820+#include <linux/uaccess.h>
22821+#include "aufs.h"
22822+
22823+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
22824+ loff_t *pos)
22825+{
22826+ ssize_t err;
22827+ mm_segment_t oldfs;
22828+
22829+ oldfs = get_fs();
22830+ set_fs(KERNEL_DS);
22831+ do {
22832+ /* todo: signal_pending? */
22833+ err = func(file, (char __user *)buf, size, pos);
22834+ } while (err == -EAGAIN || err == -EINTR);
22835+ set_fs(oldfs);
22836+
22837+#if 0 /* reserved for future use */
22838+ if (err > 0)
22839+ fsnotify_access(file->f_dentry);
22840+#endif
22841+
22842+ return err;
22843+}
22844+
22845+/* ---------------------------------------------------------------------- */
22846+
22847+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
22848+ size_t size, loff_t *pos)
22849+{
22850+ ssize_t err;
22851+ mm_segment_t oldfs;
22852+
22853+ oldfs = get_fs();
22854+ set_fs(KERNEL_DS);
22855+ lockdep_off();
22856+ do {
22857+ /* todo: signal_pending? */
22858+ err = func(file, (const char __user *)buf, size, pos);
22859+ } while (err == -EAGAIN || err == -EINTR);
22860+ lockdep_on();
22861+ set_fs(oldfs);
22862+
22863+#if 0 /* reserved for future use */
22864+ if (err > 0)
22865+ fsnotify_modify(file->f_dentry);
22866+#endif
22867+
22868+ return err;
22869+}
22870+
22871+struct do_xino_fwrite_args {
22872+ ssize_t *errp;
22873+ au_writef_t func;
22874+ struct file *file;
22875+ void *buf;
22876+ size_t size;
22877+ loff_t *pos;
22878+};
22879+
22880+static void call_do_xino_fwrite(void *args)
22881+{
22882+ struct do_xino_fwrite_args *a = args;
22883+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
22884+}
22885+
22886+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
22887+ loff_t *pos)
22888+{
22889+ ssize_t err;
22890+
22891+ /* todo: signal block and no wkq? */
22892+ /* todo: new credential scheme */
22893+ /*
22894+ * it breaks RLIMIT_FSIZE and normal user's limit,
22895+ * users should care about quota and real 'filesystem full.'
22896+ */
22897+ if (!au_test_wkq(current)) {
22898+ int wkq_err;
22899+ struct do_xino_fwrite_args args = {
22900+ .errp = &err,
22901+ .func = func,
22902+ .file = file,
22903+ .buf = buf,
22904+ .size = size,
22905+ .pos = pos
22906+ };
22907+
22908+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
22909+ if (unlikely(wkq_err))
22910+ err = wkq_err;
22911+ } else
22912+ err = do_xino_fwrite(func, file, buf, size, pos);
22913+
22914+ return err;
22915+}
22916+
22917+/* ---------------------------------------------------------------------- */
22918+
22919+/*
22920+ * create a new xinofile at the same place/path as @base_file.
22921+ */
22922+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
22923+{
22924+ struct file *file;
22925+ struct dentry *base, *dentry, *parent;
22926+ struct inode *dir;
22927+ struct qstr *name;
22928+ int err;
22929+
22930+ base = base_file->f_dentry;
22931+ parent = base->d_parent; /* dir inode is locked */
22932+ dir = parent->d_inode;
22933+ IMustLock(dir);
22934+
22935+ file = ERR_PTR(-EINVAL);
22936+ name = &base->d_name;
22937+ dentry = vfsub_lookup_one_len(name->name, parent, name->len);
22938+ if (IS_ERR(dentry)) {
22939+ file = (void *)dentry;
22940+ AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
22941+ goto out;
22942+ }
22943+
22944+ /* no need to mnt_want_write() since we call dentry_open() later */
22945+ err = vfs_create(dir, dentry, S_IRUGO | S_IWUGO, NULL);
22946+ if (unlikely(err)) {
22947+ file = ERR_PTR(err);
22948+ AuErr("%.*s create err %d\n", AuLNPair(name), err);
22949+ goto out_dput;
22950+ }
22951+
22952+ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
22953+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
22954+ current_cred());
22955+ if (IS_ERR(file)) {
22956+ AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
22957+ goto out_dput;
22958+ }
22959+
22960+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
22961+ if (unlikely(err)) {
22962+ AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
22963+ goto out_fput;
22964+ }
22965+
22966+ if (copy_src) {
22967+ /* no one can touch copy_src xino */
22968+ err = au_copy_file(file, copy_src,
22969+ i_size_read(copy_src->f_dentry->d_inode));
22970+ if (unlikely(err)) {
22971+ AuErr("%.*s copy err %d\n", AuLNPair(name), err);
22972+ goto out_fput;
22973+ }
22974+ }
22975+ goto out_dput; /* success */
22976+
22977+ out_fput:
22978+ fput(file);
22979+ file = ERR_PTR(err);
22980+ out_dput:
22981+ dput(dentry);
22982+ out:
22983+ return file;
22984+}
22985+
22986+struct au_xino_lock_dir {
22987+ struct au_hinode *hdir;
22988+ struct dentry *parent;
22989+ struct mutex *mtx;
22990+};
22991+
22992+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
22993+ struct au_xino_lock_dir *ldir)
22994+{
22995+ aufs_bindex_t brid, bindex;
22996+
22997+ ldir->hdir = NULL;
22998+ bindex = -1;
22999+ brid = au_xino_brid(sb);
23000+ if (brid >= 0)
23001+ bindex = au_br_index(sb, brid);
23002+ if (bindex >= 0) {
23003+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
23004+ au_hin_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
23005+ } else {
23006+ ldir->parent = dget_parent(xino->f_dentry);
23007+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
23008+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
23009+ }
23010+}
23011+
23012+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
23013+{
23014+ if (ldir->hdir)
23015+ au_hin_imtx_unlock(ldir->hdir);
23016+ else {
23017+ mutex_unlock(ldir->mtx);
23018+ dput(ldir->parent);
23019+ }
23020+}
23021+
23022+/* ---------------------------------------------------------------------- */
23023+
23024+/* trucate xino files asynchronously */
23025+
23026+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
23027+{
23028+ int err;
23029+ aufs_bindex_t bi, bend;
23030+ struct au_branch *br;
23031+ struct file *new_xino, *file;
23032+ struct super_block *h_sb;
23033+ struct au_xino_lock_dir ldir;
23034+
23035+ err = -EINVAL;
23036+ bend = au_sbend(sb);
23037+ if (unlikely(bindex < 0 || bend < bindex))
23038+ goto out;
23039+ br = au_sbr(sb, bindex);
23040+ file = br->br_xino.xi_file;
23041+ if (!file)
23042+ goto out;
23043+
23044+ au_xino_lock_dir(sb, file, &ldir);
23045+ /* mnt_want_write() is unnecessary here */
23046+ new_xino = au_xino_create2(file, file);
23047+ au_xino_unlock_dir(&ldir);
23048+ err = PTR_ERR(new_xino);
23049+ if (IS_ERR(new_xino))
23050+ goto out;
23051+ err = 0;
23052+ fput(file);
23053+ br->br_xino.xi_file = new_xino;
23054+
23055+ h_sb = br->br_mnt->mnt_sb;
23056+ for (bi = 0; bi <= bend; bi++) {
23057+ if (unlikely(bi == bindex))
23058+ continue;
23059+ br = au_sbr(sb, bi);
23060+ if (br->br_mnt->mnt_sb != h_sb)
23061+ continue;
23062+
23063+ fput(br->br_xino.xi_file);
23064+ br->br_xino.xi_file = new_xino;
23065+ get_file(new_xino);
23066+ }
23067+
23068+ out:
23069+ return err;
23070+}
23071+
23072+struct xino_do_trunc_args {
23073+ struct super_block *sb;
23074+ struct au_branch *br;
23075+};
23076+
23077+static void xino_do_trunc(void *_args)
23078+{
23079+ struct xino_do_trunc_args *args = _args;
23080+ struct super_block *sb;
23081+ struct au_branch *br;
23082+ struct inode *dir;
23083+ int err;
23084+ aufs_bindex_t bindex;
23085+
23086+ err = 0;
23087+ sb = args->sb;
23088+ dir = sb->s_root->d_inode;
23089+ br = args->br;
23090+
23091+ si_noflush_write_lock(sb);
23092+ ii_read_lock_parent(dir);
23093+ bindex = au_br_index(sb, br->br_id);
23094+ err = au_xino_trunc(sb, bindex);
dece6358
AM
23095+ if (!err
23096+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 23097+ >= br->br_xino_upper)
23098+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
23099+
1facf9fc 23100+ ii_read_unlock(dir);
23101+ if (unlikely(err))
23102+ AuWarn("err b%d, (%d)\n", bindex, err);
23103+ atomic_dec(&br->br_xino_running);
23104+ atomic_dec(&br->br_count);
23105+ au_nwt_done(&au_sbi(sb)->si_nowait);
23106+ si_write_unlock(sb);
23107+ kfree(args);
23108+}
23109+
23110+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
23111+{
23112+ struct xino_do_trunc_args *args;
23113+ int wkq_err;
23114+
23115+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
23116+ < br->br_xino_upper)
23117+ return;
23118+
23119+ if (atomic_inc_return(&br->br_xino_running) > 1)
23120+ goto out;
23121+
23122+ /* lock and kfree() will be called in trunc_xino() */
23123+ args = kmalloc(sizeof(*args), GFP_NOFS);
23124+ if (unlikely(!args)) {
23125+ AuErr1("no memory\n");
23126+ goto out_args;
23127+ }
23128+
dece6358 23129+ atomic_inc_return(&br->br_count);
1facf9fc 23130+ args->sb = sb;
23131+ args->br = br;
23132+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
23133+ if (!wkq_err)
23134+ return; /* success */
23135+
23136+ AuErr("wkq %d\n", wkq_err);
dece6358 23137+ atomic_dec_return(&br->br_count);
1facf9fc 23138+
23139+ out_args:
23140+ kfree(args);
23141+ out:
dece6358 23142+ atomic_dec_return(&br->br_xino_running);
1facf9fc 23143+}
23144+
23145+/* ---------------------------------------------------------------------- */
23146+
23147+static int au_xino_do_write(au_writef_t write, struct file *file,
23148+ ino_t h_ino, ino_t ino)
23149+{
23150+ loff_t pos;
23151+ ssize_t sz;
23152+
23153+ pos = h_ino;
23154+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
23155+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
23156+ return -EFBIG;
23157+ }
23158+ pos *= sizeof(ino);
23159+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
23160+ if (sz == sizeof(ino))
23161+ return 0; /* success */
23162+
23163+ AuIOErr("write failed (%zd)\n", sz);
23164+ return -EIO;
23165+}
23166+
23167+/*
23168+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
23169+ * at the position of @h_ino.
23170+ * even if @ino is zero, it is written to the xinofile and means no entry.
23171+ * if the size of the xino file on a specific filesystem exceeds the watermark,
23172+ * try truncating it.
23173+ */
23174+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23175+ ino_t ino)
23176+{
23177+ int err;
23178+ unsigned int mnt_flags;
23179+ struct au_branch *br;
23180+
23181+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
23182+ || ((loff_t)-1) > 0);
dece6358 23183+ SiMustAnyLock(sb);
1facf9fc 23184+
23185+ mnt_flags = au_mntflags(sb);
23186+ if (!au_opt_test(mnt_flags, XINO))
23187+ return 0;
23188+
23189+ br = au_sbr(sb, bindex);
23190+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
23191+ h_ino, ino);
23192+ if (!err) {
23193+ if (au_opt_test(mnt_flags, TRUNC_XINO)
23194+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
23195+ xino_try_trunc(sb, br);
23196+ return 0; /* success */
23197+ }
23198+
23199+ AuIOErr("write failed (%d)\n", err);
23200+ return -EIO;
23201+}
23202+
23203+/* ---------------------------------------------------------------------- */
23204+
23205+/* aufs inode number bitmap */
23206+
23207+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
23208+static ino_t xib_calc_ino(unsigned long pindex, int bit)
23209+{
23210+ ino_t ino;
23211+
23212+ AuDebugOn(bit < 0 || page_bits <= bit);
23213+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
23214+ return ino;
23215+}
23216+
23217+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
23218+{
23219+ AuDebugOn(ino < AUFS_FIRST_INO);
23220+ ino -= AUFS_FIRST_INO;
23221+ *pindex = ino / page_bits;
23222+ *bit = ino % page_bits;
23223+}
23224+
23225+static int xib_pindex(struct super_block *sb, unsigned long pindex)
23226+{
23227+ int err;
23228+ loff_t pos;
23229+ ssize_t sz;
23230+ struct au_sbinfo *sbinfo;
23231+ struct file *xib;
23232+ unsigned long *p;
23233+
23234+ sbinfo = au_sbi(sb);
23235+ MtxMustLock(&sbinfo->si_xib_mtx);
23236+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
23237+ || !au_opt_test(sbinfo->si_mntflags, XINO));
23238+
23239+ if (pindex == sbinfo->si_xib_last_pindex)
23240+ return 0;
23241+
23242+ xib = sbinfo->si_xib;
23243+ p = sbinfo->si_xib_buf;
23244+ pos = sbinfo->si_xib_last_pindex;
23245+ pos *= PAGE_SIZE;
23246+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
23247+ if (unlikely(sz != PAGE_SIZE))
23248+ goto out;
23249+
23250+ pos = pindex;
23251+ pos *= PAGE_SIZE;
23252+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
23253+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
23254+ else {
23255+ memset(p, 0, PAGE_SIZE);
23256+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
23257+ }
23258+ if (sz == PAGE_SIZE) {
23259+ sbinfo->si_xib_last_pindex = pindex;
23260+ return 0; /* success */
23261+ }
23262+
23263+ out:
23264+ AuIOErr1("write failed (%zd)\n", sz);
23265+ err = sz;
23266+ if (sz >= 0)
23267+ err = -EIO;
23268+ return err;
23269+}
23270+
23271+/* ---------------------------------------------------------------------- */
23272+
23273+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23274+ ino_t ino)
23275+{
23276+ int err, bit;
23277+ unsigned long pindex;
23278+ struct au_sbinfo *sbinfo;
23279+
23280+ if (!au_opt_test(au_mntflags(sb), XINO))
23281+ return 0;
23282+
23283+ err = 0;
23284+ if (ino) {
23285+ sbinfo = au_sbi(sb);
23286+ xib_calc_bit(ino, &pindex, &bit);
23287+ AuDebugOn(page_bits <= bit);
23288+ mutex_lock(&sbinfo->si_xib_mtx);
23289+ err = xib_pindex(sb, pindex);
23290+ if (!err) {
23291+ clear_bit(bit, sbinfo->si_xib_buf);
23292+ sbinfo->si_xib_next_bit = bit;
23293+ }
23294+ mutex_unlock(&sbinfo->si_xib_mtx);
23295+ }
23296+
23297+ if (!err)
23298+ err = au_xino_write(sb, bindex, h_ino, 0);
23299+ return err;
23300+}
23301+
23302+/* get an unused inode number from bitmap */
23303+ino_t au_xino_new_ino(struct super_block *sb)
23304+{
23305+ ino_t ino;
23306+ unsigned long *p, pindex, ul, pend;
23307+ struct au_sbinfo *sbinfo;
23308+ struct file *file;
23309+ int free_bit, err;
23310+
23311+ if (!au_opt_test(au_mntflags(sb), XINO))
23312+ return iunique(sb, AUFS_FIRST_INO);
23313+
23314+ sbinfo = au_sbi(sb);
23315+ mutex_lock(&sbinfo->si_xib_mtx);
23316+ p = sbinfo->si_xib_buf;
23317+ free_bit = sbinfo->si_xib_next_bit;
23318+ if (free_bit < page_bits && !test_bit(free_bit, p))
23319+ goto out; /* success */
23320+ free_bit = find_first_zero_bit(p, page_bits);
23321+ if (free_bit < page_bits)
23322+ goto out; /* success */
23323+
23324+ pindex = sbinfo->si_xib_last_pindex;
23325+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
23326+ err = xib_pindex(sb, ul);
23327+ if (unlikely(err))
23328+ goto out_err;
23329+ free_bit = find_first_zero_bit(p, page_bits);
23330+ if (free_bit < page_bits)
23331+ goto out; /* success */
23332+ }
23333+
23334+ file = sbinfo->si_xib;
23335+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
23336+ for (ul = pindex + 1; ul <= pend; ul++) {
23337+ err = xib_pindex(sb, ul);
23338+ if (unlikely(err))
23339+ goto out_err;
23340+ free_bit = find_first_zero_bit(p, page_bits);
23341+ if (free_bit < page_bits)
23342+ goto out; /* success */
23343+ }
23344+ BUG();
23345+
23346+ out:
23347+ set_bit(free_bit, p);
23348+ sbinfo->si_xib_next_bit++;
23349+ pindex = sbinfo->si_xib_last_pindex;
23350+ mutex_unlock(&sbinfo->si_xib_mtx);
23351+ ino = xib_calc_ino(pindex, free_bit);
23352+ AuDbg("i%lu\n", (unsigned long)ino);
23353+ return ino;
23354+ out_err:
23355+ mutex_unlock(&sbinfo->si_xib_mtx);
23356+ AuDbg("i0\n");
23357+ return 0;
23358+}
23359+
23360+/*
23361+ * read @ino from xinofile for the specified branch{@sb, @bindex}
23362+ * at the position of @h_ino.
23363+ * if @ino does not exist and @do_new is true, get new one.
23364+ */
23365+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23366+ ino_t *ino)
23367+{
23368+ int err;
23369+ ssize_t sz;
23370+ loff_t pos;
23371+ struct file *file;
23372+ struct au_sbinfo *sbinfo;
23373+
23374+ *ino = 0;
23375+ if (!au_opt_test(au_mntflags(sb), XINO))
23376+ return 0; /* no xino */
23377+
23378+ err = 0;
23379+ sbinfo = au_sbi(sb);
23380+ pos = h_ino;
23381+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
23382+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
23383+ return -EFBIG;
23384+ }
23385+ pos *= sizeof(*ino);
23386+
23387+ file = au_sbr(sb, bindex)->br_xino.xi_file;
23388+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
23389+ return 0; /* no ino */
23390+
23391+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
23392+ if (sz == sizeof(*ino))
23393+ return 0; /* success */
23394+
23395+ err = sz;
23396+ if (unlikely(sz >= 0)) {
23397+ err = -EIO;
23398+ AuIOErr("xino read error (%zd)\n", sz);
23399+ }
23400+
23401+ return err;
23402+}
23403+
23404+/* ---------------------------------------------------------------------- */
23405+
23406+/* create and set a new xino file */
23407+
23408+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
23409+{
23410+ struct file *file;
23411+ struct dentry *h_parent, *d;
23412+ struct inode *h_dir;
23413+ int err;
23414+
23415+ /*
23416+ * at mount-time, and the xino file is the default path,
23417+ * hinotify is disabled so we have no inotify events to ignore.
23418+ * when a user specified the xino, we cannot get au_hdir to be ignored.
23419+ */
23420+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
23421+ S_IRUGO | S_IWUGO);
23422+ if (IS_ERR(file)) {
23423+ if (!silent)
23424+ AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
23425+ return file;
23426+ }
23427+
23428+ /* keep file count */
23429+ h_parent = dget_parent(file->f_dentry);
23430+ h_dir = h_parent->d_inode;
23431+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
23432+ /* mnt_want_write() is unnecessary here */
23433+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
23434+ mutex_unlock(&h_dir->i_mutex);
23435+ dput(h_parent);
23436+ if (unlikely(err)) {
23437+ if (!silent)
23438+ AuErr("unlink %s(%d)\n", fname, err);
23439+ goto out;
23440+ }
23441+
23442+ err = -EINVAL;
23443+ d = file->f_dentry;
23444+ if (unlikely(sb == d->d_sb)) {
23445+ if (!silent)
23446+ AuErr("%s must be outside\n", fname);
23447+ goto out;
23448+ }
23449+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
23450+ if (!silent)
23451+ AuErr("xino doesn't support %s(%s)\n",
23452+ fname, au_sbtype(d->d_sb));
23453+ goto out;
23454+ }
23455+ return file; /* success */
23456+
23457+ out:
23458+ fput(file);
23459+ file = ERR_PTR(err);
23460+ return file;
23461+}
23462+
23463+/*
23464+ * find another branch who is on the same filesystem of the specified
23465+ * branch{@btgt}. search until @bend.
23466+ */
23467+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
23468+ aufs_bindex_t bend)
23469+{
23470+ aufs_bindex_t bindex;
23471+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
23472+
23473+ for (bindex = 0; bindex < btgt; bindex++)
23474+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
23475+ return bindex;
23476+ for (bindex++; bindex <= bend; bindex++)
23477+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
23478+ return bindex;
23479+ return -1;
23480+}
23481+
23482+/* ---------------------------------------------------------------------- */
23483+
23484+/*
23485+ * initialize the xinofile for the specified branch @br
23486+ * at the place/path where @base_file indicates.
23487+ * test whether another branch is on the same filesystem or not,
23488+ * if @do_test is true.
23489+ */
23490+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
23491+ struct file *base_file, int do_test)
23492+{
23493+ int err;
23494+ ino_t ino;
23495+ aufs_bindex_t bend, bindex;
23496+ struct au_branch *shared_br, *b;
23497+ struct file *file;
23498+ struct super_block *tgt_sb;
23499+
23500+ shared_br = NULL;
23501+ bend = au_sbend(sb);
23502+ if (do_test) {
23503+ tgt_sb = br->br_mnt->mnt_sb;
23504+ for (bindex = 0; bindex <= bend; bindex++) {
23505+ b = au_sbr(sb, bindex);
23506+ if (tgt_sb == b->br_mnt->mnt_sb) {
23507+ shared_br = b;
23508+ break;
23509+ }
23510+ }
23511+ }
23512+
23513+ if (!shared_br || !shared_br->br_xino.xi_file) {
23514+ struct au_xino_lock_dir ldir;
23515+
23516+ au_xino_lock_dir(sb, base_file, &ldir);
23517+ /* mnt_want_write() is unnecessary here */
23518+ file = au_xino_create2(base_file, NULL);
23519+ au_xino_unlock_dir(&ldir);
23520+ err = PTR_ERR(file);
23521+ if (IS_ERR(file))
23522+ goto out;
23523+ br->br_xino.xi_file = file;
23524+ } else {
23525+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
23526+ get_file(br->br_xino.xi_file);
23527+ }
23528+
23529+ ino = AUFS_ROOT_INO;
23530+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
23531+ h_ino, ino);
23532+ if (!err)
23533+ return 0; /* success */
23534+
23535+
23536+ out:
23537+ return err;
23538+}
23539+
23540+/* ---------------------------------------------------------------------- */
23541+
23542+/* trucate a xino bitmap file */
23543+
23544+/* todo: slow */
23545+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
23546+{
23547+ int err, bit;
23548+ ssize_t sz;
23549+ unsigned long pindex;
23550+ loff_t pos, pend;
23551+ struct au_sbinfo *sbinfo;
23552+ au_readf_t func;
23553+ ino_t *ino;
23554+ unsigned long *p;
23555+
23556+ err = 0;
23557+ sbinfo = au_sbi(sb);
dece6358 23558+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 23559+ p = sbinfo->si_xib_buf;
23560+ func = sbinfo->si_xread;
23561+ pend = i_size_read(file->f_dentry->d_inode);
23562+ pos = 0;
23563+ while (pos < pend) {
23564+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
23565+ err = sz;
23566+ if (unlikely(sz <= 0))
23567+ goto out;
23568+
23569+ err = 0;
23570+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
23571+ if (unlikely(*ino < AUFS_FIRST_INO))
23572+ continue;
23573+
23574+ xib_calc_bit(*ino, &pindex, &bit);
23575+ AuDebugOn(page_bits <= bit);
23576+ err = xib_pindex(sb, pindex);
23577+ if (!err)
23578+ set_bit(bit, p);
23579+ else
23580+ goto out;
23581+ }
23582+ }
23583+
23584+ out:
23585+ return err;
23586+}
23587+
23588+static int xib_restore(struct super_block *sb)
23589+{
23590+ int err;
23591+ aufs_bindex_t bindex, bend;
23592+ void *page;
23593+
23594+ err = -ENOMEM;
23595+ page = (void *)__get_free_page(GFP_NOFS);
23596+ if (unlikely(!page))
23597+ goto out;
23598+
23599+ err = 0;
23600+ bend = au_sbend(sb);
23601+ for (bindex = 0; !err && bindex <= bend; bindex++)
23602+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
23603+ err = do_xib_restore
23604+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
23605+ else
23606+ AuDbg("b%d\n", bindex);
23607+ free_page((unsigned long)page);
23608+
23609+ out:
23610+ return err;
23611+}
23612+
23613+int au_xib_trunc(struct super_block *sb)
23614+{
23615+ int err;
23616+ ssize_t sz;
23617+ loff_t pos;
23618+ struct au_xino_lock_dir ldir;
23619+ struct au_sbinfo *sbinfo;
23620+ unsigned long *p;
23621+ struct file *file;
23622+
dece6358
AM
23623+ SiMustWriteLock(sb);
23624+
1facf9fc 23625+ err = 0;
23626+ sbinfo = au_sbi(sb);
23627+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
23628+ goto out;
23629+
23630+ file = sbinfo->si_xib;
23631+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
23632+ goto out;
23633+
23634+ au_xino_lock_dir(sb, file, &ldir);
23635+ /* mnt_want_write() is unnecessary here */
23636+ file = au_xino_create2(sbinfo->si_xib, NULL);
23637+ au_xino_unlock_dir(&ldir);
23638+ err = PTR_ERR(file);
23639+ if (IS_ERR(file))
23640+ goto out;
23641+ fput(sbinfo->si_xib);
23642+ sbinfo->si_xib = file;
23643+
23644+ p = sbinfo->si_xib_buf;
23645+ memset(p, 0, PAGE_SIZE);
23646+ pos = 0;
23647+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
23648+ if (unlikely(sz != PAGE_SIZE)) {
23649+ err = sz;
23650+ AuIOErr("err %d\n", err);
23651+ if (sz >= 0)
23652+ err = -EIO;
23653+ goto out;
23654+ }
23655+
23656+ mutex_lock(&sbinfo->si_xib_mtx);
23657+ /* mnt_want_write() is unnecessary here */
23658+ err = xib_restore(sb);
23659+ mutex_unlock(&sbinfo->si_xib_mtx);
23660+
23661+out:
23662+ return err;
23663+}
23664+
23665+/* ---------------------------------------------------------------------- */
23666+
23667+/*
23668+ * xino mount option handlers
23669+ */
23670+static au_readf_t find_readf(struct file *h_file)
23671+{
23672+ const struct file_operations *fop = h_file->f_op;
23673+
23674+ if (fop) {
23675+ if (fop->read)
23676+ return fop->read;
23677+ if (fop->aio_read)
23678+ return do_sync_read;
23679+ }
23680+ return ERR_PTR(-ENOSYS);
23681+}
23682+
23683+static au_writef_t find_writef(struct file *h_file)
23684+{
23685+ const struct file_operations *fop = h_file->f_op;
23686+
23687+ if (fop) {
23688+ if (fop->write)
23689+ return fop->write;
23690+ if (fop->aio_write)
23691+ return do_sync_write;
23692+ }
23693+ return ERR_PTR(-ENOSYS);
23694+}
23695+
23696+/* xino bitmap */
23697+static void xino_clear_xib(struct super_block *sb)
23698+{
23699+ struct au_sbinfo *sbinfo;
23700+
dece6358
AM
23701+ SiMustWriteLock(sb);
23702+
1facf9fc 23703+ sbinfo = au_sbi(sb);
23704+ sbinfo->si_xread = NULL;
23705+ sbinfo->si_xwrite = NULL;
23706+ if (sbinfo->si_xib)
23707+ fput(sbinfo->si_xib);
23708+ sbinfo->si_xib = NULL;
23709+ free_page((unsigned long)sbinfo->si_xib_buf);
23710+ sbinfo->si_xib_buf = NULL;
23711+}
23712+
23713+static int au_xino_set_xib(struct super_block *sb, struct file *base)
23714+{
23715+ int err;
23716+ loff_t pos;
23717+ struct au_sbinfo *sbinfo;
23718+ struct file *file;
23719+
dece6358
AM
23720+ SiMustWriteLock(sb);
23721+
1facf9fc 23722+ sbinfo = au_sbi(sb);
23723+ file = au_xino_create2(base, sbinfo->si_xib);
23724+ err = PTR_ERR(file);
23725+ if (IS_ERR(file))
23726+ goto out;
23727+ if (sbinfo->si_xib)
23728+ fput(sbinfo->si_xib);
23729+ sbinfo->si_xib = file;
23730+ sbinfo->si_xread = find_readf(file);
23731+ sbinfo->si_xwrite = find_writef(file);
23732+
23733+ err = -ENOMEM;
23734+ if (!sbinfo->si_xib_buf)
23735+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
23736+ if (unlikely(!sbinfo->si_xib_buf))
23737+ goto out_unset;
23738+
23739+ sbinfo->si_xib_last_pindex = 0;
23740+ sbinfo->si_xib_next_bit = 0;
23741+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
23742+ pos = 0;
23743+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
23744+ PAGE_SIZE, &pos);
23745+ if (unlikely(err != PAGE_SIZE))
23746+ goto out_free;
23747+ }
23748+ err = 0;
23749+ goto out; /* success */
23750+
23751+ out_free:
23752+ free_page((unsigned long)sbinfo->si_xib_buf);
23753+ sbinfo->si_xib_buf = NULL;
23754+ if (err >= 0)
23755+ err = -EIO;
23756+ out_unset:
23757+ fput(sbinfo->si_xib);
23758+ sbinfo->si_xib = NULL;
23759+ sbinfo->si_xread = NULL;
23760+ sbinfo->si_xwrite = NULL;
23761+ out:
23762+ return err;
23763+}
23764+
23765+/* xino for each branch */
23766+static void xino_clear_br(struct super_block *sb)
23767+{
23768+ aufs_bindex_t bindex, bend;
23769+ struct au_branch *br;
23770+
23771+ bend = au_sbend(sb);
23772+ for (bindex = 0; bindex <= bend; bindex++) {
23773+ br = au_sbr(sb, bindex);
23774+ if (!br || !br->br_xino.xi_file)
23775+ continue;
23776+
23777+ fput(br->br_xino.xi_file);
23778+ br->br_xino.xi_file = NULL;
23779+ }
23780+}
23781+
23782+static int au_xino_set_br(struct super_block *sb, struct file *base)
23783+{
23784+ int err;
23785+ ino_t ino;
23786+ aufs_bindex_t bindex, bend, bshared;
23787+ struct {
23788+ struct file *old, *new;
23789+ } *fpair, *p;
23790+ struct au_branch *br;
23791+ struct inode *inode;
23792+ au_writef_t writef;
23793+
dece6358
AM
23794+ SiMustWriteLock(sb);
23795+
1facf9fc 23796+ err = -ENOMEM;
23797+ bend = au_sbend(sb);
23798+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
23799+ if (unlikely(!fpair))
23800+ goto out;
23801+
23802+ inode = sb->s_root->d_inode;
23803+ ino = AUFS_ROOT_INO;
23804+ writef = au_sbi(sb)->si_xwrite;
23805+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
23806+ br = au_sbr(sb, bindex);
23807+ bshared = is_sb_shared(sb, bindex, bindex - 1);
23808+ if (bshared >= 0) {
23809+ /* shared xino */
23810+ *p = fpair[bshared];
23811+ get_file(p->new);
23812+ }
23813+
23814+ if (!p->new) {
23815+ /* new xino */
23816+ p->old = br->br_xino.xi_file;
23817+ p->new = au_xino_create2(base, br->br_xino.xi_file);
23818+ err = PTR_ERR(p->new);
23819+ if (IS_ERR(p->new)) {
23820+ p->new = NULL;
23821+ goto out_pair;
23822+ }
23823+ }
23824+
23825+ err = au_xino_do_write(writef, p->new,
23826+ au_h_iptr(inode, bindex)->i_ino, ino);
23827+ if (unlikely(err))
23828+ goto out_pair;
23829+ }
23830+
23831+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
23832+ br = au_sbr(sb, bindex);
23833+ if (br->br_xino.xi_file)
23834+ fput(br->br_xino.xi_file);
23835+ get_file(p->new);
23836+ br->br_xino.xi_file = p->new;
23837+ }
23838+
23839+ out_pair:
23840+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
23841+ if (p->new)
23842+ fput(p->new);
23843+ else
23844+ break;
23845+ kfree(fpair);
23846+ out:
23847+ return err;
23848+}
23849+
23850+void au_xino_clr(struct super_block *sb)
23851+{
23852+ struct au_sbinfo *sbinfo;
23853+
23854+ au_xigen_clr(sb);
23855+ xino_clear_xib(sb);
23856+ xino_clear_br(sb);
23857+ sbinfo = au_sbi(sb);
23858+ /* lvalue, do not call au_mntflags() */
23859+ au_opt_clr(sbinfo->si_mntflags, XINO);
23860+}
23861+
23862+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
23863+{
23864+ int err, skip;
23865+ struct dentry *parent, *cur_parent;
23866+ struct qstr *dname, *cur_name;
23867+ struct file *cur_xino;
23868+ struct inode *dir;
23869+ struct au_sbinfo *sbinfo;
23870+
dece6358
AM
23871+ SiMustWriteLock(sb);
23872+
1facf9fc 23873+ err = 0;
23874+ sbinfo = au_sbi(sb);
23875+ parent = dget_parent(xino->file->f_dentry);
23876+ if (remount) {
23877+ skip = 0;
23878+ dname = &xino->file->f_dentry->d_name;
23879+ cur_xino = sbinfo->si_xib;
23880+ if (cur_xino) {
23881+ cur_parent = dget_parent(cur_xino->f_dentry);
23882+ cur_name = &cur_xino->f_dentry->d_name;
23883+ skip = (cur_parent == parent
23884+ && dname->len == cur_name->len
23885+ && !memcmp(dname->name, cur_name->name,
23886+ dname->len));
23887+ dput(cur_parent);
23888+ }
23889+ if (skip)
23890+ goto out;
23891+ }
23892+
23893+ au_opt_set(sbinfo->si_mntflags, XINO);
23894+ dir = parent->d_inode;
23895+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
23896+ /* mnt_want_write() is unnecessary here */
23897+ err = au_xino_set_xib(sb, xino->file);
23898+ if (!err)
23899+ err = au_xigen_set(sb, xino->file);
23900+ if (!err)
23901+ err = au_xino_set_br(sb, xino->file);
23902+ mutex_unlock(&dir->i_mutex);
23903+ if (!err)
23904+ goto out; /* success */
23905+
23906+ /* reset all */
23907+ AuIOErr("failed creating xino(%d).\n", err);
23908+
23909+ out:
23910+ dput(parent);
23911+ return err;
23912+}
23913+
23914+/* ---------------------------------------------------------------------- */
23915+
23916+/*
23917+ * create a xinofile at the default place/path.
23918+ */
23919+struct file *au_xino_def(struct super_block *sb)
23920+{
23921+ struct file *file;
23922+ char *page, *p;
23923+ struct au_branch *br;
23924+ struct super_block *h_sb;
23925+ struct path path;
23926+ aufs_bindex_t bend, bindex, bwr;
23927+
23928+ br = NULL;
23929+ bend = au_sbend(sb);
23930+ bwr = -1;
23931+ for (bindex = 0; bindex <= bend; bindex++) {
23932+ br = au_sbr(sb, bindex);
23933+ if (au_br_writable(br->br_perm)
23934+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
23935+ bwr = bindex;
23936+ break;
23937+ }
23938+ }
23939+
23940+ if (bwr >= 0) {
23941+ file = ERR_PTR(-ENOMEM);
23942+ page = __getname();
23943+ if (unlikely(!page))
23944+ goto out;
23945+ path.mnt = br->br_mnt;
23946+ path.dentry = au_h_dptr(sb->s_root, bwr);
23947+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
23948+ file = (void *)p;
23949+ if (!IS_ERR(p)) {
23950+ strcat(p, "/" AUFS_XINO_FNAME);
23951+ AuDbg("%s\n", p);
23952+ file = au_xino_create(sb, p, /*silent*/0);
23953+ if (!IS_ERR(file))
23954+ au_xino_brid_set(sb, br->br_id);
23955+ }
23956+ __putname(page);
23957+ } else {
23958+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
23959+ if (IS_ERR(file))
23960+ goto out;
23961+ h_sb = file->f_dentry->d_sb;
23962+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
23963+ AuErr("xino doesn't support %s(%s)\n",
23964+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
23965+ fput(file);
23966+ file = ERR_PTR(-EINVAL);
23967+ }
23968+ if (!IS_ERR(file))
23969+ au_xino_brid_set(sb, -1);
23970+ }
23971+
23972+ out:
23973+ return file;
23974+}
23975+
23976+/* ---------------------------------------------------------------------- */
23977+
23978+int au_xino_path(struct seq_file *seq, struct file *file)
23979+{
23980+ int err;
23981+
23982+ err = au_seq_path(seq, &file->f_path);
23983+ if (unlikely(err < 0))
23984+ goto out;
23985+
23986+ err = 0;
23987+#define Deleted "\\040(deleted)"
23988+ seq->count -= sizeof(Deleted) - 1;
23989+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
23990+ sizeof(Deleted) - 1));
23991+#undef Deleted
23992+
23993+ out:
23994+ return err;
23995+}
dece6358
AM
23996diff -urN linux-2.6.30.org/fs/Kconfig linux-2.6.30/fs/Kconfig
23997--- linux-2.6.30.org/fs/Kconfig 2009-06-10 05:05:27.000000000 +0200
23998+++ linux-2.6.30/fs/Kconfig 2009-07-21 09:13:25.176633466 +0200
23999@@ -176,6 +176,7 @@
24000 source "fs/sysv/Kconfig"
24001 source "fs/ufs/Kconfig"
24002 source "fs/exofs/Kconfig"
24003+source "fs/aufs/Kconfig"
24004
24005 config NILFS2_FS
24006 tristate "NILFS2 file system support (EXPERIMENTAL)"
24007diff -urN linux-2.6.30.org/fs/Makefile linux-2.6.30/fs/Makefile
24008--- linux-2.6.30.org/fs/Makefile 2009-06-10 05:05:27.000000000 +0200
24009+++ linux-2.6.30/fs/Makefile 2009-07-21 09:13:25.184549275 +0200
24010@@ -124,3 +124,4 @@
24011 obj-$(CONFIG_BTRFS_FS) += btrfs/
24012 obj-$(CONFIG_GFS2_FS) += gfs2/
24013 obj-$(CONFIG_EXOFS_FS) += exofs/
24014+obj-$(CONFIG_AUFS_FS) += aufs/
24015diff -urN linux-2.6.30.org/fs/namei.c linux-2.6.30/fs/namei.c
24016--- linux-2.6.30.org/fs/namei.c 2009-06-10 05:05:27.000000000 +0200
24017+++ linux-2.6.30/fs/namei.c 2009-07-21 09:13:29.146633618 +0200
24018@@ -337,6 +337,7 @@
24019
24020 return 0;
24021 }
24022+EXPORT_SYMBOL(deny_write_access);
24023
24024 /**
24025 * path_get - get a reference to a path
24026@@ -1200,7 +1201,7 @@
1facf9fc 24027 * needs parent already locked. Doesn't follow mounts.
24028 * SMP-safe.
24029 */
24030-static struct dentry *lookup_hash(struct nameidata *nd)
24031+struct dentry *lookup_hash(struct nameidata *nd)
24032 {
24033 int err;
24034
dece6358
AM
24035@@ -1209,8 +1210,9 @@
24036 return ERR_PTR(err);
1facf9fc 24037 return __lookup_hash(&nd->last, nd->path.dentry, nd);
24038 }
dece6358 24039+EXPORT_SYMBOL(lookup_hash);
1facf9fc 24040
24041-static int __lookup_one_len(const char *name, struct qstr *this,
24042+int __lookup_one_len(const char *name, struct qstr *this,
24043 struct dentry *base, int len)
24044 {
24045 unsigned long hash;
dece6358
AM
24046@@ -1231,6 +1233,7 @@
24047 this->hash = end_name_hash(hash);
24048 return 0;
24049 }
24050+EXPORT_SYMBOL(__lookup_one_len);
24051
24052 /**
24053 * lookup_one_len - filesystem helper to lookup single pathname component
24054diff -urN linux-2.6.30.org/fs/namespace.c linux-2.6.30/fs/namespace.c
24055--- linux-2.6.30.org/fs/namespace.c 2009-06-10 05:05:27.000000000 +0200
24056+++ linux-2.6.30/fs/namespace.c 2009-07-21 09:13:29.166633410 +0200
24057@@ -38,6 +38,7 @@
24058
24059 /* spinlock for vfsmount related operations, inplace of dcache_lock */
24060 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
24061+EXPORT_SYMBOL(vfsmount_lock);
24062
24063 static int event;
24064 static DEFINE_IDA(mnt_id_ida);
24065diff -urN linux-2.6.30.org/fs/open.c linux-2.6.30/fs/open.c
24066--- linux-2.6.30.org/fs/open.c 2009-06-10 05:05:27.000000000 +0200
24067+++ linux-2.6.30/fs/open.c 2009-07-21 09:13:29.183798348 +0200
24068@@ -221,6 +221,7 @@
24069 mutex_unlock(&dentry->d_inode->i_mutex);
24070 return err;
24071 }
24072+EXPORT_SYMBOL(do_truncate);
24073
24074 static long do_sys_truncate(const char __user *pathname, loff_t length)
24075 {
24076diff -urN linux-2.6.30.org/fs/splice.c linux-2.6.30/fs/splice.c
24077--- linux-2.6.30.org/fs/splice.c 2009-06-10 05:05:27.000000000 +0200
24078+++ linux-2.6.30/fs/splice.c 2009-07-21 09:13:29.216632034 +0200
24079@@ -905,8 +905,8 @@
0fc653ad 24080 /*
24081 * Attempt to initiate a splice from pipe to file.
24082 */
24083-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
24084- loff_t *ppos, size_t len, unsigned int flags)
24085+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
24086+ loff_t *ppos, size_t len, unsigned int flags)
24087 {
24088 int ret;
24089
dece6358
AM
24090@@ -925,13 +925,14 @@
24091
24092 return out->f_op->splice_write(pipe, out, ppos, len, flags);
24093 }
24094+EXPORT_SYMBOL(do_splice_from);
24095
0fc653ad 24096 /*
24097 * Attempt to initiate a splice from a file to a pipe.
24098 */
24099-static long do_splice_to(struct file *in, loff_t *ppos,
24100- struct pipe_inode_info *pipe, size_t len,
24101- unsigned int flags)
24102+long do_splice_to(struct file *in, loff_t *ppos,
24103+ struct pipe_inode_info *pipe, size_t len,
24104+ unsigned int flags)
24105 {
24106 int ret;
24107
dece6358
AM
24108@@ -947,6 +948,7 @@
24109
24110 return in->f_op->splice_read(in, ppos, pipe, len, flags);
24111 }
24112+EXPORT_SYMBOL(do_splice_to);
24113
24114 /**
24115 * splice_direct_to_actor - splices data directly between two non-pipes
24116diff -urN linux-2.6.30.org/include/linux/aufs_type.h linux-2.6.30/include/linux/aufs_type.h
24117--- linux-2.6.30.org/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
24118+++ linux-2.6.30/include/linux/aufs_type.h 2009-07-21 08:54:19.000000000 +0200
24119@@ -0,0 +1,109 @@
1facf9fc 24120+/*
24121+ * Copyright (C) 2005-2009 Junjiro R. Okajima
24122+ *
24123+ * This program, aufs is free software; you can redistribute it and/or modify
24124+ * it under the terms of the GNU General Public License as published by
24125+ * the Free Software Foundation; either version 2 of the License, or
24126+ * (at your option) any later version.
dece6358
AM
24127+ *
24128+ * This program is distributed in the hope that it will be useful,
24129+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24130+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24131+ * GNU General Public License for more details.
24132+ *
24133+ * You should have received a copy of the GNU General Public License
24134+ * along with this program; if not, write to the Free Software
24135+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24136+ */
24137+
24138+#ifndef __AUFS_TYPE_H__
24139+#define __AUFS_TYPE_H__
24140+
24141+#include <linux/ioctl.h>
24142+
dece6358 24143+#define AUFS_VERSION "2-standalone.tree-30-20090720"
1facf9fc 24144+
24145+/* todo? move this to linux-2.6.19/include/magic.h */
24146+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
24147+
24148+/* ---------------------------------------------------------------------- */
24149+
24150+#ifdef CONFIG_AUFS_BRANCH_MAX_127
24151+/* some environments treat 'char' as 'unsigned char' by default */
24152+typedef signed char aufs_bindex_t;
24153+#define AUFS_BRANCH_MAX 127
24154+#else
24155+typedef short aufs_bindex_t;
24156+#ifdef CONFIG_AUFS_BRANCH_MAX_511
24157+#define AUFS_BRANCH_MAX 511
24158+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
24159+#define AUFS_BRANCH_MAX 1023
24160+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
24161+#define AUFS_BRANCH_MAX 32767
24162+#endif
24163+#endif
24164+
24165+#ifdef __KERNEL__
24166+#ifndef AUFS_BRANCH_MAX
24167+#error unknown CONFIG_AUFS_BRANCH_MAX value
24168+#endif
24169+#endif /* __KERNEL__ */
24170+
24171+/* ---------------------------------------------------------------------- */
24172+
24173+#define AUFS_NAME "aufs"
24174+#define AUFS_FSTYPE AUFS_NAME
24175+
24176+#define AUFS_ROOT_INO 2
24177+#define AUFS_FIRST_INO 11
24178+
24179+#define AUFS_WH_PFX ".wh."
24180+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
24181+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
24182+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
24183+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
24184+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
24185+#define AUFS_DIRWH_DEF 3
24186+#define AUFS_RDCACHE_DEF 10 /* seconds */
24187+#define AUFS_RDBLK_DEF 512 /* bytes */
24188+#define AUFS_RDHASH_DEF 32
24189+#define AUFS_WKQ_NAME AUFS_NAME "d"
24190+#define AUFS_NWKQ_DEF 4
24191+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
24192+#define AUFS_PLINK_WARN 100 /* number of plinks */
24193+
24194+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
24195+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
24196+
24197+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
24198+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
24199+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
24200+
24201+/* doubly whiteouted */
24202+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
24203+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
24204+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
24205+
24206+/* branch permission */
24207+#define AUFS_BRPERM_RW "rw"
24208+#define AUFS_BRPERM_RO "ro"
24209+#define AUFS_BRPERM_RR "rr"
24210+#define AUFS_BRPERM_WH "wh"
24211+#define AUFS_BRPERM_NLWH "nolwh"
24212+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
24213+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
24214+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
24215+
24216+/* ---------------------------------------------------------------------- */
24217+
24218+/* ioctl */
24219+enum {
24220+ AuCtl_PLINK_MAINT,
24221+ AuCtl_PLINK_CLEAN
24222+};
24223+
24224+#define AuCtlType 'A'
24225+#define AUFS_CTL_PLINK_MAINT _IO(AuCtlType, AuCtl_PLINK_MAINT)
24226+#define AUFS_CTL_PLINK_CLEAN _IO(AuCtlType, AuCtl_PLINK_CLEAN)
24227+
24228+#endif /* __AUFS_TYPE_H__ */
dece6358
AM
24229diff -urN linux-2.6.30.org/include/linux/Kbuild linux-2.6.30/include/linux/Kbuild
24230--- linux-2.6.30.org/include/linux/Kbuild 2009-06-10 05:05:27.000000000 +0200
24231+++ linux-2.6.30/include/linux/Kbuild 2009-07-21 09:13:25.239966985 +0200
24232@@ -34,6 +34,7 @@
24233 header-y += atmsap.h
24234 header-y += atmsvc.h
24235 header-y += atm_zatm.h
24236+header-y += aufs_type.h
24237 header-y += auto_fs4.h
24238 header-y += ax25.h
24239 header-y += b1lli.h
24240diff -urN linux-2.6.30.org/include/linux/namei.h linux-2.6.30/include/linux/namei.h
24241--- linux-2.6.30.org/include/linux/namei.h 2009-06-10 05:05:27.000000000 +0200
24242+++ linux-2.6.30/include/linux/namei.h 2009-07-21 09:13:29.216632034 +0200
24243@@ -74,6 +74,9 @@
1facf9fc 24244 extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
24245 extern void release_open_intent(struct nameidata *);
24246
24247+extern struct dentry *lookup_hash(struct nameidata *nd);
24248+extern int __lookup_one_len(const char *name, struct qstr *this,
24249+ struct dentry *base, int len);
24250 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
24251 extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
24252
dece6358
AM
24253diff -urN linux-2.6.30.org/include/linux/splice.h linux-2.6.30/include/linux/splice.h
24254--- linux-2.6.30.org/include/linux/splice.h 2009-06-10 05:05:27.000000000 +0200
24255+++ linux-2.6.30/include/linux/splice.h 2009-07-21 09:13:29.234192642 +0200
24256@@ -83,4 +83,10 @@
1facf9fc 24257 extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
24258 splice_direct_actor *);
24259
0fc653ad 24260+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
1facf9fc 24261+ loff_t *ppos, size_t len, unsigned int flags);
0fc653ad 24262+extern long do_splice_to(struct file *in, loff_t *ppos,
1facf9fc 24263+ struct pipe_inode_info *pipe, size_t len,
24264+ unsigned int flags);
24265+
24266 #endif
dece6358
AM
24267diff -urN linux-2.6.30.org/security/device_cgroup.c linux-2.6.30/security/device_cgroup.c
24268--- linux-2.6.30.org/security/device_cgroup.c 2009-06-10 05:05:27.000000000 +0200
24269+++ linux-2.6.30/security/device_cgroup.c 2009-07-21 09:13:29.234192642 +0200
24270@@ -512,6 +512,7 @@
24271
24272 return -EPERM;
24273 }
24274+EXPORT_SYMBOL(devcgroup_inode_permission);
24275
24276 int devcgroup_inode_mknod(int mode, dev_t dev)
24277 {
24278diff -urN linux-2.6.30.org/security/security.c linux-2.6.30/security/security.c
24279--- linux-2.6.30.org/security/security.c 2009-06-10 05:05:27.000000000 +0200
24280+++ linux-2.6.30/security/security.c 2009-07-21 09:13:29.234192642 +0200
24281@@ -389,6 +389,7 @@
24282 return 0;
24283 return security_ops->path_mkdir(path, dentry, mode);
24284 }
24285+EXPORT_SYMBOL(security_path_mkdir);
24286
24287 int security_path_rmdir(struct path *path, struct dentry *dentry)
24288 {
24289@@ -396,6 +397,7 @@
24290 return 0;
24291 return security_ops->path_rmdir(path, dentry);
24292 }
24293+EXPORT_SYMBOL(security_path_rmdir);
24294
24295 int security_path_unlink(struct path *path, struct dentry *dentry)
24296 {
24297@@ -403,6 +405,7 @@
24298 return 0;
24299 return security_ops->path_unlink(path, dentry);
24300 }
24301+EXPORT_SYMBOL(security_path_unlink);
24302
24303 int security_path_symlink(struct path *path, struct dentry *dentry,
24304 const char *old_name)
24305@@ -411,6 +414,7 @@
24306 return 0;
24307 return security_ops->path_symlink(path, dentry, old_name);
24308 }
24309+EXPORT_SYMBOL(security_path_symlink);
24310
24311 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
24312 struct dentry *new_dentry)
24313@@ -419,6 +423,7 @@
24314 return 0;
24315 return security_ops->path_link(old_dentry, new_dir, new_dentry);
24316 }
24317+EXPORT_SYMBOL(security_path_link);
24318
24319 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
24320 struct path *new_dir, struct dentry *new_dentry)
24321@@ -429,6 +434,7 @@
24322 return security_ops->path_rename(old_dir, old_dentry, new_dir,
24323 new_dentry);
24324 }
24325+EXPORT_SYMBOL(security_path_rename);
24326
24327 int security_path_truncate(struct path *path, loff_t length,
24328 unsigned int time_attrs)
24329@@ -437,6 +443,7 @@
24330 return 0;
24331 return security_ops->path_truncate(path, length, time_attrs);
24332 }
24333+EXPORT_SYMBOL(security_path_truncate);
24334 #endif
24335
24336 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
24337@@ -508,6 +515,7 @@
24338 return 0;
24339 return security_ops->inode_readlink(dentry);
24340 }
24341+EXPORT_SYMBOL(security_inode_readlink);
24342
24343 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
24344 {
24345@@ -522,6 +530,7 @@
24346 return 0;
24347 return security_ops->inode_permission(inode, mask);
24348 }
24349+EXPORT_SYMBOL(security_inode_permission);
24350
24351 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
24352 {
24353@@ -622,6 +631,7 @@
24354 {
24355 return security_ops->file_permission(file, mask);
24356 }
24357+EXPORT_SYMBOL(security_file_permission);
24358
24359 int security_file_alloc(struct file *file)
24360 {
This page took 3.699948 seconds and 4 git commands to generate.