Btrfs: add better -ENOSPC handling
This is a step in the direction of better -ENOSPC handling. Instead of checking the global bytes counter we check the space_info bytes counters to make sure we have enough space. If we don't we go ahead and try to allocate a new chunk, and then if that fails we return -ENOSPC. This patch adds two counters to btrfs_space_info, bytes_delalloc and bytes_may_use. bytes_delalloc account for extents we've actually setup for delalloc and will be allocated at some point down the line. bytes_may_use is to keep track of how many bytes we may use for delalloc at some point. When we actually set the extent_bit for the delalloc bytes we subtract the reserved bytes from the bytes_may_use counter. This keeps us from not actually being able to allocate space for any delalloc bytes. Signed-off-by: Josef Bacik <jbacik@redhat.com>
This commit is contained in:
@@ -1091,19 +1091,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
|
||||
WARN_ON(num_pages > nrptrs);
|
||||
memset(pages, 0, sizeof(struct page *) * nrptrs);
|
||||
|
||||
ret = btrfs_check_free_space(root, write_bytes, 0);
|
||||
ret = btrfs_check_data_free_space(root, inode, write_bytes);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = prepare_pages(root, file, pages, num_pages,
|
||||
pos, first_index, last_index,
|
||||
write_bytes);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
btrfs_free_reserved_data_space(root, inode,
|
||||
write_bytes);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_copy_from_user(pos, num_pages,
|
||||
write_bytes, pages, buf);
|
||||
if (ret) {
|
||||
btrfs_free_reserved_data_space(root, inode,
|
||||
write_bytes);
|
||||
btrfs_drop_pages(pages, num_pages);
|
||||
goto out;
|
||||
}
|
||||
@@ -1111,8 +1116,11 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
|
||||
ret = dirty_and_release_pages(NULL, root, file, pages,
|
||||
num_pages, pos, write_bytes);
|
||||
btrfs_drop_pages(pages, num_pages);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
btrfs_free_reserved_data_space(root, inode,
|
||||
write_bytes);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (will_write) {
|
||||
btrfs_fdatawrite_range(inode->i_mapping, pos,
|
||||
@@ -1136,6 +1144,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
if (ret)
|
||||
err = ret;
|
||||
|
||||
out_nolock:
|
||||
kfree(pages);
|
||||
|
Reference in New Issue
Block a user