]> git.neil.brown.name Git - LaFS.git/blob - truncate.doc
README update
[LaFS.git] / truncate.doc
1
2 There are two sorts of truncate which have a lot in common,
3 but the differences need to be clearly understood.
4 There is "ftruncate" truncation, and the is final "unlink" truncation.
5
6 Truncate happens lazily as it could require reading lots of index blocks,
7 so we don't really want to wait for it.  In particular, a checkpoint
8 might need to run while truncate is happening.  So we need to always have
9 the tree in a consistent state for write-out.
10
11 When we need to truncate a file, we set i_size appropriately and
12 trunc_next to the address of the first block that might need to be
13 pruned from the file.  While I_Trunc is set, any attempt to extend
14 i_size beyond 'trunc_next' block on ... something.
15
16 truncate_inode_pages is called which calls ->invalidatepage on each
17 page.  This notices that the page is beyond the end-of-file and calls
18 lafs_erase_dblock on each block.
19
20 The inode is then recorded as an orphan and is passed to the orphan handler.
21
22 The orphan handler avoids times when a checkpoint is active, but otherwise:
23    finds the first index-leaf at-or-after trunc_next
24    runs any incorporation that is pending
25    If any addresses still appear in the block, they are de-allocated.
26    The index block itself is de-allocated, and incorporation is run on
27    the parent (think about this some more).
28    trunc_next is advanced.
29
30 When trunc_next reaches the end of the possible address-space, it wakes up
31 whatever a 'write' might be waiting on, makes sure a delete continues.
32 If it was no a delete, the orphan status is revoked.
33
34
35 When a checkpoint happens a partially truncated inode might get written out.
36 This is fine.
37
38 When the orphan handler cleans out an index block, it calls erase_iblock which
39 allocates it to 0 thus allowing incorporation in the parent.
40 If phase allows, incorporate of the parent will be processed.  This may
41 empty the parent and so it's parent will also be open for incorporation.
42 This could collapse the tree from the bottom up, or if top-level
43 collapsing is working, it might collapse from the top down.
44 Either way, if truncating the whole file, the last step will incorporate
45 nothingness into the inode.  If it's type is 0 (no type), the dblock will be
46 erased and the inode released.
47
48 For last-unlink, we set ->type to zero and trunc_next to 0, and
49 everything just happens.
50
51
52 We need some care around the InoIdx block as I currently (aug09) have a problem.
53 When we truncate a file (or directory) the InoIdx block eventually gets
54 erased and so becomes Invalid.  A subsequent create that tries to allocate
55 into that block gets badly confused.
56 So we need some good rules about the InoIdx block and what B_Valid means.