On 2019/12/10 上午8:52, Qu Wenruo wrote: > > > On 2019/12/10 上午2:56, Martin Raiber wrote: >> On 07.12.2019 08:28 Qu Wenruo wrote: >>> >>> On 2019/12/7 上午5:26, Martin Raiber wrote: >>>> Hi, >>>> >>>> with kernel 5.4.1 I have the problem that df shows 100% space used. I >>>> can still write to the btrfs volume, but my software looks at the >>>> available space and starts deleting stuff if statfs() says there is a >>>> low amount of available space. >>> If the bug still happens, mind to try the snippet to see why this happened? >>> >>> You will need to: >>> - Apply the patch to your kernel code >>> - Recompile the kernel or btrfs module >>> So this needs some experience in kernel compile. >>> - Reboot to newly compiled kernel or load the debug btrfs module >>> >>> Thanks, >>> Qu >>> >>> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c >>> index 23aa630f04c9..cf34c05b16d7 100644 >>> --- a/fs/btrfs/relocation.c >>> +++ b/fs/btrfs/relocation.c >>> @@ -523,7 +523,8 @@ static int should_ignore_root(struct btrfs_root *root) >>> { >>> struct btrfs_root *reloc_root; >>> >>> - if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state)) >>> + if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state) || >>> + test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state)) >>> return 0; >>> >>> reloc_root = root->reloc_root; >>> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c >>> index f452a94abdc3..c2b70d97a63b 100644 >>> --- a/fs/btrfs/super.c >>> +++ b/fs/btrfs/super.c >>> @@ -2064,6 +2064,8 @@ static int btrfs_statfs(struct dentry *dentry, >>> struct kstatfs *buf) >>> found->disk_used; >>> } >>> >>> + pr_info("%s: found type=0x%llx disk_used=%llu factor=%d\n", >>> + __func__, found->flags, found->disk_used, factor); >>> total_used += found->disk_used; >>> } >>> >>> @@ -2071,6 +2073,8 @@ static int btrfs_statfs(struct dentry *dentry, >>> struct kstatfs *buf) >>> >>> buf->f_blocks = div_u64(btrfs_super_total_bytes(disk_super), >>> factor); >>> buf->f_blocks >>= bits; >>> + pr_info("%s: super_total_bytes=%llu total_used=%llu >>> factor=%d\n", __func__, >>> + btrfs_super_total_bytes(disk_super), total_used, factor); >>> buf->f_bfree = buf->f_blocks - (div_u64(total_used, factor) >> >>> bits); >>> >>> /* Account global block reserve as used, it's in logical size >>> already */ >>> >> Applied. It's currently 100% used directly after reboot, and I am >> getting this log output: > > Thank you a lot for the debug output! > >> >> [...] >> [  241.245150] btrfs_statfs: super_total_bytes=128835387392 >> total_used=93778841600 factor=1 >> [  241.904824] btrfs_statfs: found type=0x1 disk_used=93464006656 factor=1 >> [  241.904824] btrfs_statfs: found type=0x4 disk_used=314818560 factor=1 >> [  241.904824] btrfs_statfs: found type=0x2 disk_used=16384 factor=1 >> [  241.904824] btrfs_statfs: super_total_bytes=128835387392 >> total_used=93778841600 factor=1 > > This proves the on-disk numbers are all correct, so far so good. > > The remaining problem is the block_rsv part. Which matches with the new > ticket system introduced in v5.4. > > Mind to test the new debug snippet? > > diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c > index f452a94abdc3..516969534095 100644 > --- a/fs/btrfs/super.c > +++ b/fs/btrfs/super.c > @@ -2076,6 +2076,8 @@ static int btrfs_statfs(struct dentry *dentry, > struct kstatfs *buf) > /* Account global block reserve as used, it's in logical size > already */ > spin_lock(&block_rsv->lock); > /* Mixed block groups accounting is not byte-accurate, avoid > overflow */ > + pr_info("%s: block_rsv->size=%llu block_rsv->reserved=%llu\n", > __func__, > + block_rsv->size, block_rsv->reserved); > if (buf->f_bfree >= block_rsv->size >> bits) > buf->f_bfree -= block_rsv->size >> bits; > else > And this extra snippet for available space. Thanks, Qu diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index f452a94abdc3..f1a3e01a0ef5 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1911,6 +1911,7 @@ static inline int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info, * We aren't under the device list lock, so this is racy-ish, but good * enough for our purposes. */ + pr_info("%s: original_free_bytes=%llu\n", __func__, *free_bytes); nr_devices = fs_info->fs_devices->open_devices; if (!nr_devices) { smp_mb(); @@ -2005,6 +2006,7 @@ static inline int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info, kfree(devices_info); *free_bytes = avail_space; + pr_info("%s: calculated_bytes=%llu\n", __func__, avail_space); return 0; }