• Josef Bacik's avatar
    Btrfs: fix regression in orphan cleanup · 6c090a11
    Josef Bacik authored
    Currently orphan cleanup only ever gets triggered if we cross subvolumes during
    a lookup, which means that if we just mount a plain jane fs that has orphans in
    it, they will never get cleaned up.  This results in panic's like these
    
    http://www.kerneloops.org/oops.php?number=1109085
    
    where adding an orphan entry results in -EEXIST being returned and we panic.  In
    order to fix this, we check to see on lookup if our root has had the orphan
    cleanup done, and if not go ahead and do it.  This is easily reproduceable by
    running this testcase
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main(int argc, char **argv)
    {
    	char data[4096];
    	char newdata[4096];
    	int fd1, fd2;
    
    	memset(data, 'a', 4096);
    	memset(newdata, 'b', 4096);
    
    	while (1) {
    		int i;
    
    		fd1 = creat("file1", 0666);
    		if (fd1 < 0)
    			break;
    
    		for (i = 0; i < 512; i++)
    			write(fd1, data, 4096);
    
    		fsync(fd1);
    		close(fd1);
    
    		fd2 = creat("file2", 0666);
    		if (fd2 < 0)
    			break;
    
    		ftruncate(fd2, 4096 * 512);
    
    		for (i = 0; i < 512; i++)
    			write(fd2, newdata, 4096);
    		close(fd2);
    
    		i = rename("file2", "file1");
    		unlink("file1");
    	}
    
    	return 0;
    }
    
    and then pulling the power on the box, and then trying to run that test again
    when the box comes back up.  I've tested this locally and it fixes the problem.
    Thanks to Tomas Carnecky for helping me track this down initially.
    Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
    Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
    6c090a11
inode.c 163 KB