FFS (Amiga)

From OSDev.wiki
Jump to navigation Jump to search
Filesystems
Virtual Filesystems

VFS

Disk Filesystems
CD/DVD Filesystems
Network Filesystems
Flash Filesystems

The Amiga Fast File System, to put it bluntly, is not - or rather, it's fast only when compared to the OFS, the Original File System of AmigaOS 1.x.

About Amiga FFS

There are many bright design ideas making the AmigaOS a very special thing, but the file system was not exactly part of it. It is prone to invalidation, holds redundant data, and its directory structure is comparatively slow to traverse. It also lacks any concept of multi-user environments.

Perhaps the only good thing with the Amiga FFS was the concept of the Rigid Disk Block (RDB) - a special area at the beginning of a disk, holding not only the partitioning information. It was also possible to store a file system there - a module that would tell a different AmigaOS machine how to read a partition if it was not formatted in FFS format but something else.

For those interested in its internals should try to find a copy of "The Amiga Guru Book" by Ralph Babel, which holds a complete reference of its rather complex block structure. (It also has a complete reference of the DOS library, as well as interesting information on various internals of the Amiga architecture. It is long out of print, but perhaps you can still find copies on eBay.) The old FAQ also held some info in the internals, which are preserved in the AmigaFFS Document.

Technical Details

Root Block

The root of the tree is the root block, which is at a fixed place on the disk. The root is like any other directory, except that it has no parent, and it's secondary type is different. AmigaDOS stores the name of the disk volume in the name field of the root block.

Each filing system block contains a checksum, where the sum (ignoring overflow) of all the words in the block is zero.

         +---------------+
       0 |  T. SHORT     | Type
         |---------------|
       1 |       0       | header key (always 0)
         |---------------|
       2 |         0     | Highest seq number (always 0)
         |---------------|
       3 |   HT SIZE     | Hashtable size (=blocksize -56)
         |---------------|
       4 |       0       |
         |---------------|
       5 |   CHECKSUM    |
         |---------------|
       6 |     hash      |
         |     table     |
         /               /
         \               \
 SIZE-51 |               |
         |---------------|
 SIZE-50 |  BMFLAG       | TRUE if bitmap on disk is valid
         |---------------|
 SIZE-49 |   bitmap      | Used to indicate the blocks
 SIZE-24 |    pages      | containing the bitmap
         |---------------|
 SIZE-23 |    DAYS       | Volume last altered date and time
         |---------------|
 SIZE-22 |    MINS       |
         |---------------|
 SIZE-21 |    TICKS      |
         |---------------|
 SIZE-20 |     DISK      | Volume name as a BCPL string
         |     NAME      | of <= 30 characters
         |---------------|
 SIZE-7  |   CREATEDAYS  | Volume creation date and time
         |---------------|
 SIZE-6  |   CREATEMINS  |
         |---------------|
 SIZE-5  |  CREATETICKS  |
         |---------------|
 SIZE-4  |       0       | Next entry on this hash chain
         |---------------| (always 0)
 SIZE-3  |       0       | Parent directory (always 0)
         |---------------|
 SIZE-2  |       0       | Extension (always 0)
         |---------------|
 SIZE-1  |    ST.ROOT    | Secondary type indicates root block
         +---------------+

User Directory Blocks

         +---------------+
       0 |   T.SHORT     | Type
         |---------------|
       1 |   OWN KEY     | Header Key (pointer to self)
         |---------------|
       2 |       0       | Highest Seq Number (always 0)
         |---------------|
       3 |       0       |
         |---------------|
       4 |       0       |
         |---------------|
       5 |  CHECKSUM     |
         |---------------|
       6 |               |
         |    hash table |
         /               /
         \               \
 SIZE-51 |               |
         |---------------|
 SIZE-50 |    Spare      |
         |---------------|
 SIZE-48 |    PROTECT    |  Protection bits
         |---------------|
 SIZE-47 |       0       | Unused (always 0)
         |---------------|
 SIZE-46 |               |
         |   COMMENT     | Stored as  BCPL string
 SIZE-24 |               |
         |---------------|
 SIZE-23 |     DAYS      | Creation date and time
         |---------------|
 SIZE-22 |     MINS      |
         |---------------|
 SIZE-21 |    TICKS      |
         |---------------|
 SIZE-20 | DIRECTORY NAME| Stored as a BCPL string <=30 chars
         |---------------|
 SIZE-4  | HASHCHAIN     | Next entry with same hash value
         |---------------|
 SIZE-3  |    PARENT     | back pointer to parent directory
         |---------------|
 SIZE-2  |      0        | Extension (always 0)
         |---------------|
 SIZE-1  |  ST.USERDIR   | secondary type
         +---------------+

User directory blocks have type T.SHORT and secondary type ST.USERDIRECTORY. The six information words at the start of the block also indicate the block's own key (this is, the block number) as a consistency check and the size of the hash table. The 50 information words at the end of the block contain the date and time of creation, the name of the directory, a pointer to the next file or directory on the hash chain, and a pointer to the directory above.

To find a file or sub-directory, you must first apply a hash function to its name. This has function yields and offset in the hash table, which is the key of the first block on a chain linking those with the same hash value (or 0, if there are none). AmigaDOS reads the block with this key and compares the name of the block with the required name. If the names do not match, it reads the next block on the chain, and so on. 1.1.3 File Header Block

          +------------+
       0  |   T.SHORT  | Type
          |------------|
       1  |   OWN KEY  | Header Key
          |------------|
       2  | HIGHEST SEQ| Total number of data blocks in file
          |------------|
       3  |  DATA SIZE | Number of data block slots used
          |------------|
       4  | FIRST DATA | First data block
          |------------|
       5  |  CHECKSUM  |
          |------------|
       6  |            |
          /            /
          \            \
          | DATA BLK 3 |
          | DATA BLK 2 | List of data block keys
 SIZE-51  | DATA BLK 1 |
          |------------|
 SIZE-50  |  Spare     |
          |------------|
 SIZE-49  |   PROTECT  | Protection bits
          |------------|
 SIZE-48  |  BYTESIZE  | Total size of file in bytes
          |------------|
 SIZE-46  |            |
          |  COMMENT   | Comment as a BCPL string
 SIZE-24  |            |
          |------------|
 SIZE-23  |    DAYS    | Creation date and time
          |------------|
 SIZE-22  |    MINS    |
          |------------|
 SIZE-21  |    TICKS   |
          |------------|
 SIZE-20  | FILE NAME  | Stored as BCPL string <= 30 chars
          |------------|
 SIZE-4   |  HASHCHAIN | Next entry with same hash value
          |------------|
 SIZE-3   |   PARENT   | Back pointer to the parent directory
          |------------|
 SIZE-2   |  EXTENSION | Zero pointer to the first extension
          |------------| block
 SIZE-1   |  ST. FILE  | Secondary type
          +------------+

Each terminal file starts with a file header block, which has type T.SHORT and secondary type ST.FILE. The start and end of the block contain name, time, and redundancy information similar to that in a directory block. The body of the file consists of Data blocks with sequence numbers from 1 upwards. AmigaDOS stores the addresses of these blocks in consecutive words downwards from offset size-51 in the block. In general, AmigaDOS does not use all the space for this list and the last data block is not full.

File List Block

If there are more blocks in the file than can be specified in the block list, then the EXTENSION field is non-zero and points to another disk block which contains a further data block list. The following figure explains the structure of the file list block.

          +-------------+
       0  |   T. LIST   | Type
          |-------------|
       1  |   OWN KEY   | Header Key
          |-------------|
       2  | BLOCK COUNT | =number of data blocks in block list
          |-------------|
       3  | DATA SIZE   | Same as above
          |-------------|
       4  | FIRST DATA  | First Data Block
          |-------------|
       5  |  CHECKSUM   |
          |-------------|
       6  |             |
          /             /
          \             \
          | BLOCK N+3   |
          | BLOCK N+2   | Extended list of data block keys
 SIZE-51  | BLOCK N+1   |
          |-------------|
 SIZE-50  |      info   | (unused)
          |-------------|
 SIZE-4   |     0       | Next in hash list (always 0)
          |-------------|
 SIZE-3   |   PARENT    | File header block of this file
          |-------------|
 SIZE-2   | EXTENTSION  | Next extension block
          |-------------|
 SIZE-1   |   ST. FILE  | Secondary type
          +-------------+

There are as many file extension blocks as required to list the data blocks that make up the file. The layout of the block is very similar to that of a file header block, except that the type is different and the date and filename fields are not used.

Data Block (OFS)

          +-------------+
       0  |   T. DATA   | type
          |-------------|
       1  |   HEADER    | header key
          |-------------|
       2  |   SEQ NUM   | Sequence number
          |-------------|
       3  |  DATA SIZE  |
          |-------------|
       4  |  NEXT DATA  | next data block
          |-------------|
       5  |  CHECKSUM   |
          |-------------|
       6  |             |
          |             |
          |             |
          |             |
          |    DATA     |
          |             |
          |             |
          |             |
          +-------------+

Data blocks contain only six words of filing system information. These six words refer to the following:

  • type (T.DATA)
  • pointer to the file header block
  • sequence number of the data block
  • number of words of data
  • pointer to the next data block
  • checksum

Normally, all data blocks except the last are full (that is, they have a blocksize = blocksize-6). The last data block has a forward pointer of 0.

Data Block (FFS)

FFS data blocks are different from OFS data blocks in that there are no metadata in the Former. The whole block is data. The lack of a checksum makes the file system more vulnerable to detect data corruption and there is no way to follow a linked list to get to the next data block in the sequence. The file header block will be the starting point to follow the list of blocks and extension blocks till 'bytesize' amount of bytes has been read, which should be in the last number of blocks indicated (HIGHEST SEQ). These lists of blocks are read in backwards order.