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 | } |
