• Mingming Cao's avatar
    [PATCH] ext3: fix race between ext3 make block reservation and reservation window discard · b8bbd251
    Mingming Cao authored
    This patch fixed a race between ext3_discard_reservation() and
    ext3_try_to_allocate_with_rsv().
    
    There is a window where ext3_discard_reservation will remove an already
    unlinked reservation window node from the filesystem reservation tree:
    It thinks the reservation is still linked in the filesystem reservation
    tree, but it is actually temperately removed from the tree by
    allocate_new_reservation() when it failed to make a new reservation from
    the current group and try to make a new reservation from next block
    group.
    
    Here is how it could happen:
    
    CPU 1
    try to allocate a block in group1 with given reservation window my_rsv
    ext3_try_to_allocate_with_rsv(group
    	----copy reservation window my_rsv into local rsv_copy
    	ext3_try_to_allocate(...rsv_copy) 
    		----no free block in existing reservation window, 
    		----need a new reservation window
    	spin_lock(&rsv_lock);
    
    CPU 2
    
    ext3_discard_reservation
    	if (!rsv_is_empty()
    		----this is true
    	spin_lock(&rsv_lock)
    		----waiting for thread 1
    
    CPU 1:
    
    	allocate_new_reservation
    		failed to reserve blocks in this group
    		remove the window from the tree
    		rsv_window_remove(my_rsv)
    			----window node is unlinked from the tree here
    		return -1
    	spin_unlock(&rsv_lock)
    ext3_try_to_allocate_with_rsv() failed in this group
    group++
    
    CPU 2
    	spin_lock(&rsv_lock) succeed
    	rsv_remove_window ()
    		---------------break, trying to remove a unlinked node from the tree
    	....
    	
    
    CPU 1:
    ext3_try_to_allocate_with_rsv(group, my_rsv)
    	rsv_is_empty is true, need a new reservation window
    	spin_lock(&rsv_lock);
    		^--------------- spinning forever
    
    We need to re-check whether the reservation window is still linked to
    the tree after grab the rsv_lock spin lock in ext3_discard_reservation,
    to prevent panic in rsv_remove_window->rb_erase.
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    b8bbd251
balloc.c 45.3 KB