Lecture: on-disk data structures
preparation
goals
- I/O stack
- high-level API: read/write/… using file names and file descriptors
- low-level API: using a block device
- terminology: block vs sector
data ← read(blockno)
write(blockno, data)
flush (ignore for now)
trim (ignore for now)
- example: xv6
- per-process
fd → struct file → fs layers (fs.c)
→ block I/O (bio.c) → disk driver (ide.c)
- walkthrough:
write() → sys_write() → filewrite() → writei() → bread()/bwrite() → iderw()
- what does
argfd() do in sys_write()?
- how does
filewrite() call different functions depending on the fd type?
data structures
- xv6 disk layout:
[ ... | superblock | log | inode blocks | free bitmap | data blocks ]
- superblock:
struct superblock in fs.h
- metadata about the entire file system
- often located at a pre-defined location (xv6: block 1)
- contain pointers to other parts of the file system
- free bitmap:
balloc/bfree in fs.c
- track free/in-use data blocks
- bit i in the free bitmap indicates whether data block i is free
- quiz
- how to check if data block i is free
- how to change it from free to in-use
- inode:
struct dinode in fs.h
- file metadata: type, size, (permission, time, …)
- contain pointers to data blocks: 12 direct blocks and 1 (single) indirect block
- goal: map (inode number, offset) to disk block number
- why indirect blocks? compare to two-level paging
- quiz
- does inode have a “name” field? why not?
- what’s the maximum file size
- given a file’s inode, how to read its n-th block - see
readi/bmap in fs.c
- file: inode + data blocks
- directory: a special “file”
- content:
struct dirents - (inode number, name) pairs
- map name to inode number
- questions
- how to locate
/d/f: how to locate the root directory, directory d, and file f
- how to append “hello” to
/d/f
- how to overwrite
/d/f with new data “world”
- how to create a new file
/newfile