Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) The Linux Journalling API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) =========================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) Overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) Details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) ~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) The journalling layer is easy to use. You need to first of all create a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) journal_t data structure. There are two calls to do this dependent on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) how you decide to allocate the physical media on which the journal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) resides. The jbd2_journal_init_inode() call is for journals stored in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) filesystem inodes, or the jbd2_journal_init_dev() call can be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) for journal stored on a raw device (in a continuous range of blocks). A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) journal_t is a typedef for a struct pointer, so when you are finally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) finished make sure you call jbd2_journal_destroy() on it to free up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) any used kernel memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) Once you have got your journal_t object you need to 'mount' or load the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) journal file. The journalling layer expects the space for the journal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) was already allocated and initialized properly by the userspace tools.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) When loading the journal you must call jbd2_journal_load() to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) journal contents. If the client file system detects the journal contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) does not need to be processed (or even need not have valid contents), it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) may call jbd2_journal_wipe() to clear the journal contents before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) calling jbd2_journal_load().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) Note that jbd2_journal_wipe(..,0) calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) jbd2_journal_skip_recovery() for you if it detects any outstanding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) transactions in the journal and similarly jbd2_journal_load() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) call jbd2_journal_recover() if necessary. I would advise reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) ext4_load_journal() in fs/ext4/super.c for examples on this stage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) Now you can go ahead and start modifying the underlying filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) Almost.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) You still need to actually journal your filesystem changes, this is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) by wrapping them into transactions. Additionally you also need to wrap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) the modification of each of the buffers with calls to the journal layer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) so it knows what the modifications you are actually making are. To do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) this use jbd2_journal_start() which returns a transaction handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) jbd2_journal_start() and its counterpart jbd2_journal_stop(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) which indicates the end of a transaction are nestable calls, so you can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) reenter a transaction if necessary, but remember you must call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) jbd2_journal_stop() the same number of times as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) jbd2_journal_start() before the transaction is completed (or more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) accurately leaves the update phase). Ext4/VFS makes use of this feature to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) simplify handling of inode dirtying, quota support, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) Inside each transaction you need to wrap the modifications to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) individual buffers (blocks). Before you start to modify a buffer you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) need to call jbd2_journal_get_create_access() /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) jbd2_journal_get_write_access() /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) jbd2_journal_get_undo_access() as appropriate, this allows the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) journalling layer to copy the unmodified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) data if it needs to. After all the buffer may be part of a previously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) uncommitted transaction. At this point you are at last ready to modify a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) buffer, and once you are have done so you need to call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) jbd2_journal_dirty_metadata(). Or if you've asked for access to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) buffer you now know is now longer required to be pushed back on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) device you can call jbd2_journal_forget() in much the same way as you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) might have used bforget() in the past.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) A jbd2_journal_flush() may be called at any time to commit and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) checkpoint all your transactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) Then at umount time , in your put_super() you can then call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) jbd2_journal_destroy() to clean up your in-core journal object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) Unfortunately there a couple of ways the journal layer can cause a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) deadlock. The first thing to note is that each task can only have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) single outstanding transaction at any one time, remember nothing commits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) until the outermost jbd2_journal_stop(). This means you must complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) the transaction at the end of each file/inode/address etc. operation you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) perform, so that the journalling system isn't re-entered on another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) journal. Since transactions can't be nested/batched across differing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) journals, and another filesystem other than yours (say ext4) may be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) modified in a later syscall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) The second case to bear in mind is that jbd2_journal_start() can block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) if there isn't enough space in the journal for your transaction (based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) on the passed nblocks param) - when it blocks it merely(!) needs to wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) for transactions to complete and be committed from other tasks, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) essentially we are waiting for jbd2_journal_stop(). So to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) deadlocks you must treat jbd2_journal_start() /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) jbd2_journal_stop() as if they were semaphores and include them in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) your semaphore ordering rules to prevent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) deadlocks. Note that jbd2_journal_extend() has similar blocking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) behaviour to jbd2_journal_start() so you can deadlock here just as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) easily as on jbd2_journal_start().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) Try to reserve the right number of blocks the first time. ;-). This will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) be the maximum number of blocks you are going to touch in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) transaction. I advise having a look at at least ext4_jbd.h to see the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) basis on which ext4 uses to make these decisions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) Another wriggle to watch out for is your on-disk block allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) strategy. Why? Because, if you do a delete, you need to ensure you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) haven't reused any of the freed blocks until the transaction freeing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) these blocks commits. If you reused these blocks and crash happens,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) there is no way to restore the contents of the reallocated blocks at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) end of the last fully committed transaction. One simple way of doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) this is to mark blocks as free in internal in-memory block allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) structures only after the transaction freeing them commits. Ext4 uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) journal commit callback for this purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) With journal commit callbacks you can ask the journalling layer to call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) a callback function when the transaction is finally committed to disk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) so that you can do some of your own management. You ask the journalling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) layer for calling the callback by simply setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ``journal->j_commit_callback`` function pointer and that function is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) called after each transaction commit. You can also use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ``transaction->t_private_list`` for attaching entries to a transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) that need processing when the transaction commits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) JBD2 also provides a way to block all transaction updates via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) jbd2_journal_lock_updates() /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) jbd2_journal_unlock_updates(). Ext4 uses this when it wants a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) window with a clean and stable fs for a moment. E.g.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)         jbd2_journal_lock_updates() //stop new stuff happening..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)         jbd2_journal_flush()        // checkpoint everything.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)         ..do stuff on stable fs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)         jbd2_journal_unlock_updates() // carry on with filesystem use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) The opportunities for abuse and DOS attacks with this should be obvious,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if you allow unprivileged userspace to trigger codepaths containing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) these calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) Fast commits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) JBD2 to also allows you to perform file-system specific delta commits known as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fast commits. In order to use fast commits, you will need to set following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) callbacks that perform correspodning work:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) `journal->j_fc_cleanup_cb`: Cleanup function called after every full commit and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) fast commit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) `journal->j_fc_replay_cb`: Replay function called for replay of fast commit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) File system is free to perform fast commits as and when it wants as long as it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) gets permission from JBD2 to do so by calling the function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) :c:func:`jbd2_fc_begin_commit()`. Once a fast commit is done, the client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) file  system should tell JBD2 about it by calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) :c:func:`jbd2_fc_end_commit()`. If file system wants JBD2 to perform a full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) commit immediately after stopping the fast commit it can do so by calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) :c:func:`jbd2_fc_end_commit_fallback()`. This is useful if fast commit operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fails for some reason and the only way to guarantee consistency is for JBD2 to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) perform the full traditional commit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) JBD2 helper functions to manage fast commit buffers. File system can use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) :c:func:`jbd2_fc_get_buf()` and :c:func:`jbd2_fc_wait_bufs()` to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) and wait on IO completion of fast commit buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) Currently, only Ext4 implements fast commits. For details of its implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) of fast commits, please refer to the top level comments in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) fs/ext4/fast_commit.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) Summary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) Using the journal is a matter of wrapping the different context changes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) being each mount, each modification (transaction) and each changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) buffer to tell the journalling layer about them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) Data Types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) The journalling layer uses typedefs to 'hide' the concrete definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) of the structures used. As a client of the JBD2 layer you can just rely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) on the using the pointer as a magic cookie of some sort. Obviously the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) hiding is not enforced as this is 'C'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) Structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .. kernel-doc:: include/linux/jbd2.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)    :internal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) Functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ---------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) The functions here are split into two groups those that affect a journal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) as a whole, and those which are used to manage transactions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) Journal Level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .. kernel-doc:: fs/jbd2/journal.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)    :export:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .. kernel-doc:: fs/jbd2/recovery.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)    :internal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) Transasction Level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .. kernel-doc:: fs/jbd2/transaction.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) See also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) `Journaling the Linux ext2fs Filesystem, LinuxExpo 98, Stephen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) Tweedie <http://kernel.org/pub/linux/kernel/people/sct/ext3/journal-design.ps.gz>`__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) `Ext3 Journalling FileSystem, OLS 2000, Dr. Stephen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) Tweedie <http://olstrans.sourceforge.net/release/OLS2000-ext3/OLS2000-ext3.html>`__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)