Next: Common Errors
Up: Experience With Nachos Assignments
Previous: Virtual Memory
Locking is a major pain because WriteAt calls ReadAt
(on occasion). One probably wants to lock for both reads and writes,
but if one already has the lock (while writing) and then calls read,
potential deadlock scenarios appear immediately. Here are some
particularly tricky cases:
- It is tempting to have a single lock per file, which one
acquires as the first step in beginning a read or write. However,
there are cases where WriteAt also calls
ReadAt. Specifically, if WriteAt needs to write a partial
sector, it must first read the sector and then update the subset of
that sector the WriteAt refers to. However, if ReadAt
attempts to acquire the same lock that WriteAt already holds,
deadlock results.
- Consider updating an directory (as part of create). To properly
update the directory, it is read from disk, then modified in memory,
then written back out to disk. For correctness, access to the
directory must be locked for the duration of all operations (not just
while reading or writing). Otherwise, two threads could attempt to
update the directory simultaneously. If both threads read the
directory, modified separate in-memory copies and then wrote out the
changes, only one set of changes would make it out to disk. Note that
it is insufficient to lock the directory only during the reads and
writes; a lock must be held across both operations. Thus, acquiring
locks within ReadAt or WriteAt is insufficient.
- A similar scenario occurs when updating the freelist as part of
removing a file. One must first read the bitmap, update it, and then
flush the changes back out to disk. The bitmap routines
FetchFrom and WriteBack call ReadAt and
WriteAt respectively.
Thomas Narten
Mon Feb 3 15:00:27 EST 1997