From: Ben Gras Date: Sun, 19 Jun 2005 22:33:49 +0000 (+0000) Subject: Fixed nasty bug that would cause FS to loop forever in rw_scattered (while X-Git-Tag: v3.1.0~728 X-Git-Url: http://zhaoyanbai.com/repos/%7B%24global.css%7D?a=commitdiff_plain;h=d844d2a547c09e5f38df0ac04b3940414c979cd7;p=minix.git Fixed nasty bug that would cause FS to loop forever in rw_scattered (while syncing, for instance) if blocks are unwritable. This could happen if: . write goes beyond device boundary to a block device . write is done for a complete block or more; thus the block is not retrieved first (at which point it would be noticed it doesn't exist), but the buffer is simply allocated . at write time, the device i/o doesn't succeed, but rw_scattered doesn't understand this and loops forever trying to get the block written. Currently, if no blocks can be written, the loop aborts, leaving all buffers intact but potentially dirty. When invalidate() is called on the device, the buffers will disappear (even if dirty). Same story for if the buffer is removed due to rmed from lru chain. There's not much we can do about this, however - we can't keep these blocks around, forever occupying a buffer in the buffer cache. The second part of the solution is not to let unwritable buffers be created in the first place. How to do this, however, without doing a wasteful read first? It looks like this code was in 2.0.4 too. --- diff --git a/servers/fs/cache.c b/servers/fs/cache.c index 6fe74c0fe..6ab4f5fc6 100644 --- a/servers/fs/cache.c +++ b/servers/fs/cache.c @@ -411,6 +411,14 @@ int rw_flag; /* READING or WRITING */ bufqsize--; } } + if(rw_flag == WRITING && i == 0) { + /* We're not making progress, this means we might keep + * looping. Buffers remain dirty if un-written. Buffers are + * lost if invalidate()d or LRU-removed while dirty. This + * is better than keeping unwritable blocks around forever.. + */ + break; + } } }