MinFS is a simple, unix-like filesystem built for Zircon.
It currently supports files up to 4 GB in size.
# (Linux) $ truncate --size=16G blk.bin # (Mac) $ mkfile -n 16g blk.bin
fx set bringup.x64 fx build fx qemu -- -hda blk.bin
Warning: On real hardware, /dev/class/block/...
refers to REAL storage devices (USBs, SSDs, etc).
BE CAREFUL NOT TO FORMAT THE WRONG DEVICE. If in doubt, only run the following commands through QEMU. The lsblk
command can be used to see more information about the devices accessible from Zircon.
lsblk
can be used to list the block devices currently on the system. On this example system below, /dev/class/block/000
is a raw block device.> lsblk ID DEV DRV SIZE TYPE LABEL 000 block block 16G
> gpt init /dev/class/block/000 ... > lsblk ID DEV DRV SIZE TYPE LABEL 002 block block 16G
lsblk
to keep track of how to refer to the block device).> gpt dump /dev/class/block/002 blocksize=512 blocks=33554432 Partition table is valid GPT contains usable blocks from 34 to 33554398 (inclusive) Total: 0 partitions
gpt dump
tells us some important info: it tells us (1) How big blocks are, and (2) which blocks we can actually use. Let's fill part of the disk with a MinFS filesystem.> gpt add 34 20000000 minfs /dev/class/block/002
lsblk
you should see a block device, which is the whole disk, and a slightly smaller device, which is the partition. In the above output, the partition is device 003, and would have the path /dev/class/block/003
> mkfs <PARTITION_PATH> minfs
lsblk
again to locate the entry for the disk. We want to edit the type of the zero-th partition. Here we use the keyword ‘fuchsia-data’ to set the type GUID, but if you wanted to use an arbitrary GUID you would supply it where ‘fuchsia-data’ is used.> gpt edit 0 type fuchsia-data <DEVICE_PATH>
On any future boots, the partition will be mounted automatically at /data
.
If you don't want the partition to be mounted automatically, you can update the visibility (or GUID) of the partition, and simply mount it manually.
> mount <PARTITION_PATH> /data
/data
(the mount point for this GUID) will persist across boots. To test this, try making a file on the new MinFS volume, rebooting, and observing it still exists.> touch /data/foobar > dm reboot > ls /data
> df <PATH>
The following section describes what IOs are performed to complete a simple end user operation like read()/write().
A row <operation> Total, like “Create Total”, gives the total number of blocks read/written. For operations involving journaling, the journal writes two more blocks, journal entry header and commit block, per operation. The number under write count for Total is the sum of WRITE COUNT (WITH JOURNALING) and journaling overhead, which is 2 blocks per operation.
Superblock, Inode table, Inode bitmap, Data bitmap, and a part of Journal are cached in memory while starting(mount/fsck) the filesystem. So, Read IOs are never issued for those BLOCK TYPES.
OPERATION | BLOCK TYPE | IO TYPE | JOURNALED | CONDITIONALLY ACCESSED | READ COUNT | WRITE COUNT(IGNORING JOURNAL) | WRITE COUNT(WITH JOURNAL) | COMMENTS |
---|---|---|---|---|---|---|---|---|
Lookup/Open | Data | Read | No | No | >=1 | 0 | 0 | If the directory is large, multiple blocks are read. |
Indirect | Read | No | Yes | >=0 | 0 | 0 | Lookup can be served by direct blocks. So indirect is optional. | |
DIndirect | Read | No | Yes | >=0 | 0 | 0 | Lookup can be served by direct blocks. So dindirect is optional. | |
Lookup/Open Total | >=1 | 0 | 0 | |||||
Create | Data | Read | No | No | >=1 | 0 | 0 | Create involves lookup first for name collisions. |
Indirect | Read | No | Yes | >=0 | 0 | 0 | ||
DIndirect | Read | No | Yes | >=0 | 0 | 0 | ||
Data | Write | Yes | No | 0 | >=1 | >=2 | ||
Indirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
DIndirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
Inode table | Write | Yes | No | 0 | 1 | 2 | Inode for the new file. | |
Inode bitmap | Write | Yes | No | 0 | 1 | 2 | Mark inode as allocated. | |
Data bitmap | Write | Yes | No | 0 | >=0 | >=0 | Directory may grow to contain new directory entry. | |
Superblock | Write | Yes | No | 0 | 1 | 2 | Among other things, allocated inode number changes. | |
Create Total | >=1 | >=4 | >=10 | Includes 2 blocks for journal entry. | ||||
Rename | Data | Read | No | No | >=1 | 0 | 0 | Rename involves a lookup in source directory. |
Indirect | Read | No | Yes | >=0 | 0 | 0 | ||
DIndirect | Read | No | Yes | >=0 | 0 | 0 | ||
Data | Write | Yes | No | 0 | >=1 | >=2 | Source directory entry. | |
Indirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
DIndirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
Inode table | Write | Yes | No | 0 | 1 | 2 | To update source directory inode. | |
Data | Read | No | No | >=0 | 0 | 0 | Rename involves a lookup in source directory. | |
Indirect | Read | No | Yes | >=0 | 0 | 0 | ||
DIndirect | Read | No | Yes | >=0 | 0 | 0 | ||
Data | Write | Yes | Yes | 0 | >=0 | >=0 | Writing destination directory entry. | |
Indirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
DIndirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
Inode table | Write | Yes | Yes | 0 | 1 | 2 | To update destination directory inode. | |
Inode table | Write | Yes | No | 0 | 1 | 2 | Renamed file’s mtime. | |
Data bitmap | Write | Yes | No | 0 | >=0 | >=0 | In case we allocated data, indirect or Dindirect block(s). | |
Superblock | Write | Yes | No | 0 | 1 | 2 | ||
Rename Total | >=1 | >=5 | >=12 | Includes 2 blocks for journal entry. | ||||
Read | Data | Read | No | No | >=1 | 0 | 0 | |
Indirect | Read | No | Yes | >=0 | 0 | 0 | ||
DIndirect | Read | No | Yes | >=0 | 0 | 0 | ||
Read Total | >=1 | 0 | 0 | |||||
Write | Indirect | Read | No | Yes | >=0 | 0 | 0 | Even if the write is not overwriting, we may share (D)indirect block with existing data. Leading to read modify write. |
DIndirect | Read | No | Yes | >=0 | 0 | 0 | ||
Data | Write | No | No | 0 | 1 | 1 | ||
Indirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
DIndirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
Inode table | Write | Yes | No | 0 | 1 | 2 | Inode's mtime update. | |
Data bitmap | Write | Yes | No | 0 | 1 | 2 | For the allocated block. | |
Superblock | Write | Yes | No | 0 | 1 | 2 | Change in number of allocated blocks. | |
Write Total | >=0 | >=4 | >=9 | Includes 2 blocks for journal entry. | ||||
Overwrite | Data | Read | No | Yes | >=0 | 0 | 0 | Read modify write. |
Indirect | Read | No | Yes | >=0 | 0 | 0 | ||
DIndirect | Read | No | Yes | >=0 | 0 | 0 | ||
Data | Write | No | No | 0 | 1 | 1 | ||
Indirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
DIndirect | Write | Yes | Yes | 0 | >=0 | >=0 | ||
Inode table | Write | Yes | No | 0 | 1 | 2 | ||
Data bitmap | Write | Yes | No | 0 | 1 | 2 | Write new allocation. | |
Data bitmap | Write | Yes | No | 0 | >=0 | >=0 | Free old block. This block bit may belong to allocated block bitmap. | |
Superblock | Write | Yes | No | 0 | 1 | 2 | ||
Overwrite Total | >=0 | >=4 | >=9 | Includes 2 blocks for journal entry. |