4058b8ac5b4b9b4945cbc126a6202208a6c7698c
[pandora-kernel.git] / Documentation / filesystems / aufs / design / 03lookup.txt
1
2 # Copyright (C) 2005-2011 Junjiro R. Okajima
3
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 Lookup in a Branch
19 ----------------------------------------------------------------------
20 Since aufs has a character of sub-VFS (see Introduction), it operates
21 lookup for branches as VFS does. It may be a heavy work. Generally
22 speaking struct nameidata is a bigger structure and includes many
23 information. But almost all lookup operation in aufs is the simplest
24 case, ie. lookup only an entry directly connected to its parent. Digging
25 down the directory hierarchy is unnecessary.
26
27 VFS has a function lookup_one_len() for that use, but it is not usable
28 for a branch filesystem which requires struct nameidata. So aufs
29 implements a simple lookup wrapper function. When a branch filesystem
30 allows NULL as nameidata, it calls lookup_one_len(). Otherwise it builds
31 a simplest nameidata and calls lookup_hash().
32 Here aufs applies "a principle in NFSD", ie. if the filesystem supports
33 NFS-export, then it has to support NULL as a nameidata parameter for
34 ->create(), ->lookup() and ->d_revalidate(). So the lookup wrapper in
35 aufs tests if ->s_export_op in the branch is NULL or not.
36
37 When a branch is a remote filesystem, aufs basically trusts its
38 ->d_revalidate(), also aufs forces the hardest revalidate tests for
39 them.
40 For d_revalidate, aufs implements three levels of revalidate tests. See
41 "Revalidate Dentry and UDBA" in detail.
42
43
44 Loopback Mount
45 ----------------------------------------------------------------------
46 Basically aufs supports any type of filesystem and block device for a
47 branch (actually there are some exceptions). But it is prohibited to add
48 a loopback mounted one whose backend file exists in a filesystem which is
49 already added to aufs. The reason is to protect aufs from a recursive
50 lookup. If it was allowed, the aufs lookup operation might re-enter a
51 lookup for the loopback mounted branch in the same context, and will
52 cause a deadlock.
53
54
55 Revalidate Dentry and UDBA (User's Direct Branch Access)
56 ----------------------------------------------------------------------
57 Generally VFS helpers re-validate a dentry as a part of lookup.
58 0. digging down the directory hierarchy.
59 1. lock the parent dir by its i_mutex.
60 2. lookup the final (child) entry.
61 3. revalidate it.
62 4. call the actual operation (create, unlink, etc.)
63 5. unlock the parent dir
64
65 If the filesystem implements its ->d_revalidate() (step 3), then it is
66 called. Actually aufs implements it and checks the dentry on a branch is
67 still valid.
68 But it is not enough. Because aufs has to release the lock for the
69 parent dir on a branch at the end of ->lookup() (step 2) and
70 ->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
71 held by VFS.
72 If the file on a branch is changed directly, eg. bypassing aufs, after
73 aufs released the lock, then the subsequent operation may cause
74 something unpleasant result.
75
76 This situation is a result of VFS architecture, ->lookup() and
77 ->d_revalidate() is separated. But I never say it is wrong. It is a good
78 design from VFS's point of view. It is just not suitable for sub-VFS
79 character in aufs.
80
81 Aufs supports such case by three level of revalidation which is
82 selectable by user.
83 1. Simple Revalidate
84    Addition to the native flow in VFS's, confirm the child-parent
85    relationship on the branch just after locking the parent dir on the
86    branch in the "actual operation" (step 4). When this validation
87    fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
88    checks the validation of the dentry on branches.
89 2. Monitor Changes Internally by Inotify/Fsnotify
90    Addition to above, in the "actual operation" (step 4) aufs re-lookup
91    the dentry on the branch, and returns EBUSY if it finds different
92    dentry.
93    Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
94    during it is in cache. When the event is notified, aufs registers a
95    function to kernel 'events' thread by schedule_work(). And the
96    function sets some special status to the cached aufs dentry and inode
97    private data. If they are not cached, then aufs has nothing to
98    do. When the same file is accessed through aufs (step 0-3) later,
99    aufs will detect the status and refresh all necessary data.
100    In this mode, aufs has to ignore the event which is fired by aufs
101    itself.
102 3. No Extra Validation
103    This is the simplest test and doesn't add any additional revalidation
104    test, and skip therevalidatin in step 4. It is useful and improves
105    aufs performance when system surely hide the aufs branches from user,
106    by over-mounting something (or another method).