• Andrew Morton's avatar
    [PATCH] ext3: fix scheduling storm and lockups · cd9ab8c2
    Andrew Morton authored
    There have been sporadic sightings of ext3 causing little blips of 100,000
    context switches per second when under load.
    
    At the start of do_get_write_access() we have this logic:
    
    	repeat:
    		lock_buffer(jh->bh);
    		...
    		unlock_buffer(jh->bh);
    		...
    		if (jh->j_list == BJ_Shadow) {
    			sleep_on_buffer(jh->bh);
    			goto repeat;
    		}
    
    The problem is that the unlock_buffer() will wake up anyone who is sleeping
    in the sleep_on_buffer().
    
    So if task A is asleep in sleep_on_buffer() and task B now runs
    do_get_write_access(), task B will wake task A by accident.  Task B will then
    sleep on the buffer and task A will loop, will run unlock_buffer() and then
    wake task B.
    
    This state will continue until I/O completes against the buffer and kjournal
    changes jh->j_list.
    
    Unless task A and task B happen to both have realtime scheduling policy - if
    they do then kjournald will never run.  The state is never cleared and your
    box locks up.
    
    
    The fix is to not do the `goto repeat;' until the buffer has been taken of
    the shadow list.  So we don't go and wake up the other waiter(s) until they
    can actually proceed to use the buffer.
    
    The patch removes the exported sleep_on_buffer() function and simply exports
    an existing function which provides access to a buffer_head's waitqueue
    pointer.  Which is a better interface anyway, because it permits the use of
    wait_event().
    
    This bug was introduced introduced into 2.4.20-pre5 and was faithfully ported
    up.
    cd9ab8c2
buffer.c 74.6 KB