diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 71c172e12b190d57cbc2a634caaa98838a792b28..3c58fc34aa107660e04d634d935a4dbb0b7f540d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3356,7 +3356,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, num_pages *= 16; num_pages *= PAGE_CACHE_SIZE; - ret = btrfs_check_data_free_space(inode, num_pages, num_pages); + ret = __btrfs_check_data_free_space(inode, 0, num_pages); if (ret) goto out_put; @@ -3365,7 +3365,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, &alloc_hint); if (!ret) dcs = BTRFS_DC_SETUP; - btrfs_free_reserved_data_space(inode, num_pages); + __btrfs_free_reserved_data_space(inode, 0, num_pages); out_put: iput(inode); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 7031e9631519523d3c933c2190e724e85723c8b7..61fb78f1ea5c88c2acc1881b24c90e80a7425b1b 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -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; } diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 58ede0a564569ed082f09f4015229ab2cfd89f85..490c9e298c5804cd44cc3a372e470e67b2691dfa 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -3034,8 +3034,8 @@ int prealloc_file_extent_cluster(struct inode *inode, BUG_ON(cluster->start != cluster->boundary[0]); mutex_lock(&inode->i_mutex); - ret = btrfs_check_data_free_space(inode, cluster->end + - 1 - cluster->start, 0); + ret = __btrfs_check_data_free_space(inode, cluster->start, + cluster->end + 1 - cluster->start); if (ret) goto out; @@ -3056,8 +3056,8 @@ int prealloc_file_extent_cluster(struct inode *inode, break; nr++; } - btrfs_free_reserved_data_space(inode, cluster->end + - 1 - cluster->start); + __btrfs_free_reserved_data_space(inode, cluster->start, + cluster->end + 1 - cluster->start); out: mutex_unlock(&inode->i_mutex); return ret;