diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-05 15:29:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-05 15:29:25 -0400 |
commit | 884b8267d5f13bdcdc7e675ecbd0dbb0257689bb (patch) | |
tree | 637c734a7466e43d3786968891e746c5b70d6a4b /fs/btrfs | |
parent | d14f5b810b49c7dbd1a01be1c6d3641d46090080 (diff) | |
parent | c9ddec74aa950a220cc4caa5215cfc5d886050b7 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
Btrfs: don't warn in btrfs_add_orphan
Btrfs: fix free space cache when there are pinned extents and clusters V2
Btrfs: Fix uninitialized root flags for subvolumes
btrfs: clear __GFP_FS flag in the space cache inode
Btrfs: fix memory leak in start_transaction()
Btrfs: fix memory leak in btrfs_ioctl_start_sync()
Btrfs: fix subvol_sem leak in btrfs_rename()
Btrfs: Fix oops for defrag with compression turned on
Btrfs: fix /proc/mounts info.
Btrfs: fix compiler warning in file.c
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/file.c | 2 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 84 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 29 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 8 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 18 | ||||
-rw-r--r-- | fs/btrfs/super.c | 19 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 |
9 files changed, 145 insertions, 25 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d47ce8307854..3458b5725540 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1284,6 +1284,8 @@ struct btrfs_root { | |||
1284 | #define BTRFS_INODE_DIRSYNC (1 << 10) | 1284 | #define BTRFS_INODE_DIRSYNC (1 << 10) |
1285 | #define BTRFS_INODE_COMPRESS (1 << 11) | 1285 | #define BTRFS_INODE_COMPRESS (1 << 11) |
1286 | 1286 | ||
1287 | #define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31) | ||
1288 | |||
1287 | /* some macros to generate set/get funcs for the struct fields. This | 1289 | /* some macros to generate set/get funcs for the struct fields. This |
1288 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple | 1290 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple |
1289 | * one for u8: | 1291 | * one for u8: |
@@ -2359,6 +2361,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); | |||
2359 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root); | 2361 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root); |
2360 | int btrfs_set_root_node(struct btrfs_root_item *item, | 2362 | int btrfs_set_root_node(struct btrfs_root_item *item, |
2361 | struct extent_buffer *node); | 2363 | struct extent_buffer *node); |
2364 | void btrfs_check_and_init_root_item(struct btrfs_root_item *item); | ||
2365 | |||
2362 | /* dir-item.c */ | 2366 | /* dir-item.c */ |
2363 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, | 2367 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, |
2364 | struct btrfs_root *root, const char *name, | 2368 | struct btrfs_root *root, const char *name, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index d7a7315bd031..8f1d44ba332f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1275,8 +1275,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, | |||
1275 | root->commit_root = btrfs_root_node(root); | 1275 | root->commit_root = btrfs_root_node(root); |
1276 | BUG_ON(!root->node); | 1276 | BUG_ON(!root->node); |
1277 | out: | 1277 | out: |
1278 | if (location->objectid != BTRFS_TREE_LOG_OBJECTID) | 1278 | if (location->objectid != BTRFS_TREE_LOG_OBJECTID) { |
1279 | root->ref_cows = 1; | 1279 | root->ref_cows = 1; |
1280 | btrfs_check_and_init_root_item(&root->root_item); | ||
1281 | } | ||
1280 | 1282 | ||
1281 | return root; | 1283 | return root; |
1282 | } | 1284 | } |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 656bc0a892b1..e621ea54a3fd 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -906,7 +906,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
906 | unsigned long last_index; | 906 | unsigned long last_index; |
907 | size_t num_written = 0; | 907 | size_t num_written = 0; |
908 | int nrptrs; | 908 | int nrptrs; |
909 | int ret; | 909 | int ret = 0; |
910 | 910 | ||
911 | nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / | 911 | nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / |
912 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / | 912 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 0037427d8a9d..f561c953205b 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "free-space-cache.h" | 24 | #include "free-space-cache.h" |
25 | #include "transaction.h" | 25 | #include "transaction.h" |
26 | #include "disk-io.h" | 26 | #include "disk-io.h" |
27 | #include "extent_io.h" | ||
27 | 28 | ||
28 | #define BITS_PER_BITMAP (PAGE_CACHE_SIZE * 8) | 29 | #define BITS_PER_BITMAP (PAGE_CACHE_SIZE * 8) |
29 | #define MAX_CACHE_BYTES_PER_GIG (32 * 1024) | 30 | #define MAX_CACHE_BYTES_PER_GIG (32 * 1024) |
@@ -81,6 +82,8 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root, | |||
81 | return ERR_PTR(-ENOENT); | 82 | return ERR_PTR(-ENOENT); |
82 | } | 83 | } |
83 | 84 | ||
85 | inode->i_mapping->flags &= ~__GFP_FS; | ||
86 | |||
84 | spin_lock(&block_group->lock); | 87 | spin_lock(&block_group->lock); |
85 | if (!root->fs_info->closing) { | 88 | if (!root->fs_info->closing) { |
86 | block_group->inode = igrab(inode); | 89 | block_group->inode = igrab(inode); |
@@ -222,6 +225,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, | |||
222 | u64 num_entries; | 225 | u64 num_entries; |
223 | u64 num_bitmaps; | 226 | u64 num_bitmaps; |
224 | u64 generation; | 227 | u64 generation; |
228 | u64 used = btrfs_block_group_used(&block_group->item); | ||
225 | u32 cur_crc = ~(u32)0; | 229 | u32 cur_crc = ~(u32)0; |
226 | pgoff_t index = 0; | 230 | pgoff_t index = 0; |
227 | unsigned long first_page_offset; | 231 | unsigned long first_page_offset; |
@@ -467,6 +471,17 @@ next: | |||
467 | index++; | 471 | index++; |
468 | } | 472 | } |
469 | 473 | ||
474 | spin_lock(&block_group->tree_lock); | ||
475 | if (block_group->free_space != (block_group->key.offset - used - | ||
476 | block_group->bytes_super)) { | ||
477 | spin_unlock(&block_group->tree_lock); | ||
478 | printk(KERN_ERR "block group %llu has an wrong amount of free " | ||
479 | "space\n", block_group->key.objectid); | ||
480 | ret = 0; | ||
481 | goto free_cache; | ||
482 | } | ||
483 | spin_unlock(&block_group->tree_lock); | ||
484 | |||
470 | ret = 1; | 485 | ret = 1; |
471 | out: | 486 | out: |
472 | kfree(checksums); | 487 | kfree(checksums); |
@@ -495,8 +510,11 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
495 | struct list_head *pos, *n; | 510 | struct list_head *pos, *n; |
496 | struct page *page; | 511 | struct page *page; |
497 | struct extent_state *cached_state = NULL; | 512 | struct extent_state *cached_state = NULL; |
513 | struct btrfs_free_cluster *cluster = NULL; | ||
514 | struct extent_io_tree *unpin = NULL; | ||
498 | struct list_head bitmap_list; | 515 | struct list_head bitmap_list; |
499 | struct btrfs_key key; | 516 | struct btrfs_key key; |
517 | u64 start, end, len; | ||
500 | u64 bytes = 0; | 518 | u64 bytes = 0; |
501 | u32 *crc, *checksums; | 519 | u32 *crc, *checksums; |
502 | pgoff_t index = 0, last_index = 0; | 520 | pgoff_t index = 0, last_index = 0; |
@@ -505,6 +523,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
505 | int entries = 0; | 523 | int entries = 0; |
506 | int bitmaps = 0; | 524 | int bitmaps = 0; |
507 | int ret = 0; | 525 | int ret = 0; |
526 | bool next_page = false; | ||
508 | 527 | ||
509 | root = root->fs_info->tree_root; | 528 | root = root->fs_info->tree_root; |
510 | 529 | ||
@@ -551,6 +570,18 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
551 | */ | 570 | */ |
552 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); | 571 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); |
553 | 572 | ||
573 | /* Get the cluster for this block_group if it exists */ | ||
574 | if (!list_empty(&block_group->cluster_list)) | ||
575 | cluster = list_entry(block_group->cluster_list.next, | ||
576 | struct btrfs_free_cluster, | ||
577 | block_group_list); | ||
578 | |||
579 | /* | ||
580 | * We shouldn't have switched the pinned extents yet so this is the | ||
581 | * right one | ||
582 | */ | ||
583 | unpin = root->fs_info->pinned_extents; | ||
584 | |||
554 | /* | 585 | /* |
555 | * Lock all pages first so we can lock the extent safely. | 586 | * Lock all pages first so we can lock the extent safely. |
556 | * | 587 | * |
@@ -580,6 +611,12 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
580 | lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, | 611 | lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, |
581 | 0, &cached_state, GFP_NOFS); | 612 | 0, &cached_state, GFP_NOFS); |
582 | 613 | ||
614 | /* | ||
615 | * When searching for pinned extents, we need to start at our start | ||
616 | * offset. | ||
617 | */ | ||
618 | start = block_group->key.objectid; | ||
619 | |||
583 | /* Write out the extent entries */ | 620 | /* Write out the extent entries */ |
584 | do { | 621 | do { |
585 | struct btrfs_free_space_entry *entry; | 622 | struct btrfs_free_space_entry *entry; |
@@ -587,6 +624,8 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
587 | unsigned long offset = 0; | 624 | unsigned long offset = 0; |
588 | unsigned long start_offset = 0; | 625 | unsigned long start_offset = 0; |
589 | 626 | ||
627 | next_page = false; | ||
628 | |||
590 | if (index == 0) { | 629 | if (index == 0) { |
591 | start_offset = first_page_offset; | 630 | start_offset = first_page_offset; |
592 | offset = start_offset; | 631 | offset = start_offset; |
@@ -598,7 +637,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
598 | entry = addr + start_offset; | 637 | entry = addr + start_offset; |
599 | 638 | ||
600 | memset(addr, 0, PAGE_CACHE_SIZE); | 639 | memset(addr, 0, PAGE_CACHE_SIZE); |
601 | while (1) { | 640 | while (node && !next_page) { |
602 | struct btrfs_free_space *e; | 641 | struct btrfs_free_space *e; |
603 | 642 | ||
604 | e = rb_entry(node, struct btrfs_free_space, offset_index); | 643 | e = rb_entry(node, struct btrfs_free_space, offset_index); |
@@ -614,12 +653,49 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
614 | entry->type = BTRFS_FREE_SPACE_EXTENT; | 653 | entry->type = BTRFS_FREE_SPACE_EXTENT; |
615 | } | 654 | } |
616 | node = rb_next(node); | 655 | node = rb_next(node); |
617 | if (!node) | 656 | if (!node && cluster) { |
618 | break; | 657 | node = rb_first(&cluster->root); |
658 | cluster = NULL; | ||
659 | } | ||
619 | offset += sizeof(struct btrfs_free_space_entry); | 660 | offset += sizeof(struct btrfs_free_space_entry); |
620 | if (offset + sizeof(struct btrfs_free_space_entry) >= | 661 | if (offset + sizeof(struct btrfs_free_space_entry) >= |
621 | PAGE_CACHE_SIZE) | 662 | PAGE_CACHE_SIZE) |
663 | next_page = true; | ||
664 | entry++; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * We want to add any pinned extents to our free space cache | ||
669 | * so we don't leak the space | ||
670 | */ | ||
671 | while (!next_page && (start < block_group->key.objectid + | ||
672 | block_group->key.offset)) { | ||
673 | ret = find_first_extent_bit(unpin, start, &start, &end, | ||
674 | EXTENT_DIRTY); | ||
675 | if (ret) { | ||
676 | ret = 0; | ||
677 | break; | ||
678 | } | ||
679 | |||
680 | /* This pinned extent is out of our range */ | ||
681 | if (start >= block_group->key.objectid + | ||
682 | block_group->key.offset) | ||
622 | break; | 683 | break; |
684 | |||
685 | len = block_group->key.objectid + | ||
686 | block_group->key.offset - start; | ||
687 | len = min(len, end + 1 - start); | ||
688 | |||
689 | entries++; | ||
690 | entry->offset = cpu_to_le64(start); | ||
691 | entry->bytes = cpu_to_le64(len); | ||
692 | entry->type = BTRFS_FREE_SPACE_EXTENT; | ||
693 | |||
694 | start = end + 1; | ||
695 | offset += sizeof(struct btrfs_free_space_entry); | ||
696 | if (offset + sizeof(struct btrfs_free_space_entry) >= | ||
697 | PAGE_CACHE_SIZE) | ||
698 | next_page = true; | ||
623 | entry++; | 699 | entry++; |
624 | } | 700 | } |
625 | *crc = ~(u32)0; | 701 | *crc = ~(u32)0; |
@@ -650,7 +726,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
650 | page_cache_release(page); | 726 | page_cache_release(page); |
651 | 727 | ||
652 | index++; | 728 | index++; |
653 | } while (node); | 729 | } while (node || next_page); |
654 | 730 | ||
655 | /* Write out the bitmaps */ | 731 | /* Write out the bitmaps */ |
656 | list_for_each_safe(pos, n, &bitmap_list) { | 732 | list_for_each_safe(pos, n, &bitmap_list) { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 93c28a1d6bdc..65413394daef 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -112,6 +112,7 @@ static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | |||
112 | static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | 112 | static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, |
113 | struct btrfs_root *root, struct inode *inode, | 113 | struct btrfs_root *root, struct inode *inode, |
114 | u64 start, size_t size, size_t compressed_size, | 114 | u64 start, size_t size, size_t compressed_size, |
115 | int compress_type, | ||
115 | struct page **compressed_pages) | 116 | struct page **compressed_pages) |
116 | { | 117 | { |
117 | struct btrfs_key key; | 118 | struct btrfs_key key; |
@@ -126,12 +127,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
126 | size_t cur_size = size; | 127 | size_t cur_size = size; |
127 | size_t datasize; | 128 | size_t datasize; |
128 | unsigned long offset; | 129 | unsigned long offset; |
129 | int compress_type = BTRFS_COMPRESS_NONE; | ||
130 | 130 | ||
131 | if (compressed_size && compressed_pages) { | 131 | if (compressed_size && compressed_pages) |
132 | compress_type = root->fs_info->compress_type; | ||
133 | cur_size = compressed_size; | 132 | cur_size = compressed_size; |
134 | } | ||
135 | 133 | ||
136 | path = btrfs_alloc_path(); | 134 | path = btrfs_alloc_path(); |
137 | if (!path) | 135 | if (!path) |
@@ -221,7 +219,7 @@ fail: | |||
221 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | 219 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, |
222 | struct btrfs_root *root, | 220 | struct btrfs_root *root, |
223 | struct inode *inode, u64 start, u64 end, | 221 | struct inode *inode, u64 start, u64 end, |
224 | size_t compressed_size, | 222 | size_t compressed_size, int compress_type, |
225 | struct page **compressed_pages) | 223 | struct page **compressed_pages) |
226 | { | 224 | { |
227 | u64 isize = i_size_read(inode); | 225 | u64 isize = i_size_read(inode); |
@@ -254,7 +252,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
254 | inline_len = min_t(u64, isize, actual_end); | 252 | inline_len = min_t(u64, isize, actual_end); |
255 | ret = insert_inline_extent(trans, root, inode, start, | 253 | ret = insert_inline_extent(trans, root, inode, start, |
256 | inline_len, compressed_size, | 254 | inline_len, compressed_size, |
257 | compressed_pages); | 255 | compress_type, compressed_pages); |
258 | BUG_ON(ret); | 256 | BUG_ON(ret); |
259 | btrfs_delalloc_release_metadata(inode, end + 1 - start); | 257 | btrfs_delalloc_release_metadata(inode, end + 1 - start); |
260 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); | 258 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); |
@@ -433,12 +431,13 @@ again: | |||
433 | * to make an uncompressed inline extent. | 431 | * to make an uncompressed inline extent. |
434 | */ | 432 | */ |
435 | ret = cow_file_range_inline(trans, root, inode, | 433 | ret = cow_file_range_inline(trans, root, inode, |
436 | start, end, 0, NULL); | 434 | start, end, 0, 0, NULL); |
437 | } else { | 435 | } else { |
438 | /* try making a compressed inline extent */ | 436 | /* try making a compressed inline extent */ |
439 | ret = cow_file_range_inline(trans, root, inode, | 437 | ret = cow_file_range_inline(trans, root, inode, |
440 | start, end, | 438 | start, end, |
441 | total_compressed, pages); | 439 | total_compressed, |
440 | compress_type, pages); | ||
442 | } | 441 | } |
443 | if (ret == 0) { | 442 | if (ret == 0) { |
444 | /* | 443 | /* |
@@ -792,7 +791,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
792 | if (start == 0) { | 791 | if (start == 0) { |
793 | /* lets try to make an inline extent */ | 792 | /* lets try to make an inline extent */ |
794 | ret = cow_file_range_inline(trans, root, inode, | 793 | ret = cow_file_range_inline(trans, root, inode, |
795 | start, end, 0, NULL); | 794 | start, end, 0, 0, NULL); |
796 | if (ret == 0) { | 795 | if (ret == 0) { |
797 | extent_clear_unlock_delalloc(inode, | 796 | extent_clear_unlock_delalloc(inode, |
798 | &BTRFS_I(inode)->io_tree, | 797 | &BTRFS_I(inode)->io_tree, |
@@ -2222,8 +2221,6 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
2222 | insert = 1; | 2221 | insert = 1; |
2223 | #endif | 2222 | #endif |
2224 | insert = 1; | 2223 | insert = 1; |
2225 | } else { | ||
2226 | WARN_ON(!BTRFS_I(inode)->orphan_meta_reserved); | ||
2227 | } | 2224 | } |
2228 | 2225 | ||
2229 | if (!BTRFS_I(inode)->orphan_meta_reserved) { | 2226 | if (!BTRFS_I(inode)->orphan_meta_reserved) { |
@@ -2537,8 +2534,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
2537 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | 2534 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); |
2538 | 2535 | ||
2539 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | 2536 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); |
2540 | if (location.objectid == BTRFS_FREE_SPACE_OBJECTID) | ||
2541 | inode->i_mapping->flags &= ~__GFP_FS; | ||
2542 | 2537 | ||
2543 | /* | 2538 | /* |
2544 | * try to precache a NULL acl entry for files that don't have | 2539 | * try to precache a NULL acl entry for files that don't have |
@@ -6960,8 +6955,10 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
6960 | * should cover the worst case number of items we'll modify. | 6955 | * should cover the worst case number of items we'll modify. |
6961 | */ | 6956 | */ |
6962 | trans = btrfs_start_transaction(root, 20); | 6957 | trans = btrfs_start_transaction(root, 20); |
6963 | if (IS_ERR(trans)) | 6958 | if (IS_ERR(trans)) { |
6964 | return PTR_ERR(trans); | 6959 | ret = PTR_ERR(trans); |
6960 | goto out_notrans; | ||
6961 | } | ||
6965 | 6962 | ||
6966 | btrfs_set_trans_block_group(trans, new_dir); | 6963 | btrfs_set_trans_block_group(trans, new_dir); |
6967 | 6964 | ||
@@ -7061,7 +7058,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
7061 | } | 7058 | } |
7062 | out_fail: | 7059 | out_fail: |
7063 | btrfs_end_transaction_throttle(trans, root); | 7060 | btrfs_end_transaction_throttle(trans, root); |
7064 | 7061 | out_notrans: | |
7065 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | 7062 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) |
7066 | up_read(&root->fs_info->subvol_sem); | 7063 | up_read(&root->fs_info->subvol_sem); |
7067 | 7064 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 7c07fe26b7cf..cfc264fefdb0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -373,6 +373,10 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
373 | inode_item->nbytes = cpu_to_le64(root->leafsize); | 373 | inode_item->nbytes = cpu_to_le64(root->leafsize); |
374 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); | 374 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); |
375 | 375 | ||
376 | root_item.flags = 0; | ||
377 | root_item.byte_limit = 0; | ||
378 | inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT); | ||
379 | |||
376 | btrfs_set_root_bytenr(&root_item, leaf->start); | 380 | btrfs_set_root_bytenr(&root_item, leaf->start); |
377 | btrfs_set_root_generation(&root_item, trans->transid); | 381 | btrfs_set_root_generation(&root_item, trans->transid); |
378 | btrfs_set_root_level(&root_item, 0); | 382 | btrfs_set_root_level(&root_item, 0); |
@@ -2436,8 +2440,10 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp | |||
2436 | return PTR_ERR(trans); | 2440 | return PTR_ERR(trans); |
2437 | transid = trans->transid; | 2441 | transid = trans->transid; |
2438 | ret = btrfs_commit_transaction_async(trans, root, 0); | 2442 | ret = btrfs_commit_transaction_async(trans, root, 0); |
2439 | if (ret) | 2443 | if (ret) { |
2444 | btrfs_end_transaction(trans, root); | ||
2440 | return ret; | 2445 | return ret; |
2446 | } | ||
2441 | 2447 | ||
2442 | if (argp) | 2448 | if (argp) |
2443 | if (copy_to_user(argp, &transid, sizeof(transid))) | 2449 | if (copy_to_user(argp, &transid, sizeof(transid))) |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 29b2d7c930eb..6928bff62daa 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -473,3 +473,21 @@ again: | |||
473 | btrfs_free_path(path); | 473 | btrfs_free_path(path); |
474 | return 0; | 474 | return 0; |
475 | } | 475 | } |
476 | |||
477 | /* | ||
478 | * Old btrfs forgets to init root_item->flags and root_item->byte_limit | ||
479 | * for subvolumes. To work around this problem, we steal a bit from | ||
480 | * root_item->inode_item->flags, and use it to indicate if those fields | ||
481 | * have been properly initialized. | ||
482 | */ | ||
483 | void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item) | ||
484 | { | ||
485 | u64 inode_flags = le64_to_cpu(root_item->inode.flags); | ||
486 | |||
487 | if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) { | ||
488 | inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT; | ||
489 | root_item->inode.flags = cpu_to_le64(inode_flags); | ||
490 | root_item->flags = 0; | ||
491 | root_item->byte_limit = 0; | ||
492 | } | ||
493 | } | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 2edfc039f098..58e7de9cc90c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -644,6 +644,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
644 | { | 644 | { |
645 | struct btrfs_root *root = btrfs_sb(vfs->mnt_sb); | 645 | struct btrfs_root *root = btrfs_sb(vfs->mnt_sb); |
646 | struct btrfs_fs_info *info = root->fs_info; | 646 | struct btrfs_fs_info *info = root->fs_info; |
647 | char *compress_type; | ||
647 | 648 | ||
648 | if (btrfs_test_opt(root, DEGRADED)) | 649 | if (btrfs_test_opt(root, DEGRADED)) |
649 | seq_puts(seq, ",degraded"); | 650 | seq_puts(seq, ",degraded"); |
@@ -662,8 +663,16 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
662 | if (info->thread_pool_size != min_t(unsigned long, | 663 | if (info->thread_pool_size != min_t(unsigned long, |
663 | num_online_cpus() + 2, 8)) | 664 | num_online_cpus() + 2, 8)) |
664 | seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); | 665 | seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); |
665 | if (btrfs_test_opt(root, COMPRESS)) | 666 | if (btrfs_test_opt(root, COMPRESS)) { |
666 | seq_puts(seq, ",compress"); | 667 | if (info->compress_type == BTRFS_COMPRESS_ZLIB) |
668 | compress_type = "zlib"; | ||
669 | else | ||
670 | compress_type = "lzo"; | ||
671 | if (btrfs_test_opt(root, FORCE_COMPRESS)) | ||
672 | seq_printf(seq, ",compress-force=%s", compress_type); | ||
673 | else | ||
674 | seq_printf(seq, ",compress=%s", compress_type); | ||
675 | } | ||
667 | if (btrfs_test_opt(root, NOSSD)) | 676 | if (btrfs_test_opt(root, NOSSD)) |
668 | seq_puts(seq, ",nossd"); | 677 | seq_puts(seq, ",nossd"); |
669 | if (btrfs_test_opt(root, SSD_SPREAD)) | 678 | if (btrfs_test_opt(root, SSD_SPREAD)) |
@@ -678,6 +687,12 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
678 | seq_puts(seq, ",discard"); | 687 | seq_puts(seq, ",discard"); |
679 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) | 688 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) |
680 | seq_puts(seq, ",noacl"); | 689 | seq_puts(seq, ",noacl"); |
690 | if (btrfs_test_opt(root, SPACE_CACHE)) | ||
691 | seq_puts(seq, ",space_cache"); | ||
692 | if (btrfs_test_opt(root, CLEAR_CACHE)) | ||
693 | seq_puts(seq, ",clear_cache"); | ||
694 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) | ||
695 | seq_puts(seq, ",user_subvol_rm_allowed"); | ||
681 | return 0; | 696 | return 0; |
682 | } | 697 | } |
683 | 698 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index ce48eb59d615..5b158da7e0bb 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -197,6 +197,7 @@ again: | |||
197 | 197 | ||
198 | ret = join_transaction(root); | 198 | ret = join_transaction(root); |
199 | if (ret < 0) { | 199 | if (ret < 0) { |
200 | kmem_cache_free(btrfs_trans_handle_cachep, h); | ||
200 | if (type != TRANS_JOIN_NOLOCK) | 201 | if (type != TRANS_JOIN_NOLOCK) |
201 | mutex_unlock(&root->fs_info->trans_mutex); | 202 | mutex_unlock(&root->fs_info->trans_mutex); |
202 | return ERR_PTR(ret); | 203 | return ERR_PTR(ret); |
@@ -975,6 +976,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
975 | record_root_in_trans(trans, root); | 976 | record_root_in_trans(trans, root); |
976 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | 977 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); |
977 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); | 978 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); |
979 | btrfs_check_and_init_root_item(new_root_item); | ||
978 | 980 | ||
979 | root_flags = btrfs_root_flags(new_root_item); | 981 | root_flags = btrfs_root_flags(new_root_item); |
980 | if (pending->readonly) | 982 | if (pending->readonly) |