diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 8 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 59 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 147 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 13 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 70 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/tree-defrag.c | 7 |
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 | } | ||
| 1528 | sleep: | 1526 | sleep: |
| 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) | |||
| 2895 | again: | 2895 | again: |
| 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 | */ | ||
| 3470 | static 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 | |||
| 3514 | static 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 | |||
| 3467 | static void init_global_block_rsv(struct btrfs_fs_info *fs_info) | 3550 | static 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 | |||
| 3580 | static 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 | ||
| 3483 | static u64 calc_trans_metadata_size(struct btrfs_root *root, int num_items) | 3591 | static 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 | } |
| 1379 | out: | 1383 | out: |
| 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 | ||
| 324 | static 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 | |||
| 333 | int 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 | |||
| 324 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | 350 | static 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, | |||
| 664 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | 700 | int 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 | ||
| 963 | int 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 | |||
| 927 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 973 | int 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); |
| 107 | int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, | 107 | int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, |
| 108 | struct btrfs_root *root); | 108 | struct btrfs_root *root); |
| 109 | int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | ||
| 110 | struct btrfs_root *root); | ||
| 109 | void btrfs_throttle(struct btrfs_root *root); | 111 | void btrfs_throttle(struct btrfs_root *root); |
| 110 | int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | 112 | int 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); |
| 116 | int btrfs_wait_marked_extents(struct btrfs_root *root, | 118 | int 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); |
| 120 | int btrfs_transaction_blocked(struct btrfs_fs_info *info); | ||
| 118 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info); | 121 | int 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); | ||
| 127 | out: | 128 | out: |
| 128 | if (path) | 129 | if (path) |
| 129 | btrfs_free_path(path); | 130 | btrfs_free_path(path); |
