aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2010-05-16 10:49:58 -0400
committerChris Mason <chris.mason@oracle.com>2010-05-25 10:34:52 -0400
commit8929ecfa50f266163832eeacfbc3642ed5eb83b6 (patch)
treee0177748af36d49d5f652cff0e421a8268cf7194 /fs
parent0ca1f7ceb1991099ed5273885ebcf4323948c72e (diff)
Btrfs: Introduce global metadata reservation
Reserve metadata space for extent tree, checksum tree and root tree Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h8
-rw-r--r--fs/btrfs/disk-io.c59
-rw-r--r--fs/btrfs/extent-tree.c147
-rw-r--r--fs/btrfs/inode.c13
-rw-r--r--fs/btrfs/ioctl.c10
-rw-r--r--fs/btrfs/transaction.c70
-rw-r--r--fs/btrfs/transaction.h3
-rw-r--r--fs/btrfs/tree-defrag.c7
8 files changed, 241 insertions, 76 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d4744192eada..504d5daf2f1c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -683,21 +683,15 @@ struct btrfs_space_info {
683 u64 bytes_reserved; /* total bytes the allocator has reserved for 683 u64 bytes_reserved; /* total bytes the allocator has reserved for
684 current allocations */ 684 current allocations */
685 u64 bytes_readonly; /* total bytes that are read only */ 685 u64 bytes_readonly; /* total bytes that are read only */
686 u64 bytes_super; /* total bytes reserved for the super blocks */ 686
687 u64 bytes_root; /* the number of bytes needed to commit a
688 transaction */
689 u64 bytes_may_use; /* number of bytes that may be used for 687 u64 bytes_may_use; /* number of bytes that may be used for
690 delalloc/allocations */ 688 delalloc/allocations */
691 u64 bytes_delalloc; /* number of bytes currently reserved for
692 delayed allocation */
693 u64 disk_used; /* total bytes used on disk */ 689 u64 disk_used; /* total bytes used on disk */
694 690
695 int full; /* indicates that we cannot allocate any more 691 int full; /* indicates that we cannot allocate any more
696 chunks for this space */ 692 chunks for this space */
697 int force_alloc; /* set if we need to force a chunk alloc for 693 int force_alloc; /* set if we need to force a chunk alloc for
698 this space */ 694 this space */
699 int force_delalloc; /* make people start doing filemap_flush until
700 we're under a threshold */
701 695
702 struct list_head list; 696 struct list_head list;
703 697
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 054b4475c757..309d8c08a640 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1463,10 +1463,6 @@ static int cleaner_kthread(void *arg)
1463 struct btrfs_root *root = arg; 1463 struct btrfs_root *root = arg;
1464 1464
1465 do { 1465 do {
1466 smp_mb();
1467 if (root->fs_info->closing)
1468 break;
1469
1470 vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); 1466 vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
1471 1467
1472 if (!(root->fs_info->sb->s_flags & MS_RDONLY) && 1468 if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
@@ -1479,11 +1475,9 @@ static int cleaner_kthread(void *arg)
1479 if (freezing(current)) { 1475 if (freezing(current)) {
1480 refrigerator(); 1476 refrigerator();
1481 } else { 1477 } else {
1482 smp_mb();
1483 if (root->fs_info->closing)
1484 break;
1485 set_current_state(TASK_INTERRUPTIBLE); 1478 set_current_state(TASK_INTERRUPTIBLE);
1486 schedule(); 1479 if (!kthread_should_stop())
1480 schedule();
1487 __set_current_state(TASK_RUNNING); 1481 __set_current_state(TASK_RUNNING);
1488 } 1482 }
1489 } while (!kthread_should_stop()); 1483 } while (!kthread_should_stop());
@@ -1495,36 +1489,40 @@ static int transaction_kthread(void *arg)
1495 struct btrfs_root *root = arg; 1489 struct btrfs_root *root = arg;
1496 struct btrfs_trans_handle *trans; 1490 struct btrfs_trans_handle *trans;
1497 struct btrfs_transaction *cur; 1491 struct btrfs_transaction *cur;
1492 u64 transid;
1498 unsigned long now; 1493 unsigned long now;
1499 unsigned long delay; 1494 unsigned long delay;
1500 int ret; 1495 int ret;
1501 1496
1502 do { 1497 do {
1503 smp_mb();
1504 if (root->fs_info->closing)
1505 break;
1506
1507 delay = HZ * 30; 1498 delay = HZ * 30;
1508 vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); 1499 vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
1509 mutex_lock(&root->fs_info->transaction_kthread_mutex); 1500 mutex_lock(&root->fs_info->transaction_kthread_mutex);
1510 1501
1511 mutex_lock(&root->fs_info->trans_mutex); 1502 spin_lock(&root->fs_info->new_trans_lock);
1512 cur = root->fs_info->running_transaction; 1503 cur = root->fs_info->running_transaction;
1513 if (!cur) { 1504 if (!cur) {
1514 mutex_unlock(&root->fs_info->trans_mutex); 1505 spin_unlock(&root->fs_info->new_trans_lock);
1515 goto sleep; 1506 goto sleep;
1516 } 1507 }
1517 1508
1518 now = get_seconds(); 1509 now = get_seconds();
1519 if (now < cur->start_time || now - cur->start_time < 30) { 1510 if (!cur->blocked &&
1520 mutex_unlock(&root->fs_info->trans_mutex); 1511 (now < cur->start_time || now - cur->start_time < 30)) {
1512 spin_unlock(&root->fs_info->new_trans_lock);
1521 delay = HZ * 5; 1513 delay = HZ * 5;
1522 goto sleep; 1514 goto sleep;
1523 } 1515 }
1524 mutex_unlock(&root->fs_info->trans_mutex); 1516 transid = cur->transid;
1525 trans = btrfs_join_transaction(root, 1); 1517 spin_unlock(&root->fs_info->new_trans_lock);
1526 ret = btrfs_commit_transaction(trans, root);
1527 1518
1519 trans = btrfs_join_transaction(root, 1);
1520 if (transid == trans->transid) {
1521 ret = btrfs_commit_transaction(trans, root);
1522 BUG_ON(ret);
1523 } else {
1524 btrfs_end_transaction(trans, root);
1525 }
1528sleep: 1526sleep:
1529 wake_up_process(root->fs_info->cleaner_kthread); 1527 wake_up_process(root->fs_info->cleaner_kthread);
1530 mutex_unlock(&root->fs_info->transaction_kthread_mutex); 1528 mutex_unlock(&root->fs_info->transaction_kthread_mutex);
@@ -1532,10 +1530,10 @@ sleep:
1532 if (freezing(current)) { 1530 if (freezing(current)) {
1533 refrigerator(); 1531 refrigerator();
1534 } else { 1532 } else {
1535 if (root->fs_info->closing)
1536 break;
1537 set_current_state(TASK_INTERRUPTIBLE); 1533 set_current_state(TASK_INTERRUPTIBLE);
1538 schedule_timeout(delay); 1534 if (!kthread_should_stop() &&
1535 !btrfs_transaction_blocked(root->fs_info))
1536 schedule_timeout(delay);
1539 __set_current_state(TASK_RUNNING); 1537 __set_current_state(TASK_RUNNING);
1540 } 1538 }
1541 } while (!kthread_should_stop()); 1539 } while (!kthread_should_stop());
@@ -1917,17 +1915,18 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1917 1915
1918 csum_root->track_dirty = 1; 1916 csum_root->track_dirty = 1;
1919 1917
1918 fs_info->generation = generation;
1919 fs_info->last_trans_committed = generation;
1920 fs_info->data_alloc_profile = (u64)-1;
1921 fs_info->metadata_alloc_profile = (u64)-1;
1922 fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
1923
1920 ret = btrfs_read_block_groups(extent_root); 1924 ret = btrfs_read_block_groups(extent_root);
1921 if (ret) { 1925 if (ret) {
1922 printk(KERN_ERR "Failed to read block groups: %d\n", ret); 1926 printk(KERN_ERR "Failed to read block groups: %d\n", ret);
1923 goto fail_block_groups; 1927 goto fail_block_groups;
1924 } 1928 }
1925 1929
1926 fs_info->generation = generation;
1927 fs_info->last_trans_committed = generation;
1928 fs_info->data_alloc_profile = (u64)-1;
1929 fs_info->metadata_alloc_profile = (u64)-1;
1930 fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
1931 fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, 1930 fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
1932 "btrfs-cleaner"); 1931 "btrfs-cleaner");
1933 if (IS_ERR(fs_info->cleaner_kthread)) 1932 if (IS_ERR(fs_info->cleaner_kthread))
@@ -2430,15 +2429,15 @@ int close_ctree(struct btrfs_root *root)
2430 fs_info->closing = 1; 2429 fs_info->closing = 1;
2431 smp_mb(); 2430 smp_mb();
2432 2431
2433 kthread_stop(root->fs_info->transaction_kthread);
2434 kthread_stop(root->fs_info->cleaner_kthread);
2435
2436 if (!(fs_info->sb->s_flags & MS_RDONLY)) { 2432 if (!(fs_info->sb->s_flags & MS_RDONLY)) {
2437 ret = btrfs_commit_super(root); 2433 ret = btrfs_commit_super(root);
2438 if (ret) 2434 if (ret)
2439 printk(KERN_ERR "btrfs: commit super ret %d\n", ret); 2435 printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
2440 } 2436 }
2441 2437
2438 kthread_stop(root->fs_info->transaction_kthread);
2439 kthread_stop(root->fs_info->cleaner_kthread);
2440
2442 fs_info->closing = 2; 2441 fs_info->closing = 2;
2443 smp_mb(); 2442 smp_mb();
2444 2443
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b1822e752b4a..cb814a71800d 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2895,10 +2895,9 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
2895again: 2895again:
2896 /* make sure we have enough space to handle the data first */ 2896 /* make sure we have enough space to handle the data first */
2897 spin_lock(&data_sinfo->lock); 2897 spin_lock(&data_sinfo->lock);
2898 used = data_sinfo->bytes_used + data_sinfo->bytes_delalloc + 2898 used = data_sinfo->bytes_used + data_sinfo->bytes_reserved +
2899 data_sinfo->bytes_reserved + data_sinfo->bytes_pinned + 2899 data_sinfo->bytes_pinned + data_sinfo->bytes_readonly +
2900 data_sinfo->bytes_readonly + data_sinfo->bytes_may_use + 2900 data_sinfo->bytes_may_use;
2901 data_sinfo->bytes_super;
2902 2901
2903 if (used + bytes > data_sinfo->total_bytes) { 2902 if (used + bytes > data_sinfo->total_bytes) {
2904 struct btrfs_trans_handle *trans; 2903 struct btrfs_trans_handle *trans;
@@ -2922,7 +2921,7 @@ alloc:
2922 bytes + 2 * 1024 * 1024, 2921 bytes + 2 * 1024 * 1024,
2923 alloc_target, 0); 2922 alloc_target, 0);
2924 btrfs_end_transaction(trans, root); 2923 btrfs_end_transaction(trans, root);
2925 if (ret) 2924 if (ret < 0)
2926 return ret; 2925 return ret;
2927 2926
2928 if (!data_sinfo) { 2927 if (!data_sinfo) {
@@ -2945,11 +2944,10 @@ alloc:
2945 goto again; 2944 goto again;
2946 } 2945 }
2947 2946
2948 printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes" 2947 printk(KERN_ERR "no space left, need %llu, %llu bytes_used, "
2949 ", %llu bytes_used, %llu bytes_reserved, " 2948 "%llu bytes_reserved, " "%llu bytes_pinned, "
2950 "%llu bytes_pinned, %llu bytes_readonly, %llu may use " 2949 "%llu bytes_readonly, %llu may use %llu total\n",
2951 "%llu total\n", (unsigned long long)bytes, 2950 (unsigned long long)bytes,
2952 (unsigned long long)data_sinfo->bytes_delalloc,
2953 (unsigned long long)data_sinfo->bytes_used, 2951 (unsigned long long)data_sinfo->bytes_used,
2954 (unsigned long long)data_sinfo->bytes_reserved, 2952 (unsigned long long)data_sinfo->bytes_reserved,
2955 (unsigned long long)data_sinfo->bytes_pinned, 2953 (unsigned long long)data_sinfo->bytes_pinned,
@@ -3464,6 +3462,91 @@ void btrfs_block_rsv_release(struct btrfs_root *root,
3464 block_rsv_release_bytes(block_rsv, global_rsv, num_bytes); 3462 block_rsv_release_bytes(block_rsv, global_rsv, num_bytes);
3465} 3463}
3466 3464
3465/*
3466 * helper to calculate size of global block reservation.
3467 * the desired value is sum of space used by extent tree,
3468 * checksum tree and root tree
3469 */
3470static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
3471{
3472 struct btrfs_space_info *sinfo;
3473 u64 num_bytes;
3474 u64 meta_used;
3475 u64 data_used;
3476 int csum_size = btrfs_super_csum_size(&fs_info->super_copy);
3477#if 0
3478 /*
3479 * per tree used space accounting can be inaccuracy, so we
3480 * can't rely on it.
3481 */
3482 spin_lock(&fs_info->extent_root->accounting_lock);
3483 num_bytes = btrfs_root_used(&fs_info->extent_root->root_item);
3484 spin_unlock(&fs_info->extent_root->accounting_lock);
3485
3486 spin_lock(&fs_info->csum_root->accounting_lock);
3487 num_bytes += btrfs_root_used(&fs_info->csum_root->root_item);
3488 spin_unlock(&fs_info->csum_root->accounting_lock);
3489
3490 spin_lock(&fs_info->tree_root->accounting_lock);
3491 num_bytes += btrfs_root_used(&fs_info->tree_root->root_item);
3492 spin_unlock(&fs_info->tree_root->accounting_lock);
3493#endif
3494 sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
3495 spin_lock(&sinfo->lock);
3496 data_used = sinfo->bytes_used;
3497 spin_unlock(&sinfo->lock);
3498
3499 sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
3500 spin_lock(&sinfo->lock);
3501 meta_used = sinfo->bytes_used;
3502 spin_unlock(&sinfo->lock);
3503
3504 num_bytes = (data_used >> fs_info->sb->s_blocksize_bits) *
3505 csum_size * 2;
3506 num_bytes += div64_u64(data_used + meta_used, 50);
3507
3508 if (num_bytes * 3 > meta_used)
3509 num_bytes = div64_u64(meta_used, 3);
3510
3511 return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
3512}
3513
3514static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
3515{
3516 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
3517 struct btrfs_space_info *sinfo = block_rsv->space_info;
3518 u64 num_bytes;
3519
3520 num_bytes = calc_global_metadata_size(fs_info);
3521
3522 spin_lock(&block_rsv->lock);
3523 spin_lock(&sinfo->lock);
3524
3525 block_rsv->size = num_bytes;
3526
3527 num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
3528 sinfo->bytes_reserved + sinfo->bytes_readonly;
3529
3530 if (sinfo->total_bytes > num_bytes) {
3531 num_bytes = sinfo->total_bytes - num_bytes;
3532 block_rsv->reserved += num_bytes;
3533 sinfo->bytes_reserved += num_bytes;
3534 }
3535
3536 if (block_rsv->reserved >= block_rsv->size) {
3537 num_bytes = block_rsv->reserved - block_rsv->size;
3538 sinfo->bytes_reserved -= num_bytes;
3539 block_rsv->reserved = block_rsv->size;
3540 block_rsv->full = 1;
3541 }
3542#if 0
3543 printk(KERN_INFO"global block rsv size %llu reserved %llu\n",
3544 block_rsv->size, block_rsv->reserved);
3545#endif
3546 spin_unlock(&sinfo->lock);
3547 spin_unlock(&block_rsv->lock);
3548}
3549
3467static void init_global_block_rsv(struct btrfs_fs_info *fs_info) 3550static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
3468{ 3551{
3469 struct btrfs_space_info *space_info; 3552 struct btrfs_space_info *space_info;
@@ -3473,11 +3556,36 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
3473 fs_info->chunk_block_rsv.priority = 10; 3556 fs_info->chunk_block_rsv.priority = 10;
3474 3557
3475 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); 3558 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
3559 fs_info->global_block_rsv.space_info = space_info;
3560 fs_info->global_block_rsv.priority = 10;
3561 fs_info->global_block_rsv.refill_used = 1;
3562 fs_info->delalloc_block_rsv.space_info = space_info;
3476 fs_info->trans_block_rsv.space_info = space_info; 3563 fs_info->trans_block_rsv.space_info = space_info;
3477 fs_info->empty_block_rsv.space_info = space_info; 3564 fs_info->empty_block_rsv.space_info = space_info;
3478 fs_info->empty_block_rsv.priority = 10; 3565 fs_info->empty_block_rsv.priority = 10;
3479 3566
3567 fs_info->extent_root->block_rsv = &fs_info->global_block_rsv;
3568 fs_info->csum_root->block_rsv = &fs_info->global_block_rsv;
3569 fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
3570 fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
3480 fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv; 3571 fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;
3572
3573 btrfs_add_durable_block_rsv(fs_info, &fs_info->global_block_rsv);
3574
3575 btrfs_add_durable_block_rsv(fs_info, &fs_info->delalloc_block_rsv);
3576
3577 update_global_block_rsv(fs_info);
3578}
3579
3580static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
3581{
3582 block_rsv_release_bytes(&fs_info->global_block_rsv, NULL, (u64)-1);
3583 WARN_ON(fs_info->delalloc_block_rsv.size > 0);
3584 WARN_ON(fs_info->delalloc_block_rsv.reserved > 0);
3585 WARN_ON(fs_info->trans_block_rsv.size > 0);
3586 WARN_ON(fs_info->trans_block_rsv.reserved > 0);
3587 WARN_ON(fs_info->chunk_block_rsv.size > 0);
3588 WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
3481} 3589}
3482 3590
3483static u64 calc_trans_metadata_size(struct btrfs_root *root, int num_items) 3591static u64 calc_trans_metadata_size(struct btrfs_root *root, int num_items)
@@ -3826,6 +3934,8 @@ int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
3826 fs_info->pinned_extents = &fs_info->freed_extents[0]; 3934 fs_info->pinned_extents = &fs_info->freed_extents[0];
3827 3935
3828 up_write(&fs_info->extent_commit_sem); 3936 up_write(&fs_info->extent_commit_sem);
3937
3938 update_global_block_rsv(fs_info);
3829 return 0; 3939 return 0;
3830} 3940}
3831 3941
@@ -4818,19 +4928,16 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
4818 printk(KERN_INFO "space_info has %llu free, is %sfull\n", 4928 printk(KERN_INFO "space_info has %llu free, is %sfull\n",
4819 (unsigned long long)(info->total_bytes - info->bytes_used - 4929 (unsigned long long)(info->total_bytes - info->bytes_used -
4820 info->bytes_pinned - info->bytes_reserved - 4930 info->bytes_pinned - info->bytes_reserved -
4821 info->bytes_super), 4931 info->bytes_readonly),
4822 (info->full) ? "" : "not "); 4932 (info->full) ? "" : "not ");
4823 printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu," 4933 printk(KERN_INFO "space_info total=%llu, used=%llu, pinned=%llu, "
4824 " may_use=%llu, used=%llu, root=%llu, super=%llu, reserved=%llu" 4934 "reserved=%llu, may_use=%llu, readonly=%llu\n",
4825 "\n",
4826 (unsigned long long)info->total_bytes, 4935 (unsigned long long)info->total_bytes,
4936 (unsigned long long)info->bytes_used,
4827 (unsigned long long)info->bytes_pinned, 4937 (unsigned long long)info->bytes_pinned,
4828 (unsigned long long)info->bytes_delalloc, 4938 (unsigned long long)info->bytes_reserved,
4829 (unsigned long long)info->bytes_may_use, 4939 (unsigned long long)info->bytes_may_use,
4830 (unsigned long long)info->bytes_used, 4940 (unsigned long long)info->bytes_readonly);
4831 (unsigned long long)info->bytes_root,
4832 (unsigned long long)info->bytes_super,
4833 (unsigned long long)info->bytes_reserved);
4834 spin_unlock(&info->lock); 4941 spin_unlock(&info->lock);
4835 4942
4836 if (!dump_block_groups) 4943 if (!dump_block_groups)
@@ -7727,6 +7834,8 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
7727 */ 7834 */
7728 synchronize_rcu(); 7835 synchronize_rcu();
7729 7836
7837 release_global_block_rsv(info);
7838
7730 while(!list_empty(&info->space_info)) { 7839 while(!list_empty(&info->space_info)) {
7731 space_info = list_entry(info->space_info.next, 7840 space_info = list_entry(info->space_info.next,
7732 struct btrfs_space_info, 7841 struct btrfs_space_info,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6e54665d37f7..f9c40b839452 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4060,7 +4060,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
4060 struct btrfs_trans_handle *trans; 4060 struct btrfs_trans_handle *trans;
4061 int ret = 0; 4061 int ret = 0;
4062 4062
4063 if (root->fs_info->btree_inode == inode) 4063 if (BTRFS_I(inode)->dummy_inode)
4064 return 0; 4064 return 0;
4065 4065
4066 if (wbc->sync_mode == WB_SYNC_ALL) { 4066 if (wbc->sync_mode == WB_SYNC_ALL) {
@@ -4081,10 +4081,19 @@ void btrfs_dirty_inode(struct inode *inode)
4081{ 4081{
4082 struct btrfs_root *root = BTRFS_I(inode)->root; 4082 struct btrfs_root *root = BTRFS_I(inode)->root;
4083 struct btrfs_trans_handle *trans; 4083 struct btrfs_trans_handle *trans;
4084 int ret;
4085
4086 if (BTRFS_I(inode)->dummy_inode)
4087 return;
4084 4088
4085 trans = btrfs_join_transaction(root, 1); 4089 trans = btrfs_join_transaction(root, 1);
4086 btrfs_set_trans_block_group(trans, inode); 4090 btrfs_set_trans_block_group(trans, inode);
4087 btrfs_update_inode(trans, root, inode); 4091
4092 ret = btrfs_update_inode(trans, root, inode);
4093 if (ret)
4094 printk(KERN_ERR"btrfs: fail to dirty inode %lu error %d\n",
4095 inode->i_ino, ret);
4096
4088 btrfs_end_transaction(trans, root); 4097 btrfs_end_transaction(trans, root);
4089} 4098}
4090 4099
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 6a706e691377..a0686658a3f6 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1341,8 +1341,10 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
1341 ret = -EPERM; 1341 ret = -EPERM;
1342 goto out; 1342 goto out;
1343 } 1343 }
1344 btrfs_defrag_root(root, 0); 1344 ret = btrfs_defrag_root(root, 0);
1345 btrfs_defrag_root(root->fs_info->extent_root, 0); 1345 if (ret)
1346 goto out;
1347 ret = btrfs_defrag_root(root->fs_info->extent_root, 0);
1346 break; 1348 break;
1347 case S_IFREG: 1349 case S_IFREG:
1348 if (!(file->f_mode & FMODE_WRITE)) { 1350 if (!(file->f_mode & FMODE_WRITE)) {
@@ -1372,9 +1374,11 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
1372 /* the rest are all set to zero by kzalloc */ 1374 /* the rest are all set to zero by kzalloc */
1373 range->len = (u64)-1; 1375 range->len = (u64)-1;
1374 } 1376 }
1375 btrfs_defrag_file(file, range); 1377 ret = btrfs_defrag_file(file, range);
1376 kfree(range); 1378 kfree(range);
1377 break; 1379 break;
1380 default:
1381 ret = -EINVAL;
1378 } 1382 }
1379out: 1383out:
1380 mnt_drop_write(file->f_path.mnt); 1384 mnt_drop_write(file->f_path.mnt);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 2616491a5c5b..6217bb6d516a 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -321,10 +321,36 @@ void btrfs_throttle(struct btrfs_root *root)
321 mutex_unlock(&root->fs_info->trans_mutex); 321 mutex_unlock(&root->fs_info->trans_mutex);
322} 322}
323 323
324static int should_end_transaction(struct btrfs_trans_handle *trans,
325 struct btrfs_root *root)
326{
327 int ret;
328 ret = btrfs_block_rsv_check(trans, root,
329 &root->fs_info->global_block_rsv, 0, 5);
330 return ret ? 1 : 0;
331}
332
333int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
334 struct btrfs_root *root)
335{
336 struct btrfs_transaction *cur_trans = trans->transaction;
337 int updates;
338
339 if (cur_trans->blocked || cur_trans->delayed_refs.flushing)
340 return 1;
341
342 updates = trans->delayed_ref_updates;
343 trans->delayed_ref_updates = 0;
344 if (updates)
345 btrfs_run_delayed_refs(trans, root, updates);
346
347 return should_end_transaction(trans, root);
348}
349
324static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, 350static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
325 struct btrfs_root *root, int throttle) 351 struct btrfs_root *root, int throttle)
326{ 352{
327 struct btrfs_transaction *cur_trans; 353 struct btrfs_transaction *cur_trans = trans->transaction;
328 struct btrfs_fs_info *info = root->fs_info; 354 struct btrfs_fs_info *info = root->fs_info;
329 int count = 0; 355 int count = 0;
330 356
@@ -350,9 +376,19 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
350 376
351 btrfs_trans_release_metadata(trans, root); 377 btrfs_trans_release_metadata(trans, root);
352 378
379 if (!root->fs_info->open_ioctl_trans &&
380 should_end_transaction(trans, root))
381 trans->transaction->blocked = 1;
382
383 if (cur_trans->blocked && !cur_trans->in_commit) {
384 if (throttle)
385 return btrfs_commit_transaction(trans, root);
386 else
387 wake_up_process(info->transaction_kthread);
388 }
389
353 mutex_lock(&info->trans_mutex); 390 mutex_lock(&info->trans_mutex);
354 cur_trans = info->running_transaction; 391 WARN_ON(cur_trans != info->running_transaction);
355 WARN_ON(cur_trans != trans->transaction);
356 WARN_ON(cur_trans->num_writers < 1); 392 WARN_ON(cur_trans->num_writers < 1);
357 cur_trans->num_writers--; 393 cur_trans->num_writers--;
358 394
@@ -664,30 +700,30 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
664int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) 700int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
665{ 701{
666 struct btrfs_fs_info *info = root->fs_info; 702 struct btrfs_fs_info *info = root->fs_info;
667 int ret;
668 struct btrfs_trans_handle *trans; 703 struct btrfs_trans_handle *trans;
704 int ret;
669 unsigned long nr; 705 unsigned long nr;
670 706
671 smp_mb(); 707 if (xchg(&root->defrag_running, 1))
672 if (root->defrag_running)
673 return 0; 708 return 0;
674 trans = btrfs_start_transaction(root, 1); 709
675 while (1) { 710 while (1) {
676 root->defrag_running = 1; 711 trans = btrfs_start_transaction(root, 0);
712 if (IS_ERR(trans))
713 return PTR_ERR(trans);
714
677 ret = btrfs_defrag_leaves(trans, root, cacheonly); 715 ret = btrfs_defrag_leaves(trans, root, cacheonly);
716
678 nr = trans->blocks_used; 717 nr = trans->blocks_used;
679 btrfs_end_transaction(trans, root); 718 btrfs_end_transaction(trans, root);
680 btrfs_btree_balance_dirty(info->tree_root, nr); 719 btrfs_btree_balance_dirty(info->tree_root, nr);
681 cond_resched(); 720 cond_resched();
682 721
683 trans = btrfs_start_transaction(root, 1);
684 if (root->fs_info->closing || ret != -EAGAIN) 722 if (root->fs_info->closing || ret != -EAGAIN)
685 break; 723 break;
686 } 724 }
687 root->defrag_running = 0; 725 root->defrag_running = 0;
688 smp_mb(); 726 return ret;
689 btrfs_end_transaction(trans, root);
690 return 0;
691} 727}
692 728
693#if 0 729#if 0
@@ -924,6 +960,16 @@ int btrfs_transaction_in_commit(struct btrfs_fs_info *info)
924 return ret; 960 return ret;
925} 961}
926 962
963int btrfs_transaction_blocked(struct btrfs_fs_info *info)
964{
965 int ret = 0;
966 spin_lock(&info->new_trans_lock);
967 if (info->running_transaction)
968 ret = info->running_transaction->blocked;
969 spin_unlock(&info->new_trans_lock);
970 return ret;
971}
972
927int btrfs_commit_transaction(struct btrfs_trans_handle *trans, 973int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
928 struct btrfs_root *root) 974 struct btrfs_root *root)
929{ 975{
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 14b3841b75d5..e104986d0bfd 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -106,6 +106,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
106 struct btrfs_root *root); 106 struct btrfs_root *root);
107int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, 107int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
108 struct btrfs_root *root); 108 struct btrfs_root *root);
109int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
110 struct btrfs_root *root);
109void btrfs_throttle(struct btrfs_root *root); 111void btrfs_throttle(struct btrfs_root *root);
110int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, 112int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
111 struct btrfs_root *root); 113 struct btrfs_root *root);
@@ -115,5 +117,6 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
115 struct extent_io_tree *dirty_pages, int mark); 117 struct extent_io_tree *dirty_pages, int mark);
116int btrfs_wait_marked_extents(struct btrfs_root *root, 118int btrfs_wait_marked_extents(struct btrfs_root *root,
117 struct extent_io_tree *dirty_pages, int mark); 119 struct extent_io_tree *dirty_pages, int mark);
120int btrfs_transaction_blocked(struct btrfs_fs_info *info);
118int btrfs_transaction_in_commit(struct btrfs_fs_info *info); 121int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
119#endif 122#endif
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index b10eacdb1620..f7ac8e013ed7 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -117,13 +117,14 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
117 path->nodes[1], 0, 117 path->nodes[1], 0,
118 cache_only, &last_ret, 118 cache_only, &last_ret,
119 &root->defrag_progress); 119 &root->defrag_progress);
120 WARN_ON(ret && ret != -EAGAIN); 120 if (ret) {
121 WARN_ON(ret == -EAGAIN);
122 goto out;
123 }
121 if (next_key_ret == 0) { 124 if (next_key_ret == 0) {
122 memcpy(&root->defrag_progress, &key, sizeof(key)); 125 memcpy(&root->defrag_progress, &key, sizeof(key));
123 ret = -EAGAIN; 126 ret = -EAGAIN;
124 } 127 }
125
126 btrfs_release_path(root, path);
127out: 128out:
128 if (path) 129 if (path)
129 btrfs_free_path(path); 130 btrfs_free_path(path);