[openfirmware] [commit] r2798 - ofw/fs/ext2fs

repository service svn at openfirmware.info
Wed Jan 4 09:51:42 CET 2012


Author: wmb
Date: Wed Jan  4 09:51:42 2012
New Revision: 2798
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2798

Log:
EXT4 extents support.  OFW can now read, but not write, EXT4 filesystems.

Added:
   ofw/fs/ext2fs/extent.fth
Modified:
   ofw/fs/ext2fs/dir.fth
   ofw/fs/ext2fs/ext2fs.fth
   ofw/fs/ext2fs/layout.fth
   ofw/fs/ext2fs/recovery.fth

Modified: ofw/fs/ext2fs/dir.fth
==============================================================================
--- ofw/fs/ext2fs/dir.fth	Tue Jan  3 03:01:40 2012	(r2797)
+++ ofw/fs/ext2fs/dir.fth	Wed Jan  4 09:51:42 2012	(r2798)
@@ -4,7 +4,7 @@
 decimal
 
 2 constant root-dir#
-0 instance value dir-block#
+0. instance 2value d.dir-block#
 0 instance value lblk#
 
 instance variable diroff
@@ -17,14 +17,17 @@
 0 instance value wf-inum  \ Inumber of file or directory found
 0 instance value wf-type  \ Type - 4 for directory, d# 10 for symlink, etc
 
+: find-dirblk  ( -- )
+   lblk# >d.pblk# 0= abort" EXT2 - missing directory block"  to d.dir-block#
+;
 : get-dirblk  ( -- end? )
    lblk# bsize um* dfile-size d< 0=  if  true exit  then
-   lblk# >pblk# to dir-block#
+   find-dirblk
    false
 ;
 
 \ **** Return the address of the current directory entry
-: dirent  ( -- adr )  dir-block# block diroff @ +  ;
+: dirent  ( -- adr )  d.dir-block# d.block diroff @ +  ;
 \ Dirent fields:
 \ 00.l inode
 \ 04.w offset to next dirent
@@ -87,10 +90,10 @@
 
 \ On entry:
 \   inode# refers to the directory block's inode
-\   dir-block# is the physical block number of the first directory block
+\   d.dir-block# is the physical block number of the first directory block
 \   diroff @ is 0
 \ On successful exit:
-\   dir-block# is the physical block number of the current directory block
+\   d.dir-block# is the physical block number of the current directory block
 \   diroff @ is the within-block offset of the new dirent
 : no-dir-space?  ( #needed -- true | offset-to-next false )
    begin						( #needed )
@@ -131,7 +134,7 @@
 ;
 : last-dirent   ( -- free-bytes )
    dfile-size bsize um/mod nip  swap 0= if  1-  then to lblk#	( )
-   lblk# >pblk# to dir-block#
+   find-dirblk
    (last-dirent) drop
    dirent-len@  dirent-reclen  -
 ;
@@ -293,10 +296,10 @@
 
 \ On entry:
 \   inode# is the inode of the directory file
-\   dir-block# is the physical block number of the first directory block
+\   d.dir-block# is the physical block number of the first directory block
 \   diroff @ and totoff @ are 0
 \ On successful exit:
-\   dir-block# is the physical block number of the current directory block
+\   d.dir-block# is the physical block number of the current directory block
 \   diroff @ is the within-block offset of the directory entry that matches name$
 \   totoff @ is the overall offset of the directory entry that matches name$
 

Modified: ofw/fs/ext2fs/ext2fs.fth
==============================================================================
--- ofw/fs/ext2fs/ext2fs.fth	Tue Jan  3 03:01:40 2012	(r2797)
+++ ofw/fs/ext2fs/ext2fs.fth	Wed Jan  4 09:51:42 2012	(r2798)
@@ -8,6 +8,7 @@
 fload ${BP}/ofw/fs/ext2fs/blocks.fth
 fload ${BP}/ofw/fs/ext2fs/inode.fth
 fload ${BP}/ofw/fs/ext2fs/bitmap.fth
+fload ${BP}/ofw/fs/ext2fs/extent.fth
 fload ${BP}/ofw/fs/ext2fs/layout.fth
 fload ${BP}/ofw/fs/ext2fs/dir.fth
 fload ${BP}/ofw/fs/ext2fs/recovery.fth

Added: ofw/fs/ext2fs/extent.fth
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ ofw/fs/ext2fs/extent.fth	Wed Jan  4 09:51:42 2012	(r2798)
@@ -0,0 +1,87 @@
+\ EXT4 extents
+d# 12 constant /extent-header
+d# 12 constant /extent-record
+
+struct
+   /w field >eh_magic
+   /w field >eh_entries
+   /w field >eh_max
+   /w field >eh_depth
+   /l field >eh_generation
+constant /extent-header
+
+: ext-magic?  ( 'eh -- flag )  >eh_magic short@ h# f30a =  ;
+: extent?  ( -- flag )  direct0 ext-magic?  ;
+
+struct
+   /l field >ee_block
+   /w field >ee_len
+   /w field >ee_start_hi
+   /l field >ee_start_lo
+constant /extent
+
+struct
+   /l field >ei_block   \ Same offset and size as >ee_block
+   /l field >ei_leaf_lo
+   /w field >ei_leaf_hi
+   /w +  ( >ei_unused )
+constant /extent-index  \ Same length as /extent
+
+: index-block@  ( 'extent-index -- d.block# )
+   dup >ei_leaf_lo int@  swap >ei_leaf_hi short@
+;
+: extent-block@  ( 'extent -- d.block# )
+   dup >ee_start_lo int@  swap >ee_start_hi short@
+;
+
+: >extent  ( index 'eh -- 'extent )
+   /extent-header +  swap /extent *  +
+;
+
+\ Works for both extents and extent-index's because they are the
+\ same length and their block fields are in the same place.
+: ext-binsearch  ( block# 'eh -- block# 'extent )
+   >r                       ( block# r: 'eh )
+   1                        ( block# left r: 'eh )
+   r@ >eh_entries short@ 1- ( block# left right r: 'eh )
+   begin  2dup <=  while    ( block# left right r: 'eh )
+      2dup + 2/             ( block# left right middle r: 'eh )
+      dup r@ >extent        ( block# left right middle 'extent r: 'eh )
+      >ei_block int@        ( block# left right middle extent-block r: 'eh )
+      4 pick >  if          ( block# left right middle r: 'eh )
+         nip 1-             ( block# left right' r: 'eh )
+      else                  ( block# left right middle r: 'eh )
+         rot drop           ( block# right middle r: 'eh )
+         1+ swap            ( block# left' right r: 'eh )
+      then                  ( block# left right r: 'eh )
+   repeat                   ( block# left right r: 'eh )
+   drop  1-                 ( block# left r: 'eh)
+   r> >extent               ( block# 'extent )
+;
+
+: extent->pblk#  ( logical-block# -- d.physical-block# )
+   direct0                      ( logical-block# 'eh )
+   dup >eh_depth short@ 0  ?do  ( logical-block# 'eh )
+      ext-binsearch             ( logical-block# 'extent-index )
+      index-block@              ( logical-block# d.block# )
+      d.block                   ( logical-block# 'eh' )
+
+      \ Error check
+      dup ext-magic? 0=  if     ( logical-block# 'eh' )
+         ." EXT4 bad index block" cr
+	 debug-me
+      then                      ( logical-block# 'eh' )
+
+   loop                         ( logical-block# 'eh )
+
+   ext-binsearch  >r            ( logical-block# r: 'extent )
+   \ At this point the extent should contain the logical block
+   r@ >ee_block int@ -          ( block-offset  r: 'extent )
+   
+   \ Error check
+   dup  r@ >ee_len short@  >=  if  ( block-offset  r: 'extent )
+      ." EXT4 block not in extent" cr
+      debug-me
+   then                            ( block-offset  r: 'extent )
+   u>d  r> extent-block@  d+       ( d.block# )
+;

Modified: ofw/fs/ext2fs/layout.fth
==============================================================================
--- ofw/fs/ext2fs/layout.fth	Tue Jan  3 03:01:40 2012	(r2797)
+++ ofw/fs/ext2fs/layout.fth	Wed Jan  4 09:51:42 2012	(r2798)
@@ -42,36 +42,42 @@
    swap la+ int@			( index-low block# )
    >ind2				( adr )
 ;
-: >pblk  ( logical-block# -- 0 | physical-block-adr )
+: >pblk-adr  ( logical-block# -- 0 | physical-block-adr )
    dup #direct-blocks <  if     ( lblk# )
-      >direct exit
+      >direct exit		( -- adr )
    then                         ( lblk# )
    #direct-blocks -             ( lblk#' )
 
    dup #ind-blocks1 <  if       ( lblk# )
-      #direct-blocks    get-direct >ind1  exit
+      #direct-blocks    get-direct >ind1  exit	( -- adr )
    then
    #ind-blocks1 -               ( lblk#' )
 
-   dup #ind-blocks2  <  if
-      #direct-blocks 1+ get-direct >ind2 exit
-   then
+   dup #ind-blocks2  <  if	( lblk# )
+      #direct-blocks 1+ get-direct >ind2 exit	( -- adr )
+   then				( lblk# )
    #ind-blocks2  -              ( lblk#' )
 
-   dup #ind-blocks3  <  if
-      #direct-blocks 2+ get-direct >ind3 exit
-   then
-
-   drop 0
-;
-: >pblk#  ( logical-block# -- physical-block# )
-   >pblk dup 0=  if  exit  then   int@
+   dup #ind-blocks3  <  if	( lblk# )
+      #direct-blocks 2+ get-direct >ind3 exit	( -- adr )
+   then				( lblk# )
+
+   drop 0			( 0 )
+;
+: >d.pblk#  ( logical-block# -- false | d.physical-block# true )
+   extent?  if                ( logical-block# )
+      extent->pblk# true exit ( -- d.physical-block# true )
+   then                       ( logical-block# )
+   >pblk-adr dup 0=  if       ( 0 )
+      exit                    ( -- false )
+   then                       ( adr )
+   int@ u>d  true             ( d.physical-block# true )
 ;
 
 
 \ writes: if any indir block is 0, allocate and return it.
 
-: get-ind1  ( index block# -- adr )
+: get-ind1  ( index ind1-block# -- block# )
    >r					( index ) ( r: ind3-block# )
    r@ block over la+ int@		( index block# )
    dup if				( index block# )
@@ -80,7 +86,7 @@
       drop u.add-block			( index new-block# )
       dup rot r@ block swap la+ int! update	( new-block# )
    then					( block# )
-   r> drop
+   r> drop				( block# )
 ;
 : get-ind2  ( index ind2-block# -- block# )
    >r					( index ) ( r: ind3-block# )
@@ -92,8 +98,8 @@
       drop u.add-block			( index-low index-high new-block# )
       dup rot r@ block swap la+ int! update	( index-low new-block# )
    then					( index-low block# )
-   get-ind1				( adr )
-   r> drop
+   get-ind1				( block# )
+   r> drop				( block# )
 ;
 : get-ind3  ( index ind3-block# -- block# )
    >r					( index ) ( r: ind3-block# )
@@ -105,43 +111,50 @@
       drop u.add-block			( index-low index-high new-block# )
       dup rot r@ block swap la+ int! update	( index-low new-block# )
    then					( index-low block# )
-   get-ind2				( adr )
-   r> drop
+   get-ind2				( block# )
+   r> drop				( block# )
 ;
 
 \ get-pblk# will allocate the block if necessary, used for writes
 : get-pblk#  ( logical-block# -- 0 | physical-block# )
    dup #direct-blocks <  if			( lblk# )
-      dup get-direct ?dup  if  nip exit  then	( lblk# )
+      dup get-direct ?dup  if			( lblk# pblk# )
+         nip exit				( -- pblk# )
+      then					( lblk# )
       
-      u.add-block dup rot >direct int! update  exit
+      u.add-block				( lblk# pblk# )
+      dup rot >direct int! update		( pblk# )
+      exit					( -- pblk# )
    then						( lblk# )
    #direct-blocks -				( lblk#' )
 
    dup #ind-blocks1 <  if			( lblk# )
       #direct-blocks    get-direct ?dup 0=  if	( lblk# )
-	 u.add-block  dup #direct-blocks put-direct
-      then					( lblk# block )
-      get-ind1  exit
-   then
+	 u.add-block				( lblk# ind1-pblk# )
+         dup #direct-blocks put-direct		( lblk# ind1-pblk# )
+      then					( lblk# ind1-pblk# )
+      get-ind1 exit				( -- pblk# )
+   then						( lblk# )
    #ind-blocks1 -				( lblk#' )
 
    dup #ind-blocks2  <  if
-      #direct-blocks 1+ get-direct ?dup 0=  if
-	 u.add-block  dup #direct-blocks 1+ put-direct
-      then					( lblk# block )
-      get-ind2 exit
-   then
-   #ind-blocks2  -              ( lblk#' )
+      #direct-blocks 1+ get-direct ?dup 0=  if	( lblk# )
+	 u.add-block				( lblk# ind2-pblk# )
+         dup #direct-blocks 1+ put-direct	( lblk# ind2-pblk# )
+      then					( lblk# ind2-pblk# )
+      get-ind2 exit				( -- pblk# )
+   then						( lblk# )
+   #ind-blocks2  -				( lblk#' )
 
-   dup #ind-blocks3  <  if
-      #direct-blocks 2+ get-direct ?dup 0=  if
-	 u.add-block  dup #direct-blocks 2+ put-direct
-      then					( lblk# block )
-      get-ind3 exit
-   then
+   dup #ind-blocks3  <  if			( lblk#' )
+      #direct-blocks 2+ get-direct ?dup 0=  if	( lblk# )
+	 u.add-block				( lblk# ind3-pblk# )
+         dup #direct-blocks 2+ put-direct	( lblk# ind3-pblk# )
+      then					( lblk# ind3-pblk# )
+      get-ind3 exit				( -- pblk# )
+   then						( lblk# )
 
-   drop 0
+   drop 0					( 0 )
 ;
 
 \ deletes
@@ -189,14 +202,14 @@
 ;
 
 : append-block   ( -- )
-   u.add-block						( block )
-   dfile-size bsize um/mod nip  dup bsize um* dfile-size!	( block #blocks )
-   1+ >pblk int! update
+   u.add-block							( pblk# )
+   dfile-size bsize um/mod nip  dup bsize um* dfile-size!	( pblk# #blocks )
+   1+ >pblk-adr int! update
 ;
 
 : read-file-block  ( adr lblk# -- )
-   >pblk#  ?dup  if      ( adr pblk# )
-      block swap bsize move
+   >d.pblk#  if          ( adr d.pblk# )
+      d.block swap bsize move
    else                  ( adr )
       bsize erase        ( )
    then
@@ -206,10 +219,13 @@
    0 swap  bsize bounds do  i l@ or  4 +loop  0=
 ;
 : write-file-block  ( adr lblk# -- )
-   over zeroed? if	\ see if it is already allocated (XXX later: deallocate it)
-      >pblk#   dup 0= if   2drop  exit  then
-   else			\ find or allocate physical block
-      get-pblk#			( adr pblk# )
+   \ see if it is already allocated (XXX later: deallocate it)
+   over zeroed? if              ( adr lblk# )
+      >d.pblk# 0=  if           ( adr )
+         drop  exit             ( -- )
+      then                      ( d.pblk# )
+   else			        ( adr lblk# )  \ find or allocate physical block
+      get-pblk#	u>d		( adr d.pblk# )
    then
 \ This interferes with journal recovery
 \  dup h# f8 < if  dup . ." attempt to destroy file system" cr abort  then

Modified: ofw/fs/ext2fs/recovery.fth
==============================================================================
--- ofw/fs/ext2fs/recovery.fth	Tue Jan  3 03:01:40 2012	(r2797)
+++ ofw/fs/ext2fs/recovery.fth	Wed Jan  4 09:51:42 2012	(r2798)
@@ -209,7 +209,7 @@
 
 listnode
    /n 2* field >o_block#
-   /n    field >o_pblock#
+   /n 2* field >o_pblock#
    /n    field >o_escaped?
 nodetype: overlay-node
 
@@ -229,19 +229,19 @@
 ;
 
 : j-read-file-block  ( adr lblk# -- )
-   >pblk#  ?dup  if               ( adr pblk# )
-      u>d find-overlay?  if       ( adr d.pblk# node )
+   >d.pblk#  if                   ( adr d.pblk# )
+      find-overlay?  if           ( adr d.pblk# node )
          nip nip                  ( adr node )
-         tuck >o_pblock# l@       ( node adr pblk# )
-         block over bsize move    ( node adr )
+         tuck >o_pblock# 2@       ( node adr d.pblk# )
+         d.block over bsize move  ( node adr )
          swap >o_escaped? l@  if  ( adr )
             jbd_magic swap be-l!  ( )
          else                     ( adr )
 	    drop                  ( )
 	 then                     ( )
       else                        ( adr d.pblk# node )
-         2drop                    ( adr pblk# )
-         block swap bsize move    ( )
+         drop                     ( adr d.pblk# )
+         d.block swap bsize move  ( )
       then                        ( )
    else                           ( adr )
       bsize erase                 ( )
@@ -252,7 +252,9 @@
 : set-overlay-node  ( escaped? log-blk# d.block# node -- )
    >r                               ( escaped? log-blk# d.block# r: node )
    r@ >o_block# 2!                  ( escaped? log-blk# r: node )
-   >pblk# r@ >o_pblock# l!          ( escaped? r: node )
+   >d.pblk#  0= abort" EXT3/4 bad block number in journal"
+                                    ( escaped? d.pblk# r: node )
+   r@ >o_pblock# 2!                 ( escaped? r: node )
    r> >o_escaped? l!                ( )
 ;
 : note-jblock  ( d.block# escaped? log-blk# -- )



More information about the openfirmware mailing list