VFS: mounts KFS, shell functions
[akaros.git] / Documentation / vfs.txt
1 Unorganized Notes on the Virtual File System
2 -------------------------------------
3 Our VFS is built similarly to Linux's, mostly because I'd like to have somewhat
4 easy integration with ext2 (or at the very least have our own FS that can
5 integrate into Linux easily).
6
7 There are four main objects in a filesystem: superblock, inode, dentry, and a
8 file.  
9         - Superblock: Specific instance of a mounted filesystem.  All
10           synchronization is done with the one spinlock.
11         - Inode: represents a specific file
12         - Dentry: in memory object, corresponding to an element of a path.  E.g. /,
13           usr, bin, and vim are all dentries.  All have inodes.  Vim happens to be a
14           file instead of a directory.
15         - File: represents a file opened by a process.
16
17 So far, dentries are the most complicated, so here are some notes about them.
18 These are probably self-consistent, but may be a bit old (or just wrong) because
19 I wrote them as I put the VFS together:
20
21 A dentry is just a connection between a part of a path and an inode.  We just
22 want to walk from dentry to dentry, asking each to find the next part in the
23 path.  When you hit a dentry that's not the end of the desired path, you ask its
24 inode for the next dentry by using it's operation (lookup).
25
26 lookup() takes the inode of the directory (or 0 for the root) and a dentry
27 (already allocated, with the d_name and i_name filled in), and it will find the
28 correct inode for the given dentry, as well as filling out any specific FS
29 things in the dentry (like d_ops).  It will return 0 on failure, or the dentry
30 pointer passed in on success.  Somehow the nameidata bit will be used too.  This
31 will probably change a bit...  Note that lookup() needs to read the actual
32 directory file and also lookup the inode off the disc, which means it will
33 block.
34
35 When the next dentry is a mountpoint, (e.g. /mnt/cdrom), when you ask mnt for
36 cdrom, lookup() will parse it's file (a directory) and see 'cdrom' there as a child
37 entry.  Then it will return cdrom's dentry, like always.
38
39 But since cdrom was a mountpoint, (which you can see from the d_mount_point),
40 you need to walk through the structures a bit to get the dentry of the FS rooted
41 at that mountpoint to keep walking.  The VFS can handle that, so lookup()
42 doesn't need to worry about it.
43
44 Why are there two dentries associated with a vfsmount?  Normally, a dentry for a
45 directory points to an inode that contains its members.  When a FS is mounted
46 over it, we don't want to destroy that.  Instead, we mark it as a mountpoint,
47 and when following, we walk into the next FS.  The mountpoint is the dentry in
48 the parent mount (using the parent mount's FS superblock), and the root is the
49 dentry of the mounted FS, using the FS superblock of the mounted FS.
50
51 Sometimes lookup() will not be called at all.  We want to look for present
52 dentries first (ones that exist in memory already, including all of those with a
53 refcnt).  So we can look in the cache (currently just an SLIST, but will
54 eventually be a hash table).  When hitting in the cache (hashed by dentry name,
55 and probably the parent dir), we need to verify that the dentry's parent is our
56 own (handled by the VFS code).  All vfsmount dentries will be in the cache,
57 since they all have a refcnt (the vfsmount struct points to them).
58
59 Dentries for / and pwd and whatnot have a refcnt (pointed to by fs_struct,
60 vfsmounts, etc).  Anything with a pointer to it has a refcnt, so it never goes
61 away.  So if we have an inode in memory, it's entire dentry path is cached,
62 (just follow the parent pointers back).  Note that when a dentry's refcnt hits
63 0, we do *not* deallocate (like we do with many other structures).  It will just
64 be on the LRU list in the dcache system.  Likewise, every dentry points to its
65 inode, which pins that inode in memory.
66
67 Other refcnts: just about everything has a refcnt, and we need to be careful
68 about when we want to use them and dealloc.  Some things would be a pain in the
69 ass, like with the super_block refcnt.  Every dentry has a ref to the SB, but
70 changing that ref every time we add or remove a dentry will probably be an
71 unnecessary penalty if we can ensure all dentries of that FS are gone before
72 removing the superblock through another mechanism.  We'll see.  Mostly, this
73 just means we need to think about what we really want from a refcnt, and whether
74 or not we want the kref / process style refcnting.
75
76 Mounting:
77
78 When you mount, you need to read in the super block and connect the relevant
79 data structures together.  The SB is connected to the vfsmount, which is
80 connected to the dentry of the mount point and the dentry of the root of the FS.
81 This means when mounting the FS, we need to create the dentry for "/", which
82 means we also need the inode, which needs to be read_inode()'d in.  Actually, we
83 might not need to read the inode in right away - we might be able to get away
84 with reading them in on-demand.
85
86 All of this means that for every mount point, the SB, vfsmount, dentry, and
87 inode are in memory.  Due to the way dentries link, every dentry and inode back
88 up to the real root are all in memory too.  Having a mount point is like having
89 a process working in that directory - the chain back up is pinned.