|
@@ -1507,12 +1507,17 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
|
|
|
}
|
|
|
|
|
|
reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
|
|
|
- ret = btrfs_check_data_free_space(inode, reserve_bytes, write_bytes);
|
|
|
- if (ret == -ENOSPC &&
|
|
|
- (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
|
|
|
- BTRFS_INODE_PREALLOC))) {
|
|
|
+
|
|
|
+ if (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
|
|
|
+ BTRFS_INODE_PREALLOC)) {
|
|
|
ret = check_can_nocow(inode, pos, &write_bytes);
|
|
|
+ if (ret < 0)
|
|
|
+ break;
|
|
|
if (ret > 0) {
|
|
|
+ /*
|
|
|
+ * For nodata cow case, no need to reserve
|
|
|
+ * data space.
|
|
|
+ */
|
|
|
only_release_metadata = true;
|
|
|
/*
|
|
|
* our prealloc extent may be smaller than
|
|
@@ -1521,20 +1526,19 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
|
|
|
num_pages = DIV_ROUND_UP(write_bytes + offset,
|
|
|
PAGE_CACHE_SIZE);
|
|
|
reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
|
|
|
- ret = 0;
|
|
|
- } else {
|
|
|
- ret = -ENOSPC;
|
|
|
+ goto reserve_metadata;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- if (ret)
|
|
|
+ ret = __btrfs_check_data_free_space(inode, pos, write_bytes);
|
|
|
+ if (ret < 0)
|
|
|
break;
|
|
|
|
|
|
+reserve_metadata:
|
|
|
ret = btrfs_delalloc_reserve_metadata(inode, reserve_bytes);
|
|
|
if (ret) {
|
|
|
if (!only_release_metadata)
|
|
|
- btrfs_free_reserved_data_space(inode,
|
|
|
- reserve_bytes);
|
|
|
+ __btrfs_free_reserved_data_space(inode, pos,
|
|
|
+ write_bytes);
|
|
|
else
|
|
|
btrfs_end_write_no_snapshoting(root);
|
|
|
break;
|
|
@@ -2566,8 +2570,11 @@ static long btrfs_fallocate(struct file *file, int mode,
|
|
|
/*
|
|
|
* Make sure we have enough space before we do the
|
|
|
* allocation.
|
|
|
+ * XXX: The behavior must be changed to do accurate check first
|
|
|
+ * and then check data reserved space.
|
|
|
*/
|
|
|
- ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start, alloc_end - alloc_start);
|
|
|
+ ret = btrfs_check_data_free_space(inode, alloc_start,
|
|
|
+ alloc_end - alloc_start);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -2700,7 +2707,8 @@ static long btrfs_fallocate(struct file *file, int mode,
|
|
|
out:
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
|
/* Let go of our reservation. */
|
|
|
- btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
|
|
|
+ __btrfs_free_reserved_data_space(inode, alloc_start,
|
|
|
+ alloc_end - alloc_start);
|
|
|
return ret;
|
|
|
}
|
|
|
|