aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@redhat.com>2009-02-20 11:00:09 -0500
committerChris Mason <chris.mason@oracle.com>2009-02-20 11:00:09 -0500
commit6a63209fc02d5483371f07e4913ee8abad608051 (patch)
tree7595e0df452928b677b66a64baf0cb3b7ec53dfc /fs/btrfs/file.c
parent2cfbd50b536c878e58ab3681c4e944fa3d99b415 (diff)
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>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 872f104576e5..dc78954861b3 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1091,19 +1091,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1091 WARN_ON(num_pages > nrptrs); 1091 WARN_ON(num_pages > nrptrs);
1092 memset(pages, 0, sizeof(struct page *) * nrptrs); 1092 memset(pages, 0, sizeof(struct page *) * nrptrs);
1093 1093
1094 ret = btrfs_check_free_space(root, write_bytes, 0); 1094 ret = btrfs_check_data_free_space(root, inode, write_bytes);
1095 if (ret) 1095 if (ret)
1096 goto out; 1096 goto out;
1097 1097
1098 ret = prepare_pages(root, file, pages, num_pages, 1098 ret = prepare_pages(root, file, pages, num_pages,
1099 pos, first_index, last_index, 1099 pos, first_index, last_index,
1100 write_bytes); 1100 write_bytes);
1101 if (ret) 1101 if (ret) {
1102 btrfs_free_reserved_data_space(root, inode,
1103 write_bytes);
1102 goto out; 1104 goto out;
1105 }
1103 1106
1104 ret = btrfs_copy_from_user(pos, num_pages, 1107 ret = btrfs_copy_from_user(pos, num_pages,
1105 write_bytes, pages, buf); 1108 write_bytes, pages, buf);
1106 if (ret) { 1109 if (ret) {
1110 btrfs_free_reserved_data_space(root, inode,
1111 write_bytes);
1107 btrfs_drop_pages(pages, num_pages); 1112 btrfs_drop_pages(pages, num_pages);
1108 goto out; 1113 goto out;
1109 } 1114 }
@@ -1111,8 +1116,11 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1111 ret = dirty_and_release_pages(NULL, root, file, pages, 1116 ret = dirty_and_release_pages(NULL, root, file, pages,
1112 num_pages, pos, write_bytes); 1117 num_pages, pos, write_bytes);
1113 btrfs_drop_pages(pages, num_pages); 1118 btrfs_drop_pages(pages, num_pages);
1114 if (ret) 1119 if (ret) {
1120 btrfs_free_reserved_data_space(root, inode,
1121 write_bytes);
1115 goto out; 1122 goto out;
1123 }
1116 1124
1117 if (will_write) { 1125 if (will_write) {
1118 btrfs_fdatawrite_range(inode->i_mapping, pos, 1126 btrfs_fdatawrite_range(inode->i_mapping, pos,
@@ -1136,6 +1144,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1136 } 1144 }
1137out: 1145out:
1138 mutex_unlock(&inode->i_mutex); 1146 mutex_unlock(&inode->i_mutex);
1147 if (ret)
1148 err = ret;
1139 1149
1140out_nolock: 1150out_nolock:
1141 kfree(pages); 1151 kfree(pages);