diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 88f866f85e7a..c207e8c32c9b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -163,8 +163,14 @@ static void wait_current_trans(struct btrfs_root *root) | |||
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | enum btrfs_trans_type { | ||
167 | TRANS_START, | ||
168 | TRANS_JOIN, | ||
169 | TRANS_USERSPACE, | ||
170 | }; | ||
171 | |||
166 | static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | 172 | static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, |
167 | int num_blocks, int wait) | 173 | int num_blocks, int type) |
168 | { | 174 | { |
169 | struct btrfs_trans_handle *h = | 175 | struct btrfs_trans_handle *h = |
170 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | 176 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); |
@@ -172,7 +178,8 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
172 | 178 | ||
173 | mutex_lock(&root->fs_info->trans_mutex); | 179 | mutex_lock(&root->fs_info->trans_mutex); |
174 | if (!root->fs_info->log_root_recovering && | 180 | if (!root->fs_info->log_root_recovering && |
175 | ((wait == 1 && !root->fs_info->open_ioctl_trans) || wait == 2)) | 181 | ((type == TRANS_START && !root->fs_info->open_ioctl_trans) || |
182 | type == TRANS_USERSPACE)) | ||
176 | wait_current_trans(root); | 183 | wait_current_trans(root); |
177 | ret = join_transaction(root); | 184 | ret = join_transaction(root); |
178 | BUG_ON(ret); | 185 | BUG_ON(ret); |
@@ -186,6 +193,9 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
186 | h->alloc_exclude_start = 0; | 193 | h->alloc_exclude_start = 0; |
187 | h->delayed_ref_updates = 0; | 194 | h->delayed_ref_updates = 0; |
188 | 195 | ||
196 | if (!current->journal_info && type != TRANS_USERSPACE) | ||
197 | current->journal_info = h; | ||
198 | |||
189 | root->fs_info->running_transaction->use_count++; | 199 | root->fs_info->running_transaction->use_count++; |
190 | record_root_in_trans(h, root); | 200 | record_root_in_trans(h, root); |
191 | mutex_unlock(&root->fs_info->trans_mutex); | 201 | mutex_unlock(&root->fs_info->trans_mutex); |
@@ -195,18 +205,18 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
195 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 205 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |
196 | int num_blocks) | 206 | int num_blocks) |
197 | { | 207 | { |
198 | return start_transaction(root, num_blocks, 1); | 208 | return start_transaction(root, num_blocks, TRANS_START); |
199 | } | 209 | } |
200 | struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, | 210 | struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, |
201 | int num_blocks) | 211 | int num_blocks) |
202 | { | 212 | { |
203 | return start_transaction(root, num_blocks, 0); | 213 | return start_transaction(root, num_blocks, TRANS_JOIN); |
204 | } | 214 | } |
205 | 215 | ||
206 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, | 216 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, |
207 | int num_blocks) | 217 | int num_blocks) |
208 | { | 218 | { |
209 | return start_transaction(r, num_blocks, 2); | 219 | return start_transaction(r, num_blocks, TRANS_USERSPACE); |
210 | } | 220 | } |
211 | 221 | ||
212 | /* wait for a transaction commit to be fully complete */ | 222 | /* wait for a transaction commit to be fully complete */ |
@@ -317,6 +327,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
317 | wake_up(&cur_trans->writer_wait); | 327 | wake_up(&cur_trans->writer_wait); |
318 | put_transaction(cur_trans); | 328 | put_transaction(cur_trans); |
319 | mutex_unlock(&info->trans_mutex); | 329 | mutex_unlock(&info->trans_mutex); |
330 | |||
331 | if (current->journal_info == trans) | ||
332 | current->journal_info = NULL; | ||
320 | memset(trans, 0, sizeof(*trans)); | 333 | memset(trans, 0, sizeof(*trans)); |
321 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 334 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
322 | 335 | ||
@@ -338,10 +351,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, | |||
338 | /* | 351 | /* |
339 | * when btree blocks are allocated, they have some corresponding bits set for | 352 | * when btree blocks are allocated, they have some corresponding bits set for |
340 | * them in one of two extent_io trees. This is used to make sure all of | 353 | * them in one of two extent_io trees. This is used to make sure all of |
341 | * those extents are on disk for transaction or log commit | 354 | * those extents are sent to disk but does not wait on them |
342 | */ | 355 | */ |
343 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 356 | int btrfs_write_marked_extents(struct btrfs_root *root, |
344 | struct extent_io_tree *dirty_pages) | 357 | struct extent_io_tree *dirty_pages) |
345 | { | 358 | { |
346 | int ret; | 359 | int ret; |
347 | int err = 0; | 360 | int err = 0; |
@@ -388,6 +401,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | |||
388 | page_cache_release(page); | 401 | page_cache_release(page); |
389 | } | 402 | } |
390 | } | 403 | } |
404 | if (err) | ||
405 | werr = err; | ||
406 | return werr; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * when btree blocks are allocated, they have some corresponding bits set for | ||
411 | * them in one of two extent_io trees. This is used to make sure all of | ||
412 | * those extents are on disk for transaction or log commit. We wait | ||
413 | * on all the pages and clear them from the dirty pages state tree | ||
414 | */ | ||
415 | int btrfs_wait_marked_extents(struct btrfs_root *root, | ||
416 | struct extent_io_tree *dirty_pages) | ||
417 | { | ||
418 | int ret; | ||
419 | int err = 0; | ||
420 | int werr = 0; | ||
421 | struct page *page; | ||
422 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
423 | u64 start = 0; | ||
424 | u64 end; | ||
425 | unsigned long index; | ||
426 | |||
391 | while (1) { | 427 | while (1) { |
392 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, | 428 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, |
393 | EXTENT_DIRTY); | 429 | EXTENT_DIRTY); |
@@ -418,6 +454,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | |||
418 | return werr; | 454 | return werr; |
419 | } | 455 | } |
420 | 456 | ||
457 | /* | ||
458 | * when btree blocks are allocated, they have some corresponding bits set for | ||
459 | * them in one of two extent_io trees. This is used to make sure all of | ||
460 | * those extents are on disk for transaction or log commit | ||
461 | */ | ||
462 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | ||
463 | struct extent_io_tree *dirty_pages) | ||
464 | { | ||
465 | int ret; | ||
466 | int ret2; | ||
467 | |||
468 | ret = btrfs_write_marked_extents(root, dirty_pages); | ||
469 | ret2 = btrfs_wait_marked_extents(root, dirty_pages); | ||
470 | return ret || ret2; | ||
471 | } | ||
472 | |||
421 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 473 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
422 | struct btrfs_root *root) | 474 | struct btrfs_root *root) |
423 | { | 475 | { |
@@ -743,6 +795,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
743 | memcpy(&pending->root_key, &key, sizeof(key)); | 795 | memcpy(&pending->root_key, &key, sizeof(key)); |
744 | fail: | 796 | fail: |
745 | kfree(new_root_item); | 797 | kfree(new_root_item); |
798 | btrfs_unreserve_metadata_space(root, 6); | ||
746 | return ret; | 799 | return ret; |
747 | } | 800 | } |
748 | 801 | ||
@@ -1059,6 +1112,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1059 | 1112 | ||
1060 | mutex_unlock(&root->fs_info->trans_mutex); | 1113 | mutex_unlock(&root->fs_info->trans_mutex); |
1061 | 1114 | ||
1115 | if (current->journal_info == trans) | ||
1116 | current->journal_info = NULL; | ||
1117 | |||
1062 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 1118 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
1063 | return ret; | 1119 | return ret; |
1064 | } | 1120 | } |