Author: wmb Date: Sat Apr 7 01:05:35 2012 New Revision: 2939 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2939
Log: Ext2/3/4 file system journal recovery - OLPC trac 11762 - Fixed list management problem that could result in missing list nodes in the journal overlay and revocation lists.
Modified: forth/lib/linklist.fth ofw/fs/ext2fs/recovery.fth
Modified: forth/lib/linklist.fth ============================================================================== --- forth/lib/linklist.fth Fri Apr 6 11:32:55 2012 (r2938) +++ forth/lib/linklist.fth Sat Apr 7 01:05:35 2012 (r2939) @@ -45,6 +45,11 @@ \ for each node in the list. Returns the node for which "acf" \ returned "true", and also the preceding node. See the comments \ in the code for more information. +\ +\ find-node? ( ??? list acf -- ??? false | ??? node true ) +\ Searches the linked list "list", executing the procedure "acf" +\ for each node in the list. Returns the node and true if found, +\ or false if not found.
alias list: variable
@@ -58,6 +63,8 @@
alias >next-node @ ( node-adr -- next-node-adr )
+: list-end? ( node-adr -- flag ) >next-node @ 0= ; + \ Inserts "new-node" into a linked list after "prev-node" (and before \ the node which was the successor of "prev-node").
@@ -112,6 +119,14 @@ r> r> r> drop ( ??? prev-node this-node ) ;
+: find-node? ( ??? list acf -- ??? false | ??? node true ) + find-node ?dup if ( ??? prev-node this-node ) + nip true ( ??? node true ) + else ( ??? prev-node ) + drop false ( ??? false ) + then ( ??? false | ??? node true ) +; + \ Here's how "find-node" could be used to locate the insertion point \ for a list sorted in ascending order of the second field.
Modified: ofw/fs/ext2fs/recovery.fth ============================================================================== --- ofw/fs/ext2fs/recovery.fth Fri Apr 6 11:32:55 2012 (r2938) +++ ofw/fs/ext2fs/recovery.fth Sat Apr 7 01:05:35 2012 (r2939) @@ -160,7 +160,8 @@ /n field >r_sequence nodetype: revoke-node
-list: revoke-list +instance variable revoke-list +revoke-list off
: free-revoke-list ( -- ) begin revoke-list >next-node while ( ) @@ -169,44 +170,40 @@ repeat ( ) ;
-: block#> ( d.block# 'node -- d.block# flag ) - >r_block# 2@ 2over d< +\ Worker function for find-node? +: block#= ( d.block# 'node -- d.block# flag ) + >r_block# 2@ 2over d= ;
\ node is either the found one or the insertion point -: find-revoked ( d.block# -- d.block# node found? ) - revoke-list ['] block#> find-node if ( d.block# node ) - 3dup >r_block# 2@ d= ( d.block# node found? ) - else ( d.block# node ) - false ( d.block# node found? ) - then ( d.block# node found? ) +: find-revoked? ( d.block# -- d.block# false | d.block# node found? ) + revoke-list ['] block#= find-node? ;
0 value next-commit-id
: revoked? ( d.block# -- revoked? ) - find-revoked if ( d.block# node ) - nip nip ( node ) - >r_sequence @ ( sequence# ) - next-commit-id = ( revoked? ) - else ( d.block# node ) - 3drop false ( revoked? ) - then ( revoked? ) + find-revoked? if ( d.block# node ) + nip nip ( node ) + >r_sequence @ ( sequence# ) + next-commit-id = ( revoked? ) + else ( d.block# ) + 2drop false ( revoked? ) + then ( revoked? ) ;
: set-revoke ( d.block# -- ) - find-revoked if ( d.block# node ) + find-revoked? if ( d.block# node ) nip nip ( node ) next-commit-id over >r_sequence @ - 0>= if ( node ) next-commit-id over >r_sequence ! ( node ) then ( node ) drop ( ) - else ( d.block# node ) - -rot ( node d.block# ) - revoke-node allocate-node >r ( node d.block# r: newnode ) - r@ >r_block# 2! ( node r: newnode ) - next-commit-id r@ >r_sequence ! ( node r: newnode ) - r> swap insert-after ( ) + else ( d.block# ) + revoke-node allocate-node >r ( d.block# r: newnode ) + r@ >r_block# 2! ( r: newnode ) + next-commit-id r@ >r_sequence ! ( r: newnode ) + r> revoke-list insert-after ( ) then ( ) ;
@@ -216,7 +213,8 @@ /n field >o_escaped? nodetype: overlay-node
-list: overlay-list +instance variable overlay-list +overlay-list off
: free-overlay-list ( -- ) begin overlay-list >next-node while ( ) @@ -225,13 +223,8 @@ repeat ( ) ;
-\ node is either the found one or the insertion point -: find-overlay? ( d.block# -- d.block# node found? ) - overlay-list ['] block#> find-node if ( d.block# node ) - 3dup >r_block# 2@ d= ( d.block# node found? ) - else ( d.block# node ) - false ( d.block# node found? ) - then ( d.block# node found? ) +: find-overlay? ( d.block# -- d.block# false | d.block# node true ) + overlay-list ['] block#= find-node? ;
: j-read-file-block ( adr lblk# -- ) @@ -245,8 +238,7 @@ else ( adr ) drop ( ) then ( ) - else ( adr d.pblk# node ) - drop ( adr d.pblk# ) + else ( adr d.pblk# ) d.block swap bsize move ( ) then ( ) else ( adr ) @@ -266,11 +258,10 @@ : note-jblock ( d.block# escaped? log-blk# -- ) 2swap find-overlay? if ( escaped? log-blk# d.block# node ) set-overlay-node ( ) - else ( escaped? log-blk# d.block# node ) - >r ( escaped? log-blk# d.block# r: prev-node ) - >r overlay-node allocate-node ( d.block# escaped? log-blk# newnode r: prevnode ) - dup >r set-overlay-node ( r: prevnode newnode ) - r> r> insert-after ( ) + else ( escaped? log-blk# d.block# ) + overlay-node allocate-node >r ( d.block# escaped? log-blk# r: newnode ) + r@ set-overlay-node ( r: newnode ) + r> overlay-list insert-after ( ) then ;
@@ -408,6 +399,7 @@ then ; : commit-journal ( -- ) + j-read-only? if exit then jsb >s_sequence dup be-l@ 1+ swap be-l! 0 jsb >s_start be-l! jsb 0 write-file-block @@ -416,7 +408,10 @@ : process-journal ( -- ) read-journal if exit then
-." Recovering from journal ... " + ." Recovering from journal " + j-read-only? if ." (read-only)" then + ." ... " + 0 to end-transaction
0 ['] one-pass catch ?dup if @@ -443,4 +438,3 @@ free-journal cr ; -\ XXX need to do free-overlay-list in close
openfirmware@openfirmware.info