Btrfs: Fix the write error into tiny space
RFC PATCH 1/1 Btrfs: Fix the write error into tiny space
reproduce:
dd if=/dev/zero of=tmpfile bs=4K count=1
dd if=/dev/zero of=tmpfile1 bs=1M
dd if=/dev/zero of=tmpfile2 bs=4K
rm -f tmpfile
sync
dd if=/dev/zero of=tmpfile bs=8K count=1
We try to create a 8K file when there is only 4K space left, btrfs will write no data into a file, but under EXT4 it will still write the first 4K data. Also the POSIX hopes we writting as much as possible.
quote the POSIX:
If a write() requests that more bytes be written than there is room for(for example, [XSI] [Option Start] the process' file size limit or [Option End] the physical end of a medium), only as many bytes as there is room for shall be written. For example, suppose there is space for 20 bytes more in a file before reaching a limit. A write of 512 bytes will return 20. The next write of a non-zero number of bytes would give a failure return (except as noted below).
--- fs/btrfs/file.c | 18 ++++++++++++++++-- 1 files changed, 16 insertions(+), 2 deletions(-)
fs/btrfs/file.c +16 -2
@@ -1179,11 +1179,14 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,size_t write_bytes =min (iov_iter_count (i), nrptrs * (size_t )PAGE_CACHE_SIZE - offset); -size_t num_pages = (write_bytes + offset + -PAGE_CACHE_SIZE -1 ) >>PAGE_CACHE_SHIFT ; +size_t num_pages;size_t dirty_pages;size_t copied; +again: + num_pages = (write_bytes + offset + +PAGE_CACHE_SIZE -1 ) >>PAGE_CACHE_SHIFT ; +WARN_ON (num_pages > nrptrs);/*
@@ -1197,6 +1200,17 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, ret =btrfs_delalloc_reserve_space (inode, num_pages <<PAGE_CACHE_SHIFT ); + +/* try to reserve smaller space for write */ +if (ret == -ENOSPC ) { +if (num_pages >1 ) { + write_bytes >>=1 ; + goto again; + }else { +break ; + } + } +if (ret)break ;
Signature · 1 line
1.7.3.1