]> git.neil.brown.name Git - LaFS.git/blob - block.doc
README update
[LaFS.git] / block.doc
1
2 Data of files (including directories, and even the inode file
3 which holds all inodes) are kept in the page cache.
4
5 We attach an array of "struct datablock" via the 'private' pointer.
6 These datablocks point back to the page but do not own a reference.
7 When the datablocks are detached from the page at truncate time, 
8 they temporarily get to hold a reference until the last one is released.
9
10 Each inode also points to it's dblock, and the dblock has a my_inode
11 pointer to the inode.
12 my_inode is a counted reference so the inode will outlive the dblock.
13 So if we have a reference on the dblock, we can follow my_inode, and
14 get to the ->dblock backpointer. It can be cleared under private_lock
15 for the inode (not the fileset).
16
17 When all datablocks on a page have a refcount of zero, and all
18 are Valid (so the page is Uptodate) the ->private pointer can be
19 cleared and the data blocks can be freed.
20 This will happen by releasepage being called immediately after
21 a fullpage read completes (if that works).
22
23 A Dirty or Realloc block will never be freed.
24
25
26 There are two ways that the VM can request that we remove the
27 ->private attachment to a page. releasepage and invalidatepage
28
29 Releasepage is called when idle clean pages are being freed.
30   It is unlikely that the datablock will be in use, but if it is
31     it can simply fail the request.
32 Invalidatepage is called when a page is being removed either by
33    truncate or when an inode is being evicted.  In this case there
34    should be no active references and no new references can be taken
35    so the consequent releasepage should succeed.
36    BUT a block on a page being invalidated could have unincorporated
37      changes for the next phase. FIXME.
38
39 IT IS NOT TRUE THAT So there is no reason ever to have datablocks without the page,
40 but there can be pages without a datablock.  This would be appropriate
41 for a file that is read and cached read-only such as an executable.
42
43 So...
44   A page points to a dblock array but does not hold a refcount.
45   It can be accessed under private_lock for the address space holding the page.
46   The dblock array disappears when the page is released, or when
47    the dblock array has done it's time on a freelist
48
49   A dblock points to the page but does not hold an explicit reference.
50    Instead there is an implicit reference which releasepage checks for.
51
52   A dblock in an inodefile hold a counted reference to the inode, which
53    hold an uncounted (sometimes) reference back.  This loop can only
54    be broken under private_lock for the inode.
55
56   When a dblock array for a regular file appears unnecessary it goes onto
57    a freelist and can be freed.  For an inodefile, this does not happen.
58    The dblock array is not freed until the page is released.
59
60   
61 ----------------------
62 No.  I don't like the global lock for the freelist being held so much.
63 Let's scrap that idea.
64 We never detach the dblock array from a page until we are ready to free it.
65 When we read a whole page in - not for preparing to write - we free
66 the whole dblock array straight away.
67
68 So we still need private_lock to take a reference.
69 When we drop the last reference, we just leave it there.
70 After a successful readpage, we call release_page to release the private
71 data if it is not in use.
72
73
74 NOTE:
75  While a dblock should always have a page, there is a brief time when it
76 does not.  This makes accounting etc easier.
77 When a dblock array is disconnected from the page, the ->page pointer
78 is cleared.  From this point on, no new references can be taken on the
79 dblocks.