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 dirent
s - (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