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