Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Btrfs: fix wrong free space information

Btrfs subtracted the size of the allocated space twice when it allocated
the space from the bitmap in the cluster, it broke the free space information
and led to oops finally.

And this patch also fixes the bug that ctl->free_space was subtracted
without lock.

Reported-by: Liu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>

authored by

Miao Xie and committed by
Chris Mason
bb3ac5a4 f4ac904c

+11 -5
+11 -5
fs/btrfs/free-space-cache.c
··· 1168 1168 div64_u64(extent_bytes, (sizeof(struct btrfs_free_space))); 1169 1169 } 1170 1170 1171 - static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, 1172 - struct btrfs_free_space *info, u64 offset, 1173 - u64 bytes) 1171 + static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, 1172 + struct btrfs_free_space *info, 1173 + u64 offset, u64 bytes) 1174 1174 { 1175 1175 unsigned long start, count; 1176 1176 ··· 1181 1181 bitmap_clear(info->bitmap, start, count); 1182 1182 1183 1183 info->bytes -= bytes; 1184 + } 1185 + 1186 + static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, 1187 + struct btrfs_free_space *info, u64 offset, 1188 + u64 bytes) 1189 + { 1190 + __bitmap_clear_bits(ctl, info, offset, bytes); 1184 1191 ctl->free_space -= bytes; 1185 1192 } 1186 1193 ··· 1991 1984 return 0; 1992 1985 1993 1986 ret = search_start; 1994 - bitmap_clear_bits(ctl, entry, ret, bytes); 1987 + __bitmap_clear_bits(ctl, entry, ret, bytes); 1995 1988 1996 1989 return ret; 1997 1990 } ··· 2046 2039 continue; 2047 2040 } 2048 2041 } else { 2049 - 2050 2042 ret = entry->offset; 2051 2043 2052 2044 entry->offset += bytes;