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# -- )
openfirmware@openfirmware.info