Required reading: Chapter 15, 16, and 17
mount /dev/rk0 /mnt). For example, /dev/rk0
specifies the i-node for
a special file. the i-node contains a major device number and a minor
number. The major device number indexes into bdevsw (block device) or
cdevsw (character device). The minor number indexes into an array
within that device driver (if there are multiple devices of the same
type).
Driver fits in 3 pages of code.
buffers -
b_flags
B_READ - marks i/o read request
B_DONE - i/o has finished
B_ERROR - i/o caused error
B_BUSY - locked (not available)
B_WANTED - issue wakeup when !BUSY or DONE changes
B_ASYNC - don't wait for i/o completion
B_DELWRI - write before reusing block
b_forw b_back - device list
av_forw av_back - avail list
b_dev - device owning this block
b_wcounct - i/o params
b_addr
b_xmem
b_blkno
b_error - i/o error reason (not used)
b_resid - how much i/o happened
binit - put all blocks on free list
set up circular linked list on block device tabs
bread - read a block from disk into a buffer
how do errors get propagated?
- any read-only operations can just check for error on exit
- iget checks B_ERROR.
return locked block
breada - start a read for the block, but start i/o on the next block
return locked block, do not lock read-ahead block
(why can't someone get the read-ahead block before it's done?
the block is locked, and unlocked by iodone)
bwrite - write the block
handed a locked block, eventually unlocks it
bdwrite - release with delayed write
mark the block to be written later
unlock it but leave it in memory
why bawrite for tmtab?
bawrite - start async write of block
how do we know it's okay to call the strategy?
(strategy queues the blocks)
brelse - put the buffer back on the free list
unlock(b)
put b on freelist
wakeup(freelist) if needed
getblk - find a block for dev, blkno already in cache
return locked block
why is it safe to call notavail? what if it's already notavail
and the pointer is being used for something else?
iodone - finish with block after i/o finishes
b->flags |= B_DONE
if async write,
unlock(b)
else
wakeup(b)
iowait - wait for i/o to finish
waiting for B_DONE
geterror - set EIO with B_ERROR
bflush - flush all the write-behind blocks
bawrite on every block
doesn't actually wait for blocks to finish writing
devstart - generic DEC controller device i/o start
physio - start raw i/o
rkstrategy - add block to queue, kick disk driver (rkstart)
rkintr - note block finished
locking protocol -
lock(b)
while(b->flags&B_BUSY){
b->flags =| B_WANTED;
sleep(b, PRIBIO);
}
b->flags =| B_BUSY
unlock(b)
if(b->flags & B_WANTED)
wakeup(b)
b->flags =& ~B_BUSY
routines return locked blocks