aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-06-21 14:05:49 -0400
committerChris Mason <chris.mason@fusionio.com>2012-07-23 15:41:40 -0400
commit96c3f4331a8c1cd0a58307e4ac7e73e09d7dab23 (patch)
tree9791f09825d0a03b66a2c2b41a40ef5d3bd79b71 /fs/btrfs
parentb27f7c0c150f74564b5d4c6c24a03c5226bf6327 (diff)
Btrfs: flush delayed inodes if we're short on space
Those crazy gentoo guys have been complaining about ENOSPC errors on their portage volumes. This is because doing things like untar tends to create lots of new files which will soak up all the reservation space in the delayed inodes. Usually this gets papered over by the fact that we will try and commit the transaction, however if this happens in the wrong spot or we choose not to commit the transaction you will be screwed. So add the ability to expclitly flush delayed inodes to free up space. Please test this out guys to make sure it works since as usual I cannot reproduce. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/delayed-inode.c22
-rw-r--r--fs/btrfs/delayed-inode.h2
-rw-r--r--fs/btrfs/extent-tree.c97
3 files changed, 83 insertions, 38 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 2399f4086915..21d91a8073ee 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1113,8 +1113,8 @@ static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
1113 * Returns < 0 on error and returns with an aborted transaction with any 1113 * Returns < 0 on error and returns with an aborted transaction with any
1114 * outstanding delayed items cleaned up. 1114 * outstanding delayed items cleaned up.
1115 */ 1115 */
1116int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, 1116static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
1117 struct btrfs_root *root) 1117 struct btrfs_root *root, int nr)
1118{ 1118{
1119 struct btrfs_root *curr_root = root; 1119 struct btrfs_root *curr_root = root;
1120 struct btrfs_delayed_root *delayed_root; 1120 struct btrfs_delayed_root *delayed_root;
@@ -1122,6 +1122,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
1122 struct btrfs_path *path; 1122 struct btrfs_path *path;
1123 struct btrfs_block_rsv *block_rsv; 1123 struct btrfs_block_rsv *block_rsv;
1124 int ret = 0; 1124 int ret = 0;
1125 bool count = (nr > 0);
1125 1126
1126 if (trans->aborted) 1127 if (trans->aborted)
1127 return -EIO; 1128 return -EIO;
@@ -1137,7 +1138,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
1137 delayed_root = btrfs_get_delayed_root(root); 1138 delayed_root = btrfs_get_delayed_root(root);
1138 1139
1139 curr_node = btrfs_first_delayed_node(delayed_root); 1140 curr_node = btrfs_first_delayed_node(delayed_root);
1140 while (curr_node) { 1141 while (curr_node && (!count || (count && nr--))) {
1141 curr_root = curr_node->root; 1142 curr_root = curr_node->root;
1142 ret = btrfs_insert_delayed_items(trans, path, curr_root, 1143 ret = btrfs_insert_delayed_items(trans, path, curr_root,
1143 curr_node); 1144 curr_node);
@@ -1149,6 +1150,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
1149 path, curr_node); 1150 path, curr_node);
1150 if (ret) { 1151 if (ret) {
1151 btrfs_release_delayed_node(curr_node); 1152 btrfs_release_delayed_node(curr_node);
1153 curr_node = NULL;
1152 btrfs_abort_transaction(trans, root, ret); 1154 btrfs_abort_transaction(trans, root, ret);
1153 break; 1155 break;
1154 } 1156 }
@@ -1158,12 +1160,26 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
1158 btrfs_release_delayed_node(prev_node); 1160 btrfs_release_delayed_node(prev_node);
1159 } 1161 }
1160 1162
1163 if (curr_node)
1164 btrfs_release_delayed_node(curr_node);
1161 btrfs_free_path(path); 1165 btrfs_free_path(path);
1162 trans->block_rsv = block_rsv; 1166 trans->block_rsv = block_rsv;
1163 1167
1164 return ret; 1168 return ret;
1165} 1169}
1166 1170
1171int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
1172 struct btrfs_root *root)
1173{
1174 return __btrfs_run_delayed_items(trans, root, -1);
1175}
1176
1177int btrfs_run_delayed_items_nr(struct btrfs_trans_handle *trans,
1178 struct btrfs_root *root, int nr)
1179{
1180 return __btrfs_run_delayed_items(trans, root, nr);
1181}
1182
1167static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, 1183static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
1168 struct btrfs_delayed_node *node) 1184 struct btrfs_delayed_node *node)
1169{ 1185{
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
index f5aa4023d3e1..4f808e1baeed 100644
--- a/fs/btrfs/delayed-inode.h
+++ b/fs/btrfs/delayed-inode.h
@@ -107,6 +107,8 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode);
107 107
108int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, 108int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
109 struct btrfs_root *root); 109 struct btrfs_root *root);
110int btrfs_run_delayed_items_nr(struct btrfs_trans_handle *trans,
111 struct btrfs_root *root, int nr);
110 112
111void btrfs_balance_delayed_items(struct btrfs_root *root); 113void btrfs_balance_delayed_items(struct btrfs_root *root);
112 114
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 6e1d36702ff7..3cde907a25a5 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3728,6 +3728,60 @@ commit:
3728 return btrfs_commit_transaction(trans, root); 3728 return btrfs_commit_transaction(trans, root);
3729} 3729}
3730 3730
3731enum flush_state {
3732 FLUSH_DELALLOC = 1,
3733 FLUSH_DELALLOC_WAIT = 2,
3734 FLUSH_DELAYED_ITEMS_NR = 3,
3735 FLUSH_DELAYED_ITEMS = 4,
3736 COMMIT_TRANS = 5,
3737};
3738
3739static int flush_space(struct btrfs_root *root,
3740 struct btrfs_space_info *space_info, u64 num_bytes,
3741 u64 orig_bytes, int state)
3742{
3743 struct btrfs_trans_handle *trans;
3744 int nr;
3745 int ret;
3746
3747 switch (state) {
3748 case FLUSH_DELALLOC:
3749 case FLUSH_DELALLOC_WAIT:
3750 ret = shrink_delalloc(root, num_bytes,
3751 state == FLUSH_DELALLOC_WAIT);
3752 if (ret > 0)
3753 ret = 0;
3754 break;
3755 case FLUSH_DELAYED_ITEMS_NR:
3756 case FLUSH_DELAYED_ITEMS:
3757 if (state == FLUSH_DELAYED_ITEMS_NR) {
3758 u64 bytes = btrfs_calc_trans_metadata_size(root, 1);
3759
3760 nr = (int)div64_u64(num_bytes, bytes);
3761 if (!nr)
3762 nr = 1;
3763 nr *= 2;
3764 } else {
3765 nr = -1;
3766 }
3767 trans = btrfs_join_transaction(root);
3768 if (IS_ERR(trans)) {
3769 ret = PTR_ERR(trans);
3770 break;
3771 }
3772 ret = btrfs_run_delayed_items_nr(trans, root, nr);
3773 btrfs_end_transaction(trans, root);
3774 break;
3775 case COMMIT_TRANS:
3776 ret = may_commit_transaction(root, space_info, orig_bytes, 0);
3777 break;
3778 default:
3779 ret = -ENOSPC;
3780 break;
3781 }
3782
3783 return ret;
3784}
3731/** 3785/**
3732 * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space 3786 * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space
3733 * @root - the root we're allocating for 3787 * @root - the root we're allocating for
@@ -3749,11 +3803,10 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
3749 struct btrfs_space_info *space_info = block_rsv->space_info; 3803 struct btrfs_space_info *space_info = block_rsv->space_info;
3750 u64 used; 3804 u64 used;
3751 u64 num_bytes = orig_bytes; 3805 u64 num_bytes = orig_bytes;
3752 int retries = 0; 3806 int flush_state = FLUSH_DELALLOC;
3753 int ret = 0; 3807 int ret = 0;
3754 bool committed = false;
3755 bool flushing = false; 3808 bool flushing = false;
3756 bool wait_ordered = false; 3809 bool committed = false;
3757 3810
3758again: 3811again:
3759 ret = 0; 3812 ret = 0;
@@ -3812,9 +3865,8 @@ again:
3812 * amount plus the amount of bytes that we need for this 3865 * amount plus the amount of bytes that we need for this
3813 * reservation. 3866 * reservation.
3814 */ 3867 */
3815 wait_ordered = true;
3816 num_bytes = used - space_info->total_bytes + 3868 num_bytes = used - space_info->total_bytes +
3817 (orig_bytes * (retries + 1)); 3869 (orig_bytes * 2);
3818 } 3870 }
3819 3871
3820 if (ret) { 3872 if (ret) {
@@ -3867,8 +3919,6 @@ again:
3867 trace_btrfs_space_reservation(root->fs_info, 3919 trace_btrfs_space_reservation(root->fs_info,
3868 "space_info", space_info->flags, orig_bytes, 1); 3920 "space_info", space_info->flags, orig_bytes, 1);
3869 ret = 0; 3921 ret = 0;
3870 } else {
3871 wait_ordered = true;
3872 } 3922 }
3873 } 3923 }
3874 3924
@@ -3887,36 +3937,13 @@ again:
3887 if (!ret || !flush) 3937 if (!ret || !flush)
3888 goto out; 3938 goto out;
3889 3939
3890 /* 3940 ret = flush_space(root, space_info, num_bytes, orig_bytes,
3891 * We do synchronous shrinking since we don't actually unreserve 3941 flush_state);
3892 * metadata until after the IO is completed. 3942 flush_state++;
3893 */ 3943 if (!ret)
3894 ret = shrink_delalloc(root, num_bytes, wait_ordered);
3895 if (ret < 0)
3896 goto out;
3897
3898 ret = 0;
3899
3900 /*
3901 * So if we were overcommitted it's possible that somebody else flushed
3902 * out enough space and we simply didn't have enough space to reclaim,
3903 * so go back around and try again.
3904 */
3905 if (retries < 2) {
3906 wait_ordered = true;
3907 retries++;
3908 goto again; 3944 goto again;
3909 } 3945 else if (flush_state <= COMMIT_TRANS)
3910
3911 ret = -ENOSPC;
3912 if (committed)
3913 goto out;
3914
3915 ret = may_commit_transaction(root, space_info, orig_bytes, 0);
3916 if (!ret) {
3917 committed = true;
3918 goto again; 3946 goto again;
3919 }
3920 3947
3921out: 3948out:
3922 if (flushing) { 3949 if (flushing) {