[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