[openfirmware] [commit] r2636 - ofw/fs/ext2fs
repository service
svn at openfirmware.info
Sat Oct 22 05:40:39 CEST 2011
Author: wmb
Date: Sat Oct 22 05:40:39 2011
New Revision: 2636
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2636
Log:
Initial checkin of barely-tested code to handle ext3/4 journals.
Added:
ofw/fs/ext2fs/recovery.fth
Added: ofw/fs/ext2fs/recovery.fth
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ ofw/fs/ext2fs/recovery.fth Sat Oct 22 05:40:39 2011 (r2636)
@@ -0,0 +1,362 @@
+h# c03b3998 constant jbd_magic
+
+struct
+ /l field >h_magic
+ /l field >h_blocktype
+ /l field >h_sequence
+constant /journal-header
+
+/journal-header
+ /c field >h_chksum_type
+ /c field >h_chksum_size
+ 2 /c* \ Padding
+ 4 /l* field >h_chksum
+ 2 /l* field >h_commit_sec
+ /l field >h_commit_nsec
+constant /commit-header
+
+/journal-header
+ /l field >r_count
+constant /revoke-header
+
+struct
+ /l field >t_blocknr
+ /l field >t_flags
+dup constant /tag32
+ /l field >t_blocknr_high
+constant /tag64
+
+/journal-header
+ /l field >s_blocksize
+ /l field >s_maxlen
+ /l field >s_first
+ /l field >s_sequence
+ /l field >s_start
+ /l field >s_errno
+ /l field >s_feature_compat
+ /l field >s_feature_incompat
+ /l field >s_feature_ro_compat
+ \ We don't need the rest
+drop
+
+0 value j-buf
+0 value j-compat
+0 value j-incompat
+0 value j-blocksize
+0 value j-first
+0 value j-last
+0 value j-start
+0 value j-sequence
+0 value tag-bytes
+
+0 value jsb
+0 value bh
+0 value obh
+: free-journal ( -- )
+ jsb if jsb bsize free-mem 0 to jsb then
+ bh if bh j-blocksize free-mem 0 to bh then
+ obh if obh j-blocksize free-mem 0 to obh then
+;
+: read-journal ( -- skip? )
+ bsize alloc-mem to jsb
+ 8 set-inode \ 8 is the well-known inode# for the journal
+ jsb 0 read-file-block ( )
+
+ jsb >h_magic be-l@ jbd_magic <> if
+ free-journal true exit ( -- skip? )
+ then
+
+ jsb >h_blocktype be-l@ 3 4 between 0= if
+ \ Not superblock
+ free-journal true exit ( -- skip? )
+ then
+
+ jsb >s_start be-l@ to j-start
+ jsb 0= if
+ free-journal true exit ( -- skip? )
+ then
+
+ jsb >s_blocksize be-l@ to j-blocksize ( )
+
+ j-blocksize bsize <> if
+ ." Journal block size != filesystem block size" cr
+ free-journal true exit ( -- skip? )
+ then
+
+ j-blocksize alloc-mem to bh ( )
+ j-blocksize alloc-mem to obh ( )
+
+ jsb >s_sequence be-l@ to j-sequence ( )
+ jsb >s_first be-l@ to j-first ( )
+ jsb >s_maxlen be-l@ to j-last ( )
+
+ jsb >s_feature_compat be-l@ to j-compat ( )
+ jsb >s_feature_incompat be-l@ to j-incompat ( )
+
+ j-incompat 2 and if /tag64 else /tag32 then to tag-bytes \ 2:FEATURE_INCOMPAT_64BIT
+
+ false ( skip? )
+;
+
+: +wrap ( n increment -- n' )
+ + dup j-last >= if
+ j-last - j-first +
+ then
+;
+
+0 value tagend
+0 value tagp
+: first-tag ( -- )
+ bh j-blocksize + to tagend ( )
+ bh /journal-header + to tagp ( )
+;
+: +tagp ( -- end? )
+ tagp >t_flags be-l@ ( flags )
+ tagp tag-bytes + ( flags tagp )
+ over 2 and 0= if d# 16 + then ( flags tagp ) \ 2:FLAG_SAME_UUID
+ to tagp ( flags )
+ 8 and if ( ) \ 8:FLAG_LAST_TAG
+ true ( end? )
+ else ( )
+ tagp tagend >= ( end? )
+ then ( end? )
+;
+: count-tags ( -- count )
+ 0 ( count )
+ first-tag begin 1+ +tagp until ( count end? )
+;
+
+: write-jblock ( d.block# adr -- )
+ -rot drop write-fs-block ( error? )
+\ j-blocksize 2swap ( adr len d.block# )
+\ j-blocksize du* ( adr len d.byte# )
+\ write-bytes
+ if ." Journal recovery write error" cr abort then
+;
+
+0 value next-log-block
+: next-jblock ( buf -- )
+ next-log-block read-file-block ( )
+ next-log-block 1 +wrap to next-log-block ( )
+;
+
+0 value crc32-sum
+: crc32-block ( buf -- )
+ crc32-sum crctab rot j-blocksize ($crc) to crc32-sum
+;
+: calc-chksums ( -- )
+ bh crc32-block
+ count-tags 0 ?do
+ obh next-jblock obh crc32-block
+ loop
+;
+
+listnode
+ /n 2* field >r_block#
+ /n field >r_sequence
+nodetype: revoke-node
+
+list: revoke-list
+
+: free-revoke-list ( -- )
+ begin revoke-list >next-node while ( )
+ revoke-list delete-after ( node )
+ revoke-node free-node ( )
+ repeat ( )
+;
+
+: 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 drop ( d.block# node )
+ 3dup >r_block# 2@ d= ( d.block# 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? )
+;
+
+: set-revoke ( d.block# -- )
+ 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 ( )
+ then ( )
+;
+
+: replay-tag ( -- )
+ obh next-jblock ( )
+
+ tagp >t_blocknr be-l@ ( block# )
+ j-incompat 2 and if ( block# ) \ 2:FEATURE_INCOMPAT_64BIT
+ tagp >t_blocknr_high be-l@ ( d.block# )
+ else ( block# )
+ u>d ( d.block# )
+ then ( d.block# )
+ 2dup revoked? if ( d.block# )
+ 2drop ( )
+ else ( d.block# )
+ tagp >t_flags be-l@ 1 and if ( d.block# ) \ 1:FLAG_ESCAPE
+ jbd_magic obh >data be-l! ( d.block# )
+ then ( d.block# )
+ obh write-jblock ( )
+ then ( )
+;
+
+: replay-descriptor-block ( -- )
+ first-tag begin replay-tag +tagp until ( )
+;
+
+0 value pass
+: scanning? ( -- flag ) pass 0= ;
+: revoking? ( -- flag ) pass 1 = ;
+: replaying? ( -- flag ) pass 2 = ;
+
+0 value end-transaction
+
+: do-descriptor-block ( -- )
+ replaying? if
+ replay-descriptor-block
+ else
+ scanning? if
+ j-compat 1 and if \ FEATURE_COMPAT_CHECKSUM
+ end-transaction 0= if
+ calc-chksums \ Can abort
+ exit \ Continues loop in pass-loop
+ then
+ then
+ then
+ next-log-block count-tags +wrap to next-log-block
+ then
+;
+
+0 value j-failed-commit
+: do-commit-chksum ( -- )
+ bh >h_chksum be-l@ ( sum )
+ end-transaction if ( sum )
+ true to j-failed-commit ( sum )
+ drop exit ( -- )
+ then ( sum )
+
+ dup crc32-sum = ( sum flag )
+ bh >h_chksum_type c@ 1 = and \ 1:CRC32_CHKSUM ( sum flag' )
+ bh >h_chksum_size c@ 4 = and \ 4:CRC32_CHKSUM_SIZE ( sum flag' )
+ if ( sum )
+ drop ( )
+ else ( sum )
+ 0= ( flag )
+ bh >h_chksum_type c@ 0= ( flag' )
+ bh >h_chksum_size c@ 0= and 0= if ( flag' )
+ next-commit-id to end-transaction ( )
+ j-incompat 4 and if ( ) \ 4:FEATURE_INCOMPAT_ASYNC_COMMIT
+ next-commit-id to j-failed-commit ( )
+ abort
+ then ( )
+ then ( )
+ then ( )
+ -1 to crc32-sum ( )
+;
+: do-commit-block ( -- )
+ scanning? if
+ j-compat 1 and if \ FEATURE_COMPAT_CHECKSUM
+ do-commit-chksum
+ then
+ then
+ next-commit-id 1+ to next-commit-id
+;
+
+: be-x@ ( adr -- d ) dup la1+ be-l@ swap be-l@ ;
+: do-revoke-block ( -- )
+ revoking? 0= if exit then
+
+ bh /revoke-header + ( adr )
+ bh >r_count be-l@ bounds ( endadr adr )
+
+ j-incompat 2 and if ( endadr adr ) \ 2:FEATURE_INCOMPAT_64BIT
+ ?do i be-x@ set-revoke 8 +loop ( )
+ else
+ ?do i be-l@ u>d set-revoke 4 +loop ( )
+ then
+;
+
+: pass-loop ( -- )
+ begin
+ scanning? 0= if
+ next-commit-id end-transaction - 0>= if exit then
+ then
+ bh next-jblock ( )
+ bh >h_magic be-l@ jbd_magic <> if ( )
+ exit ( -- )
+ then ( )
+ bh >h_sequence be-l@ next-commit-id <> if ( adr )
+ exit ( -- )
+ then ( )
+ bh >h_blocktype be-l@ case ( )
+ 1 of do-descriptor-block endof ( )
+ 2 of do-commit-block endof ( )
+ 5 of do-revoke-block endof ( )
+ ( default ) drop exit ( )
+ endcase ( )
+ again
+;
+: one-pass ( pass -- )
+ to pass
+ -1 to crc32-sum
+ j-sequence to next-commit-id
+ j-start to next-log-block
+ pass-loop
+ scanning? if
+ end-transaction 0= if
+ next-commit-id to end-transaction
+ then
+ else
+ end-transaction next-commit-id <> abort" Recover end-transaction mismatch"
+ then
+;
+: commit-journal ( -- )
+ 0 jsb >s_start be-l!
+ jsb 0 write-file-block
+ flush
+;
+: process-journal ( -- )
+ read-journal if exit then
+
+ 0 ['] one-pass catch if
+ ." Journal scan failed" cr
+ free-journal exit
+ then
+
+ 1 ['] one-pass catch if
+ ." Journal revoke failed" cr
+ free-revoke-list free-journal exit
+ then
+
+ 2 ['] one-pass catch if
+ ." Journal replay failed" cr
+ free-revoke-list free-journal exit
+ then
+
+ free-revoke-list
+
+ \ commit-journal
+ free-journal
+;
More information about the openfirmware
mailing list