[OpenBIOS] r473 - ofw/fs/jffs2
svn at openbios.org
svn at openbios.org
Thu Jul 19 06:18:00 CEST 2007
Author: wmb
Date: 2007-07-19 06:18:00 +0200 (Thu, 19 Jul 2007)
New Revision: 473
Modified:
ofw/fs/jffs2/jffs2.fth
Log:
JFFS2 driver - Fixed OLPC trac #2292 (failure of "size" method) and
also improved the speed of directory operations by a factor of about 4.
Modified: ofw/fs/jffs2/jffs2.fth
===================================================================
--- ofw/fs/jffs2/jffs2.fth 2007-07-18 05:09:39 UTC (rev 472)
+++ ofw/fs/jffs2/jffs2.fth 2007-07-19 04:18:00 UTC (rev 473)
@@ -437,8 +437,12 @@
l at + ( hash adr' )
w at + ( hash w adr' )
swap ?dup if ( hash adr' w ) \ Short form
- swap -rot ( adr' hash w )
- /l* dirent-offset +! ( adr' hash )
+\ swap -rot ( adr' hash w )
+\ /l* dirent-offset +! ( adr' hash )
+
+ /l* dirent-offset +! ( hash adr' )
+ swap ( adr' hash )
+
dirent-offset @ ( adr' hash offset )
cur-pino @ rot ( adr' offset pino hash )
else ( hash adr' ) \ Long form
@@ -449,6 +453,110 @@
true
;
+
+\ Information that we need about the working file/directory
+\ The working file changes at each level of a path search
+
+0 instance value wd-inum \ Inumber of directory
+0 instance value wf-inum \ Inumber of file or directory
+0 instance value wf-type \ Type - 4 for directory, d# 10 for symlink, etc
+
+1 [if]
+code (next-pino-match) ( adr next-dirent pino cur-pino dirent-offset -- false | adr' offset hash true )
+ dx pop \ dx: dirent-offset
+ cx pop \ cx: cur-pino
+ bx pop \ bx: pino
+ 0 [sp] bp xchg \ bp: next-dirent
+ 4 [sp] si xchg \ si: adr
+
+ si bp cmp = if
+ 0 [sp] bp mov \ restore bp
+ 4 [sp] si mov \ restore si
+ 4 # sp add \ clean stack
+ ax ax xor 0 # 0 [sp] mov \ return false
+ next
+ then
+
+ \ If the first encoded dirent is short-form, the pino is the same as
+ \ before and thus matches.
+ ax ax xor op: 4 [si] ax mov \ ax: w
+ ax ax or 0<> if \ Short form
+ 2 # ax shl ax 0 [dx] add \ Update dirent-offset
+ 0 [si] cx mov \ cx: hash
+ 6 # si add \ skip long hash and word offset
+ 4 [sp] si xchg \ Put adr back on stack and restore si
+ 0 [dx] bp mov \ bp: offset
+ 0 [sp] bp xchg \ Put offset on stack and restore bp
+ cx push \ Put hash on stack
+ -1 # push \ Put true on stack
+ next
+ then
+
+ long-offsets on
+ begin
+ ax ax xor op: 4 [si] ax mov \ ax: w
+ ax ax or 0<> if \ Short form
+ 2 # ax shl ax 0 [dx] add \ Update dirent-offset
+ 6 # si add \ skip long hash and word offset
+ else
+ d# 10 [si] ax mov ax 0 [dx] mov \ Update dirent-offset
+ d# 6 [si] ax mov ax 0 [cx] mov \ Update cur-pino
+ d# 14 # si add \ skip record
+ ax bx cmp = if
+ d# -14 [si] cx mov \ cx: hash
+ 4 [sp] si xchg \ Put adr back on stack and restore si
+ 0 [dx] bp mov \ bp: offset
+ 0 [sp] bp xchg \ Put offset on stack and restore bp
+ cx push \ Put hash on stack
+ -1 # push \ Put true on stack
+ next
+ then
+ then
+ bp si cmp = until
+ long-offsets off
+
+ 0 [sp] bp mov \ restore bp
+ 4 [sp] si mov \ restore si
+ 4 # sp add \ clean stack
+ ax ax xor 0 # 0 [sp] mov \ return false
+c;
+: next-pino-match ( adr -- false | pino adr' offset hash true )
+ next-dirent wd-inum cur-pino dirent-offset (next-pino-match)
+;
+[then]
+
+[ifndef] next-pino-match
+: next-pino-match ( adr -- false | adr' offset hash true )
+ dup next-dirent >= if drop false exit then
+
+ \ If the first encoded dirent is short-form, the pino is the same as
+ \ before and thus matches.
+ dup la1+ w@ ?dup if ( adr w )
+ /l* dirent-offset +! ( adr )
+ dirent-offset @ ( adr offset )
+ swap l at + wa1+ ( offset hash adr' )
+ -rot true ( offset hash adr' )
+ exit
+ then ( adr )
+
+ begin ( adr )
+ la1+ w at + swap ?dup if ( adr' w )
+ /l* dirent-offset +! ( adr' )
+ else ( adr' )
+ l at + swap cur-pino ! ( adr' )
+ l at + swap dirent-offset ! ( adr' )
+ wd-inum cur-pino @ = if ( adr' )
+ dirent-offset @ ( adr' offset )
+ over -3 la+ -1 wa+ l@ ( adr' offset hash )
+ true ( adr' offset hash true )
+ exit
+ then ( adr )
+ then ( adr )
+ dup next-dirent >= until ( adr )
+ drop false ( false )
+;
+[then]
+
\ Copy summary dirent from FLASH to memory
\ Summary dirent: w.nodetype l.totlen l.offset l.pino l.version
\ l.ino c.nsize c.type name
@@ -758,13 +866,6 @@
;
-\ Information that we need about the working file/directory
-\ The working file changes at each level of a path search
-
-0 instance value wd-inum \ Inumber of directory
-0 instance value wf-inum \ Inumber of file or directory
-0 instance value wf-type \ Type - 4 for directory, d# 10 for symlink, etc
-
: set-root ( -- ) 1 to wd-inum 1 to wf-inum 4 to wf-type ;
\ latest-node is for symlinks and directories, which have only one data node.
@@ -886,6 +987,23 @@
r> drop
;
+\ This is related to play-log, but instead of going forward and
+\ reading the data, it goes backward and just looks for the last
+\ good node, from which it extracts the total size field.
+: find-size ( -- size )
+ -1 to the-eblock#
+ -1 to have-eblock#
+ next-minode begin dup minodes <> while ( 'minode )
+ 8 - dup na1+ @ get-node ( 'minode' inode )
+ dup inode-good? if ( 'minode inode )
+ nip riisize@ ( size )
+ exit ( -- size )
+ then ( 'minode inode )
+ drop ( 'minode )
+ repeat ( 'minode )
+ drop 0 ( size )
+;
+
: play-log ( -- )
get-inflater
@@ -896,7 +1014,16 @@
release-inflater
;
-: ?play-log ( -- ) file-size -1 = if play-log then ;
+: ?play-log ( -- )
+ file-size -1 = if
+ file-buf -1 = if
+ \ This is the value we will use for file-buf if we use read and seek
+ \ For load, the buffer address is given to us
+ next-minode to file-buf
+ then
+ play-log
+ then
+;
: +dirent ( adr -- adr' ) na1+ dup w@ 0= if 2 na+ then wa1+ ;
@@ -942,21 +1069,21 @@
wd-inum crctab 2over ($crc) >r ( name$ r: hash )
0 dirent-offset !
- dirents begin decode-dirent while ( name$ adr' offset pino' hash' )
- nip ( name$ adr offset hash' )
+ dirents begin next-pino-match while ( name$ adr' offset hash )
\ Check for a hash match
r@ = if ( name$ adr offset )
2over ?update-dirent ( name$ adr )
else ( name$ adr offset )
drop ( name$ adr )
then ( name$ adr )
- repeat ( name$ adr r: hash )
+ repeat ( name$ r: hash )
2drop r> drop ( )
my-vers 0< if true exit then ( )
wf-type 4 = if wf-inum to wd-inum then
false
;
+
\ The work file is a symlink. Resolve it to a new dirent
: dir-link ( -- error? )
delimiter >r [char] / to delimiter
@@ -1064,13 +1191,10 @@
: prep-dirents ( -- )
minodes 'next-minode ! \ Empty the list
- dirents begin decode-dirent while ( adr offset pino hash )
- drop wd-inum = if ( adr offset )
- insert-dirent ( adr )
- else ( adr offset )
- drop ( adr )
- then ( adr )
- repeat ( )
+ dirents ( adr )
+ begin next-pino-match while ( adr' offset hash )
+ drop insert-dirent ( adr )
+ repeat ( )
;
\ End of "tdirent" section
@@ -1181,6 +1305,27 @@
: ?release ( flag -- flag ) dup 0= if release-buffers then ;
+\ Starting at the current directory (wd-inum), process all the path components,
+\ resolving symlinks until either a directory or an ordinary file is found.
+\ If the resulting final component is a directory, leave wd-inum set to it.
+\ If the resulting final component is a file, collect its data nodes so that
+\ "seek", "read", and "load" will access its data.
+
+: $find-file ( name$ -- found? )
+ $resolve-path if false exit then ( )
+
+ begin
+ \ We now have the dirent for the file at the end of the string
+ wf-type case
+ 4 of wf-inum to wd-inum true exit endof \ Directory
+ 8 of collect-nodes exit endof \ Regular file
+ d# 10 of dir-link if false exit then endof \ Link
+ ( default ) \ Anything else (special file) is error
+ drop false exit
+ endcase
+ again
+;
+
: open ( -- flag )
\ This lets us open the node during compilation
standalone? 0= if true exit then
@@ -1193,30 +1338,19 @@
scan-occupied ( )
- \ This is the value we will use for file-buf if we use read and seek
- next-inode to file-buf
-
false to first-time?
my-args " <NoFile>" $= if true exit then
- my-args set-root $resolve-path if false ?release exit then ( )
-
- begin
- \ We now have the dirent for the file at the end of the string
- wf-type case
- 4 of wf-inum to wd-inum true exit endof \ Directory
- 8 of collect-nodes ?release exit endof \ Regular file
- d# 10 of dir-link if false ?release exit then endof \ Link
- ( default ) \ Anything else (special file) is error
- drop false ?release exit
- endcase
- again
+ set-root
+ my-args $find-file ( okay? )
+ ?release
;
: close ( -- ) release-buffers ;
-: size ( -- d.size ) ?play-log file-size 0 ;
+: size ( -- d.size ) find-size 0 ;
+
: read ( adr len -- actual )
?play-log ( adr len )
clip-size tuck ( len' len' adr len' )
More information about the OpenBIOS
mailing list