Commit 6599716
btrfs: fix -ENOSPC mmap write failure on NOCOW files/extents
If we attempt a mmap write into a NOCOW file or a prealloc extent when
there is no more available data space (or unallocated space to allocate a
new data block group) and we can do a NOCOW write (there are no reflinks
for the target extent or snapshots), we always fail due to -ENOSPC, unlike
for the regular buffered write and direct IO paths where we check that we
can do a NOCOW write in case we can't reserve data space.
Simple reproducer:
$ cat test.sh
#!/bin/bash
DEV=/dev/sdi
MNT=/mnt/sdi
umount $DEV &> /dev/null
mkfs.btrfs -f -b $((512 * 1024 * 1024)) $DEV
mount $DEV $MNT
touch $MNT/foobar
# Make it a NOCOW file.
chattr +C $MNT/foobar
# Add initial data to file.
xfs_io -c "pwrite -S 0xab 0 1M" $MNT/foobar
# Fill all the remaining data space and unallocated space with data.
dd if=/dev/zero of=$MNT/filler bs=4K &> /dev/null
# Overwrite the file with a mmap write. Should succeed.
xfs_io -c "mmap -w 0 1M" \
-c "mwrite -S 0xcd 0 1M" \
-c "munmap" \
$MNT/foobar
# Unmount, mount again and verify the new data was persisted.
umount $MNT
mount $DEV $MNT
od -A d -t x1 $MNT/foobar
umount $MNT
Running this:
$ ./test.sh
(...)
wrote 1048576/1048576 bytes at offset 0
1 MiB, 256 ops; 0.0008 sec (1.188 GiB/sec and 311435.5231 ops/sec)
./test.sh: line 24: 234865 Bus error xfs_io -c "mmap -w 0 1M" -c "mwrite -S 0xcd 0 1M" -c "munmap" $MNT/foobar
0000000 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab
*
1048576
Fix this by not failing in case we can't allocate data space and we can
NOCOW into the target extent - reserving only metadata space in this case.
After this change the test passes:
$ ./test.sh
(...)
wrote 1048576/1048576 bytes at offset 0
1 MiB, 256 ops; 0.0007 sec (1.262 GiB/sec and 330749.3540 ops/sec)
0000000 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
*
1048576
A test case for fstests will be added soon.
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>1 parent e8d2e25 commit 6599716
1 file changed
Lines changed: 51 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1841 | 1841 | | |
1842 | 1842 | | |
1843 | 1843 | | |
| 1844 | + | |
1844 | 1845 | | |
1845 | 1846 | | |
1846 | 1847 | | |
| |||
1861 | 1862 | | |
1862 | 1863 | | |
1863 | 1864 | | |
1864 | | - | |
1865 | | - | |
1866 | | - | |
| 1865 | + | |
| 1866 | + | |
| 1867 | + | |
| 1868 | + | |
| 1869 | + | |
| 1870 | + | |
| 1871 | + | |
| 1872 | + | |
| 1873 | + | |
| 1874 | + | |
| 1875 | + | |
| 1876 | + | |
| 1877 | + | |
| 1878 | + | |
| 1879 | + | |
| 1880 | + | |
| 1881 | + | |
| 1882 | + | |
| 1883 | + | |
| 1884 | + | |
| 1885 | + | |
| 1886 | + | |
| 1887 | + | |
| 1888 | + | |
| 1889 | + | |
| 1890 | + | |
1867 | 1891 | | |
| 1892 | + | |
1868 | 1893 | | |
1869 | 1894 | | |
1870 | 1895 | | |
| |||
1905 | 1930 | | |
1906 | 1931 | | |
1907 | 1932 | | |
| 1933 | + | |
| 1934 | + | |
1908 | 1935 | | |
1909 | | - | |
1910 | | - | |
1911 | | - | |
| 1936 | + | |
| 1937 | + | |
| 1938 | + | |
| 1939 | + | |
| 1940 | + | |
| 1941 | + | |
| 1942 | + | |
1912 | 1943 | | |
1913 | 1944 | | |
1914 | 1945 | | |
| |||
1945 | 1976 | | |
1946 | 1977 | | |
1947 | 1978 | | |
| 1979 | + | |
| 1980 | + | |
| 1981 | + | |
| 1982 | + | |
1948 | 1983 | | |
1949 | 1984 | | |
1950 | 1985 | | |
1951 | 1986 | | |
| 1987 | + | |
| 1988 | + | |
1952 | 1989 | | |
1953 | 1990 | | |
1954 | 1991 | | |
| |||
1958 | 1995 | | |
1959 | 1996 | | |
1960 | 1997 | | |
1961 | | - | |
1962 | | - | |
| 1998 | + | |
| 1999 | + | |
| 2000 | + | |
| 2001 | + | |
| 2002 | + | |
1963 | 2003 | | |
1964 | 2004 | | |
| 2005 | + | |
| 2006 | + | |
| 2007 | + | |
1965 | 2008 | | |
1966 | 2009 | | |
1967 | 2010 | | |
| |||
0 commit comments