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

btrfs: statfs: report zero available if metadata are exhausted

There is one ENOSPC case that's very confusing. There's Available
greater than zero but no file operation succeds (besides removing
files). This happens when the metadata are exhausted and there's no
possibility to allocate another chunk.

In this scenario it's normal that there's still some space in the data
chunk and the calculation in df reflects that in the Avail value.

To at least give some clue about the ENOSPC situation, let statfs report
zero value in Avail, even if there's still data space available.

Current:
/dev/sdb1 4.0G 3.3G 719M 83% /mnt/test

New:
/dev/sdb1 4.0G 3.3G 0 100% /mnt/test

We calculate the remaining metadata space minus global reserve. If this
is (supposedly) smaller than zero, there's no space. But this does not
hold in practice, the exhausted state happens where's still some
positive delta. So we apply some guesswork and compare the delta to a 4M
threshold. (Practically observed delta was 2M.)

We probably cannot calculate the exact threshold value because this
depends on the internal reservations requested by various operations, so
some operations that consume a few metadata will succeed even if the
Avail is zero. But this is better than the other way around.

Signed-off-by: David Sterba <dsterba@suse.com>

+24
+24
fs/btrfs/super.c
··· 1956 1956 * there are other factors that may change the result (like a new metadata 1957 1957 * chunk). 1958 1958 * 1959 + * If metadata is exhausted, f_bavail will be 0. 1960 + * 1959 1961 * FIXME: not accurate for mixed block groups, total and free/used are ok, 1960 1962 * available appears slightly larger. 1961 1963 */ ··· 1969 1967 struct btrfs_space_info *found; 1970 1968 u64 total_used = 0; 1971 1969 u64 total_free_data = 0; 1970 + u64 total_free_meta = 0; 1972 1971 int bits = dentry->d_sb->s_blocksize_bits; 1973 1972 __be32 *fsid = (__be32 *)fs_info->fsid; 1974 1973 unsigned factor = 1; 1975 1974 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 1976 1975 int ret; 1976 + u64 thresh = 0; 1977 1977 1978 1978 /* 1979 1979 * holding chunk_muext to avoid allocating new chunks, holding ··· 2001 1997 } 2002 1998 } 2003 1999 } 2000 + if (found->flags & BTRFS_BLOCK_GROUP_METADATA) 2001 + total_free_meta += found->disk_total - found->disk_used; 2004 2002 2005 2003 total_used += found->disk_used; 2006 2004 } ··· 2024 2018 return ret; 2025 2019 buf->f_bavail += div_u64(total_free_data, factor); 2026 2020 buf->f_bavail = buf->f_bavail >> bits; 2021 + 2022 + /* 2023 + * We calculate the remaining metadata space minus global reserve. If 2024 + * this is (supposedly) smaller than zero, there's no space. But this 2025 + * does not hold in practice, the exhausted state happens where's still 2026 + * some positive delta. So we apply some guesswork and compare the 2027 + * delta to a 4M threshold. (Practically observed delta was ~2M.) 2028 + * 2029 + * We probably cannot calculate the exact threshold value because this 2030 + * depends on the internal reservations requested by various 2031 + * operations, so some operations that consume a few metadata will 2032 + * succeed even if the Avail is zero. But this is better than the other 2033 + * way around. 2034 + */ 2035 + thresh = 4 * 1024 * 1024; 2036 + 2037 + if (total_free_meta - thresh < block_rsv->size) 2038 + buf->f_bavail = 0; 2027 2039 2028 2040 buf->f_type = BTRFS_SUPER_MAGIC; 2029 2041 buf->f_bsize = dentry->d_sb->s_blocksize;