[openfirmware] r923 - ofw/fs/ext2fs

svn at openfirmware.info svn at openfirmware.info
Sun Sep 7 21:23:05 CEST 2008


Author: wmb
Date: 2008-09-07 21:23:04 +0200 (Sun, 07 Sep 2008)
New Revision: 923

Modified:
   ofw/fs/ext2fs/bitmap.fth
   ofw/fs/ext2fs/blocks.fth
   ofw/fs/ext2fs/dir.fth
   ofw/fs/ext2fs/layout.fth
   ofw/fs/ext2fs/methods.fth
   ofw/fs/ext2fs/sb.fth
Log:
EXT2 file system - major edit to fix bugs and performance problems for writing.




Modified: ofw/fs/ext2fs/bitmap.fth
===================================================================
--- ofw/fs/ext2fs/bitmap.fth	2008-09-04 23:43:37 UTC (rev 922)
+++ ofw/fs/ext2fs/bitmap.fth	2008-09-07 19:23:04 UTC (rev 923)
@@ -3,6 +3,8 @@
 
 decimal
 
+\ Group descriptor access
+
 0 instance value gd-modified?
 
 : gd-update   ( -- )   true to gd-modified?  ;
@@ -10,116 +12,163 @@
 : inode-bitmap  ( group# -- block# )   group-desc 4 + le-l@  ;
 : inode-table   ( group# -- block# )   group-desc 8 + le-l@  ;
 : free-blocks   ( group# -- n )    group-desc h# 0c + le-w@  ;
-: free-inodes   ( group# -- n )    group-desc h# 0e + le-w@  ;
 : free-blocks+!  ( n group# -- )
-   group-desc h# 0c + 
-   tuck le-w@ + swap le-w!  gd-update
+   group-desc h# 0c +
+   tuck le-w@ +  0 max  swap le-w!  gd-update
 ;
-: free-inodes+!  ( n group# -- )
+: free-inodes   ( group# -- n )    group-desc h# 0e + le-w@  ;
+: free-inodes+!  ( n inode# -- )
    group-desc h# 0e +
    tuck le-w@ + swap le-w!  gd-update
 ;
 
-\ find the lowest clear bit in a byte
-: find-low   ( byte -- bit )
-   1  8 0 do
-      2dup and 0= if
-	 drop i leave
-      then
-      2*
-   loop
-   nip 1+
-;
-\ find the first clear bit in a bitmap
-: first-free   ( map len -- n )
-   -1 -rot  0 ?do			( byte map )
-      dup i + c@ h# ff <> if
-	 nip i swap leave
-      then
-   loop					( byte map )
-   over 0< if  2drop 0 exit  then
-   
-   over + c@ find-low			( byte bit )
-   swap 8* +
-;
+[ifdef] 386-assembler
+code find-low-zero  ( n -- bit# )
+   ax pop
+   cx cx xor
+   clc
+   begin
+      cx inc
+      1 # ax rcr
+   no-carry? until
+   cx dec
+   cx push
+c;
+[else]
+create lowbits
+   8 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 0-f
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 10-1f
 
-: (find-free-block)   ( group# -- n )
-   block-bitmap  block
-   fpg 8 /  bsize min			\ XXX stay in this block
-   first-free
-;
-: find-free-block   ( -- n )
-   0
-   #groups 0 ?do
-      drop
-      i (find-free-block) dup ?leave
-   loop
-   dup 0= abort" no free blocks found"
-;
+   5 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 20-2f
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 30-3f
 
-: (find-free-inode)   ( group# -- n )
-   inode-bitmap  block
-   ipg 8 /  bsize min			\ XXX stay in this block
-   first-free
+   6 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 40-4f
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 50-5f
+
+   5 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 20-2f
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 30-3f
+
+   7 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 80-8f
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ 90-9f
+
+   5 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ a0-af
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ b0-bf
+
+   6 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ c0-cf
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ d0-df
+
+   5 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ e0-ef
+   4 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  3 c,  0 c,  1 c,  0 c,  2 c,  0 c,  1 c,  0 c,  \ f0-ff
+
+: find-low-zero  ( byte -- bit# )  invert h# ff and  lowbits + c@  ;
+[then]
+
+\ Find the first clear bit in a bitmap, set it if found
+: first-free   ( len block# -- false | block#-in-group true )
+   block swap				( map len )
+
+   2dup  h# ff bskip  dup  0=  if	( map len 0 )
+      3drop false exit
+   then					( map len residue )
+   - 					( map byte# )
+   tuck +  dup  c@  dup  find-low-zero	( byte# adr byte bit# )
+
+   \ Set the bit we just found
+   >r  1 r@ lshift  or			( byte# adr byte' r: bit# )
+   swap c!  \ Write back to map		( byte# r: bit# )
+
+   8* r> +				( block#-in-group )
+   update				( block#-in-group )
+   true
 ;
-: find-free-inode   ( -- n )
-   0
-   #groups 0 ?do
-      drop
-      i (find-free-inode) dup ?leave
-   loop
-   dup 0= abort" no free inodes found"
-;
 
 : bitup    ( n adr -- mask adr' )
    over 3 rshift +			( n adr' )
    1 rot 7 and lshift			( adr' mask )
    swap
 ;
-: block-bit     ( block# -- n adr )   1- fpg /mod block-bitmap block bitup  ;
-: block-free?   ( block# -- set? )  block-bit c@ and 0=  ;
-: set-block-bit   ( block# -- )   block-bit cset   update  ;
-: clr-block-bit   ( block# -- )   block-bit creset update  ;
+
+: clear-bit?  ( bit# block# -- cleared? )
+   block  bitup				( mask adr' )
+   tuck c@				( adr mask byte )
+   2dup and  0=  if	\ Already free	( adr mask byte )
+      3drop  false  exit
+   then					( adr mask byte )
+   swap invert and			( adr byte' )
+   swap c!				( )
+   update				( )
+   true
+;
+
 : free-block      ( block# -- )
-   dup block-free? if  drop exit  then
-   
-   dup clr-block-bit			( block# )
-   1 swap 1- fpg /			( 1 group# )
-   free-blocks+!
+   datablock0 - bpg /mod  		( bit# group# )
+   tuck block-bitmap 			( group# bit# block# )
+   clear-bit?  if			( group# )
+      1  swap  free-blocks+!
+   else					( group# )
+      drop
+   then
 ;
-: alloc-block     ( -- block# )
-   find-free-block dup set-block-bit	( block# )
-   dup block bsize erase update		( block# )
-   dup 1- fpg /				( block# group# )
-   -1 swap free-blocks+!
+
+: alloc-block   ( -- block# )
+   #groups 0  ?do			( )
+      i free-blocks  if			( )
+         bpg 3 rshift  bsize min	( len )	\ XXX stay in this block
+         i  block-bitmap  		( len block# )
+         first-free  if			( block#-in-group )
+            -1 i free-blocks+!		( block#-in-group )
+            i bpg *  +  datablock0 +	( block# )
+            dup buffer bsize erase update	( block# )
+            unloop exit
+         else
+            \ The allocation bitmap disagrees with the free block count,
+            \ so fix the free block count to prevent thrashing.
+            i free-blocks  negate  i free-blocks+!
+         then
+      then
+   loop
+   true abort" no free blocks found"
 ;
 
-: inode-bit     ( inode# -- n adr )   1- ipg /mod inode-bitmap block bitup  ;
-: inode-free?   ( inode# -- set? )  inode-bit c@ and 0=  ;
-: set-inode-bit   ( inode# -- )   inode-bit cset   update  ;
-: clr-inode-bit   ( inode# -- )   inode-bit creset update  ;
 : free-inode      ( inode# -- )
-   dup inode-free? if  drop exit  then
-   
-   dup clr-inode-bit
-   1 swap 1- ipg /			( 1 group# )
-   free-inodes+!
+   1- ipg /mod 				( bit# group# )
+   tuck inode-bitmap			( group# bit# block# )
+   clear-bit?  if			( group# )
+      1  swap  free-inodes+!
+   else					( group# )
+      drop
+   then
 ;
-: alloc-inode     ( -- inode# )
-   find-free-inode dup set-inode-bit	( inode# )
-   dup inode /inode erase update	( inode# )
-   dup 1- ipg /				( inode# group# )
-   -1 swap free-inodes+!
+
+: alloc-inode   ( -- inode# )
+   #groups 0 ?do
+      ipg 3 rshift  bsize min		( len )		\ XXX stay in this block
+      i  inode-bitmap 			( len block# )
+      first-free  if			( inode#-in-group )
+         -1 i free-inodes+!		( inode#-in-group )
+         i ipg * +  1+			( inode# )
+         dup inode /inode erase update	( inode# )
+         unloop exit
+      then
+   loop
+   true abort" no free inodes found"
 ;
+
 : update-sb   ( -- )
    0  #groups 0 ?do  i free-inodes +  loop  total-free-inodes!
    0  #groups 0 ?do  i free-blocks +  loop  total-free-blocks!
    put-super-block abort" failed to update superblock "
    gds /gds gds-block# write-ublocks abort" failed to update group descriptors "
 ;
+
 : update-gds   ( -- )
    gd-modified? if
-      #groups 1 do  0 group-desc  i fpg * 2 + block  bsize move update  loop
+      \ Copy group descriptors to backup locations
+      #groups 1  do
+         0 group-desc		( gd0-adr )
+         i bpg *  2+ block	( gd0-adr gdn-adr )
+         bsize move update	( )
+      loop
       false to gd-modified?
       update-sb
    then

Modified: ofw/fs/ext2fs/blocks.fth
===================================================================
--- ofw/fs/ext2fs/blocks.fth	2008-09-04 23:43:37 UTC (rev 922)
+++ ofw/fs/ext2fs/blocks.fth	2008-09-07 19:23:04 UTC (rev 923)
@@ -66,7 +66,10 @@
    dup dirty? if			( buffer# )
       false over dirty!
       dup >buffer  swap blk#		( buffer-adr block# )
-      dup 3 < if  dup . ." attempt to corrupt superblock or group desciptor" abort  then
+      dup gds-fs-block# <=  if
+         dup . ." attempt to corrupt superblock or group descriptor" abort
+      then
+      bbug? if ." W " dup . cr then
       write-fs-block abort" write error "
    else
       drop

Modified: ofw/fs/ext2fs/dir.fth
===================================================================
--- ofw/fs/ext2fs/dir.fth	2008-09-04 23:43:37 UTC (rev 922)
+++ ofw/fs/ext2fs/dir.fth	2008-09-07 19:23:04 UTC (rev 923)
@@ -18,12 +18,31 @@
 
 \ **** Return the address of the current directory entry
 : dirent  ( -- adr )  dir-block# block diroff @ +  ;
+\ Dirent fields:
+\ 00.l inode
+\ 04.w offset to next dirent
+\ 06.b name length
+\ 07.b flags?
+\ 08.s name string
 
+: >reclen   ( name-length -- record-length )   8 + 4 round-up  ;
+
+: dirent-inode@  ( -- n )  dirent int@  ;
+: dirent-inode!  ( n -- )  dirent int!  ;
+: dirent-len@  ( -- n )  dirent la1+ short@  ;
+: dirent-len!  ( n -- )  dirent la1+ short!  ;
+: dirent-nameadr   ( -- adr )  dirent la1+ 2 wa+  ;
+: dirent-namelen@  ( -- b )  dirent la1+ wa1+ c@  ;
+: dirent-namelen!  ( b -- )  dirent la1+ wa1+ c!  ;
+: dirent-type@     ( -- b )  dirent la1+ wa1+ ca1+  c@  ;
+: dirent-type!     ( b -- )  dirent la1+ wa1+ ca1+  c!  ;
+: dirent-reclen    ( -- n )  dirent-namelen@ >reclen  ;
+
 : lblk#++  ( -- )   lblk# 1+ to lblk#  ;
 
 \ **** Select the next directory entry
 : next-dirent  ( -- end? )
-   dirent  la1+ short@  dup diroff +!  totoff +!
+   dirent-len@  dup diroff +!  totoff +!
    totoff @  file-size >=  if  true exit  then
    diroff @  bsize =  if
       lblk#++  get-dirblk  if  true exit  then
@@ -34,12 +53,12 @@
 
 \ **** From directory, get handle of the file or subdir that it references
 \ For Unix, file handle is the inode #
-: file-handle  ( -- i# )  dirent int@  ;
+: file-handle  ( -- i# )  dirent-inode@  ;
 
 \ **** From directory, get name of file
 : file-name  ( -- adr len )
    dirent la1+ wa1+  dup wa1+    ( len-adr name-adr )
-   swap short@  h# ff and   ( adr len )
+   swap c@                       ( adr len )
 ;
 
 \
@@ -59,53 +78,92 @@
    update
    r> drop
 ;
-: >reclen   ( name-length -- record-length )   8 + 4 round-up  ;
+
+\ On entry:
+\   current-dir @  is the inode of the directory file
+\   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
+\   diroff @ is the within-block offset of the new dirent
+: no-dir-space?  ( #needed -- true | offset-to-next false )
+   begin						( #needed )
+      dirent-inode@  if					( #needed )
+         dup  dirent-len@ dirent-reclen -  <=  if	( #needed )
+            \ Carve space out of active dirent
+            drop					( )
+            dirent-len@ dirent-reclen -			( offset-to-next )
+            dirent-reclen  dup dirent-len!  diroff +!	( offset-to-next )
+            false exit
+         then
+      else						( #needed )
+         dup  dirent-len@  <=  if			( #needed )
+            \ Reuse deleted-but-present dirent
+            drop					( )
+            dirent-len@					( offset-to-next )
+            false exit
+         then						( #needed )
+      then						( #needed )
+      next-dirent					( #needed )
+   until						( #needed )
+   drop true
+;
+
 \ a directory entry needs 8+n 4-aligned bytes, where n is the name length
 \ the last entry has a larger size; it points to the end of the block
-: (last-dirent)   ( -- penultimate-offset last-offset )
-   diroff off   0 0
-   begin						( previous' last' )
-      nip diroff @					( previous last )
-      dirent la1+ short@				( previous last rec-len )
-      dup diroff @ + bsize <				( previous last rec-len not-end? )
-      over dirent la1+ wa1+ short@ >reclen = and	( previous last rec-len not-end? )
-   while						( previous last rec-len )
-      diroff +!						( previous last )
-   repeat						( previous last rec-len )
-   drop
+: (last-dirent)   ( -- penultimate-offset )
+   diroff off   0
+   begin						( last )
+      dirent-len@				        ( last rec-len )
+      dup diroff @ + bsize <				( last rec-len not-end? )
+\     over dirent-reclen =  and				( last rec-len not-end? )
+   while						( last rec-len )
+      nip diroff @ swap					( last' rec-len )
+      diroff +!						( last )
+   repeat						( last )
+   drop							( last )
 ;
 : last-dirent   ( -- free-bytes )
    file-size bsize /mod swap 0= if  1-  then to lblk#	( )
    lblk# >pblk# to dir-block#
-   (last-dirent) 2drop
-   dirent la1+ dup short@  swap wa1+ short@ >reclen -
+   (last-dirent) drop
+   dirent-len@  dirent-reclen  -
 ;
 : set-dirent   ( name$ rec-len inode# -- )
    dirent int!						( name$ rec-len )
-   dirent la1+ short!					( name$ )
-   dup dirent la1+ wa1+ short!
-   dirent la1+ 2 wa+ swap move
+   dirent-len!						( name$ )
+   dup dirent-namelen!					( name$ )
+   \ XXX set actual file type here if EXT2_FEATURE_INCOMPAT_FILETYPE
+   0 dirent-type!					( name$ )
+   dirent-nameadr swap move				( )
    update
 ;
 
+: to-previous-dirent  ( -- )
+   diroff @  					( this )
+   0 diroff !					( this )
+   begin					( this )
+      dup  diroff @ dirent-len@ +  <>		( this not-found? )
+   while					( this )
+      dirent-len@ diroff +!			( this )
+   repeat					( this )
+   diroff @ swap -  totoff +!			( )
+;
+
 \ delete directory entry at diroff
 : del-dirent   ( -- error? )
-   diroff @ >r
-   (last-dirent) dup r@ = if				( prev last )
-      \ current entry is the last
-      r> 2drop						( prev )
-      diroff @ 0= abort" delete this block in directory" \ XXX last is also first
-      dirent  bsize diroff @ - erase			( prev )
-   else							( prev last )
-      nip						( last )
-      r> diroff !					( last )
-      dirent  dup la1+ wa1+ short@ >reclen		( last dirent oldlen )
-      rot over - -rot					( last' dirent oldlen )
-      2dup + -rot					( last' nextent dirent reclen )
-      diroff @ + bsize swap - move			( last' )
-   then							( last )
-   dup diroff !
-   bsize swap -  dirent la1+ short!
+   diroff @  if
+      \ Not first dirent in block; coalesce with previous
+      dirent-len@				( deleted-len )
+      to-previous-dirent			( deleted-len )
+      dirent-len@ + dirent-len!			( )
+      dirent dirent-reclen +			( adr )
+      dirent-len@ dirent-reclen -  erase	( )
+   else
+      \ First dirent in block; zap its inode
+      0 dirent-inode!
+      
+   then      
    update
    false
 ;
@@ -113,19 +171,16 @@
 : ($create)   ( name$ mode -- error? )
    >r							( name$ )
    \ check for room in the directory, and expand it if necessary
-   dup >reclen  last-dirent  tuck <  if			( name$ free )
-      
-      \ there is room. update previous entry, and point to new entry
-      dirent la1+ wa1+ short@ >reclen			( name$ free old-len )
-      dup dirent la1+ short!  diroff +!			( name$ free )
-   else							( name$ free )
+   dup >reclen  no-dir-space?   if			( name$ new-reclen )
       \ doesn't fit, allocate more room
-      drop bsize					( name$ bsize )
+      bsize						( name$ bsize )
       append-block
       lblk#++ get-dirblk drop
    then							( name$ rec-len )
+
+   \ At this point dirent points to the place for the new dirent
    alloc-inode set-dirent false				( error? )
-   r> file-handle init-inode
+   r> dirent-inode@ init-inode
 ;
 
 \ On entry:
@@ -138,7 +193,9 @@
 \   totoff @ is the overall offset of the directory entry that matches name$
 : lookup  ( name$ -- not-found? )
    begin
-      2dup file-name  $=  if  2drop false exit  then
+      dirent-inode@  if   \ inode=0 for a deleted dirent at the beginning of a block
+         2dup file-name  $=  if  2drop false exit  then
+      then
       next-dirent
    until
    2drop true
@@ -257,7 +314,7 @@
    r> to inode#
 ;
 
-\ Linux sometimes leaves a deleted file in the directory with an inode of 0
+\ Deleted files at the beginning of a directory block have inode=0
 : next-file-info  ( id -- false | id' s m h d m y len attributes name$ true )
    dup  if  
       begin

Modified: ofw/fs/ext2fs/layout.fth
===================================================================
--- ofw/fs/ext2fs/layout.fth	2008-09-04 23:43:37 UTC (rev 922)
+++ ofw/fs/ext2fs/layout.fth	2008-09-07 19:23:04 UTC (rev 923)
@@ -221,19 +221,20 @@
 
 \ **** Allocate memory for necessary data structures
 : allocate-buffers  ( -- error? )
-   /super-block alloc-mem is super-block
+   init-io
+   /super-block do-alloc is super-block
    get-super-block ?dup  if
-      super-block /super-block free-mem exit
+      super-block /super-block do-free exit
    then
 
-   /gds alloc-mem is gds
+   /gds do-alloc is gds
    gds /gds gds-block# read-ublocks dup  if
-      gds         /gds          free-mem
-      super-block /super-block  free-mem exit
+      gds         /gds          do-free
+      super-block /super-block  do-free exit
    then
 
    bsize /buf-hdr + dup to /buffer
-   #bufs *  alloc-mem is block-bufs
+   #bufs *  do-alloc is block-bufs
    empty-buffers
 
    bsize /l /  dup to #ind-blocks1  ( #ind-blocks1 )
@@ -242,9 +243,9 @@
 ;
 
 : release-buffers  ( -- )
-   gds             /gds             free-mem
-   block-bufs      /buffer #bufs *  free-mem
-   super-block     /super-block     free-mem
+   gds             /gds             do-free
+   block-bufs      /buffer #bufs *  do-free
+   super-block     /super-block     do-free
 ;
 
 \ LICENSE_BEGIN

Modified: ofw/fs/ext2fs/methods.fth
===================================================================
--- ofw/fs/ext2fs/methods.fth	2008-09-04 23:43:37 UTC (rev 922)
+++ ofw/fs/ext2fs/methods.fth	2008-09-07 19:23:04 UTC (rev 923)
@@ -7,6 +7,8 @@
 
 external
 
+: free-bytes  ( -- d )  total-free-blocks bsize um*  ;
+
 : $create   ( name$ -- error? )
    o# 100666 ($create)
 ;
@@ -103,7 +105,7 @@
    \ XXX I am sceptical about this line.
    dup  0>  if  lblk#++  then				( actual )
    true to modified?
-   flush					\ XXX kludge for tests
+\   flush					\ XXX kludge for tests
 ;
 
 : $ext2fsopen  ( adr len mode -- false | fid fmode size align close seek write read true )

Modified: ofw/fs/ext2fs/sb.fth
===================================================================
--- ofw/fs/ext2fs/sb.fth	2008-09-04 23:43:37 UTC (rev 922)
+++ ofw/fs/ext2fs/sb.fth	2008-09-07 19:23:04 UTC (rev 923)
@@ -8,6 +8,8 @@
 1024    constant /super-block
 h# ef53 constant fs-magic
 
+0 instance partition-offset
+
 0 instance value super-block
 0 instance value gds
 
@@ -20,9 +22,11 @@
 \ superblock data
 : +sbl  ( index -- value )  super-block  swap la+ int@  ;
 : +sbw  ( index -- value )  super-block  swap wa+ short@  ;
+: datablock0    ( -- n )   5 +sbl  ;
 : logbsize	( -- n )   6 +sbl 1+  ;
 : bsize		( -- n )   1024  6 +sbl lshift  ;	\ 1024
 : /frag		( -- n )   1024  7 +sbl lshift  ;	\ 1024
+: bpg		( -- n )   8 +sbl  ;			\ h#2000 blocks_per_group
 : fpg		( -- n )   9 +sbl  ;			\ h#2000 frags_per_group
 : ipg		( -- n )  10 +sbl  ;			\ h#790  inodes_per_group
 : magic         ( -- n )  28 +sbw  ;
@@ -36,31 +40,49 @@
 
 \ : total-inodes		( -- n )   0 +sbl  ;
 : total-blocks		( -- n )   1 +sbl  ;
-\ : total-free-blocks	( -- n )   3 +sbl  ;
+: total-free-blocks	( -- n )   3 +sbl  ;
 \ : total-free-inodes	( -- n )   4 +sbl  ;
 \ : total-free-blocks+!	( -- n )   3 +sbl  +  super-block  3 la+ int!  ;
 \ : total-free-inodes+!	( -- n )   4 +sbl  +  super-block  4 la+ int!  ;
 : total-free-blocks!	( -- n )   super-block  3 la+ int!  ;
 : total-free-inodes!	( -- n )   super-block  4 la+ int!  ;
-: #groups   ( -- n )   total-blocks fpg ceiling  ;
+: #groups   ( -- n )   total-blocks bpg ceiling  ;
 
 \ Don't write to a disk that uses extensions we don't understand
 : unknown-extensions?   ( -- unsafe? )
-   0  super-block h# 54 +  h# 14 bounds do   i l@ or   4 +loop  0<>
+   24 +sbl 4 and   if  ." ext3 journal needs recovery" cr  then 
+
+   23 +sbl h# ffffffff invert and        \ Accept all compat extensions
+   24 +sbl h# 00000002 invert and  or    \ Incompatible - accept FILETYPE
+   25 +sbl h# 00000001 invert and  or    \ RO - accept SPARSE_SUPER
 ;
 
+: do-alloc  ( adr len -- )  " dma-alloc" $call-parent  ;
+: do-free   ( adr len -- )  " dma-free" $call-parent  ;
+
+: init-io  ( -- )
+   " offset-low" $call-parent  " offset-high" $call-parent
+   ublock um/mod nip  to partition-offset
+;
+
 : write-ublocks  ( adr len dev-block# -- error? )
-   ublock um* " seek" $call-parent ?dup  if  exit  then		( adr len )
-   tuck " write" $call-parent <>
+\   ublock um* " seek" $call-parent ?dup  if  exit  then		( adr len )
+\   tuck " write" $call-parent <>
+   partition-offset +  swap ublock 1- + 9 rshift             ( adr block# #blocks )
+   dup >r  " write-blocks" $call-parent  r> <>
 ;
 : put-super-block  ( -- error? )
    super-block /super-block super-block# write-ublocks
 ;
 
 : read-ublocks  ( adr len dev-block# -- error? )
-   ublock um* " seek" $call-parent ?dup  if  exit  then		( adr len )
-   tuck " read" $call-parent <>
+   partition-offset +  swap ublock 1- + 9 rshift             ( adr block# #blocks )
+   dup >r  " read-blocks" $call-parent  r> <>
+
+\   ublock um* " seek" $call-parent ?dup  if  exit  then		( adr len )
+\   tuck " read" $call-parent <>
 ;
+
 : get-super-block  ( -- error? )
    super-block /super-block super-block# read-ublocks ?dup  if  exit  then
 
@@ -73,11 +95,13 @@
    magic fs-magic <>
 ;
 
-: gds-block#  ( -- dev-block# )
+: gds-fs-block#  ( -- fs-block# )
    bsize d# 1024 =  if  2  else  1  then	( logical block# )
-   bsize ublock / *				( dev-block# )
 ;
-: /gds  ( -- size )  #groups h# 20 *  ;
+: gds-block#  ( -- dev-block# )
+   gds-fs-block#  bsize ublock / *		( dev-block# )
+;
+: /gds  ( -- size )  #groups h# 20 *  ublock round-up  ;
 : group-desc  ( group# -- adr )  h# 20 *  gds +  ;
 : gpimin    ( group -- block# )   group-desc  2 la+ int@  ;
 : blkstofrags  ( #blocks -- #frags )  ;		\ XXX is this needed?




More information about the openfirmware mailing list