diff options
| author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-24 14:31:04 -0500 |
|---|---|---|
| committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-02-24 14:33:45 -0500 |
| commit | 109d28152b6e9d5de64cd23e3bc08885ccb3d1ef (patch) | |
| tree | b7b8863faa05254781acfb85cc41da3eef467c6b /fs/btrfs | |
| parent | 168cf9af699e87d5a6f44b684583714ecabb8e71 (diff) | |
| parent | 60b341b778cc2929df16c0a504c91621b3c6a4ad (diff) | |
Merge tag 'v2.6.33' for its firewire changes since last branch point
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/acl.c | 13 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 13 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 40 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.c | 14 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 104 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 72 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 9 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 17 |
12 files changed, 176 insertions, 119 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 2e9e69987a82..6df6d6ed74fd 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
| @@ -112,12 +112,14 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, | |||
| 112 | switch (type) { | 112 | switch (type) { |
| 113 | case ACL_TYPE_ACCESS: | 113 | case ACL_TYPE_ACCESS: |
| 114 | mode = inode->i_mode; | 114 | mode = inode->i_mode; |
| 115 | ret = posix_acl_equiv_mode(acl, &mode); | ||
| 116 | if (ret < 0) | ||
| 117 | return ret; | ||
| 118 | ret = 0; | ||
| 119 | inode->i_mode = mode; | ||
| 120 | name = POSIX_ACL_XATTR_ACCESS; | 115 | name = POSIX_ACL_XATTR_ACCESS; |
| 116 | if (acl) { | ||
| 117 | ret = posix_acl_equiv_mode(acl, &mode); | ||
| 118 | if (ret < 0) | ||
| 119 | return ret; | ||
| 120 | inode->i_mode = mode; | ||
| 121 | } | ||
| 122 | ret = 0; | ||
| 121 | break; | 123 | break; |
| 122 | case ACL_TYPE_DEFAULT: | 124 | case ACL_TYPE_DEFAULT: |
| 123 | if (!S_ISDIR(inode->i_mode)) | 125 | if (!S_ISDIR(inode->i_mode)) |
| @@ -242,6 +244,7 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans, | |||
| 242 | ACL_TYPE_ACCESS); | 244 | ACL_TYPE_ACCESS); |
| 243 | } | 245 | } |
| 244 | } | 246 | } |
| 247 | posix_acl_release(clone); | ||
| 245 | } | 248 | } |
| 246 | failed: | 249 | failed: |
| 247 | posix_acl_release(acl); | 250 | posix_acl_release(acl); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 9f806dd04c27..2aa8ec6a0981 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1161,6 +1161,7 @@ struct btrfs_root { | |||
| 1161 | #define BTRFS_MOUNT_SSD_SPREAD (1 << 8) | 1161 | #define BTRFS_MOUNT_SSD_SPREAD (1 << 8) |
| 1162 | #define BTRFS_MOUNT_NOSSD (1 << 9) | 1162 | #define BTRFS_MOUNT_NOSSD (1 << 9) |
| 1163 | #define BTRFS_MOUNT_DISCARD (1 << 10) | 1163 | #define BTRFS_MOUNT_DISCARD (1 << 10) |
| 1164 | #define BTRFS_MOUNT_FORCE_COMPRESS (1 << 11) | ||
| 1164 | 1165 | ||
| 1165 | #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) | 1166 | #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) |
| 1166 | #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) | 1167 | #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 009e3bd18f23..2b59201b955c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1982,7 +1982,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1982 | 1982 | ||
| 1983 | if (!(sb->s_flags & MS_RDONLY)) { | 1983 | if (!(sb->s_flags & MS_RDONLY)) { |
| 1984 | ret = btrfs_recover_relocation(tree_root); | 1984 | ret = btrfs_recover_relocation(tree_root); |
| 1985 | BUG_ON(ret); | 1985 | if (ret < 0) { |
| 1986 | printk(KERN_WARNING | ||
| 1987 | "btrfs: failed to recover relocation\n"); | ||
| 1988 | err = -EINVAL; | ||
| 1989 | goto fail_trans_kthread; | ||
| 1990 | } | ||
| 1986 | } | 1991 | } |
| 1987 | 1992 | ||
| 1988 | location.objectid = BTRFS_FS_TREE_OBJECTID; | 1993 | location.objectid = BTRFS_FS_TREE_OBJECTID; |
| @@ -1993,6 +1998,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1993 | if (!fs_info->fs_root) | 1998 | if (!fs_info->fs_root) |
| 1994 | goto fail_trans_kthread; | 1999 | goto fail_trans_kthread; |
| 1995 | 2000 | ||
| 2001 | if (!(sb->s_flags & MS_RDONLY)) { | ||
| 2002 | down_read(&fs_info->cleanup_work_sem); | ||
| 2003 | btrfs_orphan_cleanup(fs_info->fs_root); | ||
| 2004 | up_read(&fs_info->cleanup_work_sem); | ||
| 2005 | } | ||
| 2006 | |||
| 1996 | return tree_root; | 2007 | return tree_root; |
| 1997 | 2008 | ||
| 1998 | fail_trans_kthread: | 2009 | fail_trans_kthread: |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 56e50137d0e6..559f72489b3b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -83,6 +83,17 @@ static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) | |||
| 83 | return (cache->flags & bits) == bits; | 83 | return (cache->flags & bits) == bits; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | void btrfs_get_block_group(struct btrfs_block_group_cache *cache) | ||
| 87 | { | ||
| 88 | atomic_inc(&cache->count); | ||
| 89 | } | ||
| 90 | |||
| 91 | void btrfs_put_block_group(struct btrfs_block_group_cache *cache) | ||
| 92 | { | ||
| 93 | if (atomic_dec_and_test(&cache->count)) | ||
| 94 | kfree(cache); | ||
| 95 | } | ||
| 96 | |||
| 86 | /* | 97 | /* |
| 87 | * this adds the block group to the fs_info rb tree for the block group | 98 | * this adds the block group to the fs_info rb tree for the block group |
| 88 | * cache | 99 | * cache |
| @@ -156,7 +167,7 @@ block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr, | |||
| 156 | } | 167 | } |
| 157 | } | 168 | } |
| 158 | if (ret) | 169 | if (ret) |
| 159 | atomic_inc(&ret->count); | 170 | btrfs_get_block_group(ret); |
| 160 | spin_unlock(&info->block_group_cache_lock); | 171 | spin_unlock(&info->block_group_cache_lock); |
| 161 | 172 | ||
| 162 | return ret; | 173 | return ret; |
| @@ -407,6 +418,8 @@ err: | |||
| 407 | 418 | ||
| 408 | put_caching_control(caching_ctl); | 419 | put_caching_control(caching_ctl); |
| 409 | atomic_dec(&block_group->space_info->caching_threads); | 420 | atomic_dec(&block_group->space_info->caching_threads); |
| 421 | btrfs_put_block_group(block_group); | ||
| 422 | |||
| 410 | return 0; | 423 | return 0; |
| 411 | } | 424 | } |
| 412 | 425 | ||
| @@ -447,6 +460,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache) | |||
| 447 | up_write(&fs_info->extent_commit_sem); | 460 | up_write(&fs_info->extent_commit_sem); |
| 448 | 461 | ||
| 449 | atomic_inc(&cache->space_info->caching_threads); | 462 | atomic_inc(&cache->space_info->caching_threads); |
| 463 | btrfs_get_block_group(cache); | ||
| 450 | 464 | ||
| 451 | tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n", | 465 | tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n", |
| 452 | cache->key.objectid); | 466 | cache->key.objectid); |
| @@ -486,12 +500,6 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group( | |||
| 486 | return cache; | 500 | return cache; |
| 487 | } | 501 | } |
| 488 | 502 | ||
| 489 | void btrfs_put_block_group(struct btrfs_block_group_cache *cache) | ||
| 490 | { | ||
| 491 | if (atomic_dec_and_test(&cache->count)) | ||
| 492 | kfree(cache); | ||
| 493 | } | ||
| 494 | |||
| 495 | static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | 503 | static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, |
| 496 | u64 flags) | 504 | u64 flags) |
| 497 | { | 505 | { |
| @@ -2582,7 +2590,7 @@ next_block_group(struct btrfs_root *root, | |||
| 2582 | if (node) { | 2590 | if (node) { |
| 2583 | cache = rb_entry(node, struct btrfs_block_group_cache, | 2591 | cache = rb_entry(node, struct btrfs_block_group_cache, |
| 2584 | cache_node); | 2592 | cache_node); |
| 2585 | atomic_inc(&cache->count); | 2593 | btrfs_get_block_group(cache); |
| 2586 | } else | 2594 | } else |
| 2587 | cache = NULL; | 2595 | cache = NULL; |
| 2588 | spin_unlock(&root->fs_info->block_group_cache_lock); | 2596 | spin_unlock(&root->fs_info->block_group_cache_lock); |
| @@ -4227,7 +4235,7 @@ search: | |||
| 4227 | u64 offset; | 4235 | u64 offset; |
| 4228 | int cached; | 4236 | int cached; |
| 4229 | 4237 | ||
| 4230 | atomic_inc(&block_group->count); | 4238 | btrfs_get_block_group(block_group); |
| 4231 | search_start = block_group->key.objectid; | 4239 | search_start = block_group->key.objectid; |
| 4232 | 4240 | ||
| 4233 | have_block_group: | 4241 | have_block_group: |
| @@ -4315,7 +4323,7 @@ have_block_group: | |||
| 4315 | 4323 | ||
| 4316 | btrfs_put_block_group(block_group); | 4324 | btrfs_put_block_group(block_group); |
| 4317 | block_group = last_ptr->block_group; | 4325 | block_group = last_ptr->block_group; |
| 4318 | atomic_inc(&block_group->count); | 4326 | btrfs_get_block_group(block_group); |
| 4319 | spin_unlock(&last_ptr->lock); | 4327 | spin_unlock(&last_ptr->lock); |
| 4320 | spin_unlock(&last_ptr->refill_lock); | 4328 | spin_unlock(&last_ptr->refill_lock); |
| 4321 | 4329 | ||
| @@ -5394,10 +5402,6 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, | |||
| 5394 | int ret; | 5402 | int ret; |
| 5395 | 5403 | ||
| 5396 | while (level >= 0) { | 5404 | while (level >= 0) { |
| 5397 | if (path->slots[level] >= | ||
| 5398 | btrfs_header_nritems(path->nodes[level])) | ||
| 5399 | break; | ||
| 5400 | |||
| 5401 | ret = walk_down_proc(trans, root, path, wc, lookup_info); | 5405 | ret = walk_down_proc(trans, root, path, wc, lookup_info); |
| 5402 | if (ret > 0) | 5406 | if (ret > 0) |
| 5403 | break; | 5407 | break; |
| @@ -5405,6 +5409,10 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, | |||
| 5405 | if (level == 0) | 5409 | if (level == 0) |
| 5406 | break; | 5410 | break; |
| 5407 | 5411 | ||
| 5412 | if (path->slots[level] >= | ||
| 5413 | btrfs_header_nritems(path->nodes[level])) | ||
| 5414 | break; | ||
| 5415 | |||
| 5408 | ret = do_walk_down(trans, root, path, wc, &lookup_info); | 5416 | ret = do_walk_down(trans, root, path, wc, &lookup_info); |
| 5409 | if (ret > 0) { | 5417 | if (ret > 0) { |
| 5410 | path->slots[level]++; | 5418 | path->slots[level]++; |
| @@ -7395,9 +7403,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
| 7395 | wait_block_group_cache_done(block_group); | 7403 | wait_block_group_cache_done(block_group); |
| 7396 | 7404 | ||
| 7397 | btrfs_remove_free_space_cache(block_group); | 7405 | btrfs_remove_free_space_cache(block_group); |
| 7398 | 7406 | btrfs_put_block_group(block_group); | |
| 7399 | WARN_ON(atomic_read(&block_group->count) != 1); | ||
| 7400 | kfree(block_group); | ||
| 7401 | 7407 | ||
| 7402 | spin_lock(&info->block_group_cache_lock); | 7408 | spin_lock(&info->block_group_cache_lock); |
| 7403 | } | 7409 | } |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 96577e8bf9fd..b177ed319612 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -3165,10 +3165,9 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
| 3165 | spin_unlock(&tree->buffer_lock); | 3165 | spin_unlock(&tree->buffer_lock); |
| 3166 | goto free_eb; | 3166 | goto free_eb; |
| 3167 | } | 3167 | } |
| 3168 | spin_unlock(&tree->buffer_lock); | ||
| 3169 | |||
| 3170 | /* add one reference for the tree */ | 3168 | /* add one reference for the tree */ |
| 3171 | atomic_inc(&eb->refs); | 3169 | atomic_inc(&eb->refs); |
| 3170 | spin_unlock(&tree->buffer_lock); | ||
| 3172 | return eb; | 3171 | return eb; |
| 3173 | 3172 | ||
| 3174 | free_eb: | 3173 | free_eb: |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 46bea0f4dc7b..428fcac45f90 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
| @@ -155,20 +155,6 @@ static struct rb_node *__tree_search(struct rb_root *root, u64 offset, | |||
| 155 | return NULL; | 155 | return NULL; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | /* | ||
| 159 | * look for an offset in the tree, and if it can't be found, return | ||
| 160 | * the first offset we can find smaller than 'offset'. | ||
| 161 | */ | ||
| 162 | static inline struct rb_node *tree_search(struct rb_root *root, u64 offset) | ||
| 163 | { | ||
| 164 | struct rb_node *prev; | ||
| 165 | struct rb_node *ret; | ||
| 166 | ret = __tree_search(root, offset, &prev, NULL); | ||
| 167 | if (!ret) | ||
| 168 | return prev; | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* check to see if two extent_map structs are adjacent and safe to merge */ | 158 | /* check to see if two extent_map structs are adjacent and safe to merge */ |
| 173 | static int mergable_maps(struct extent_map *prev, struct extent_map *next) | 159 | static int mergable_maps(struct extent_map *prev, struct extent_map *next) |
| 174 | { | 160 | { |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index feaa13b105d9..6ed434ac037f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -506,7 +506,8 @@ next_slot: | |||
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static int extent_mergeable(struct extent_buffer *leaf, int slot, | 508 | static int extent_mergeable(struct extent_buffer *leaf, int slot, |
| 509 | u64 objectid, u64 bytenr, u64 *start, u64 *end) | 509 | u64 objectid, u64 bytenr, u64 orig_offset, |
| 510 | u64 *start, u64 *end) | ||
| 510 | { | 511 | { |
| 511 | struct btrfs_file_extent_item *fi; | 512 | struct btrfs_file_extent_item *fi; |
| 512 | struct btrfs_key key; | 513 | struct btrfs_key key; |
| @@ -522,6 +523,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, | |||
| 522 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | 523 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
| 523 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || | 524 | if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG || |
| 524 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || | 525 | btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || |
| 526 | btrfs_file_extent_offset(leaf, fi) != key.offset - orig_offset || | ||
| 525 | btrfs_file_extent_compression(leaf, fi) || | 527 | btrfs_file_extent_compression(leaf, fi) || |
| 526 | btrfs_file_extent_encryption(leaf, fi) || | 528 | btrfs_file_extent_encryption(leaf, fi) || |
| 527 | btrfs_file_extent_other_encoding(leaf, fi)) | 529 | btrfs_file_extent_other_encoding(leaf, fi)) |
| @@ -561,6 +563,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | |||
| 561 | u64 split; | 563 | u64 split; |
| 562 | int del_nr = 0; | 564 | int del_nr = 0; |
| 563 | int del_slot = 0; | 565 | int del_slot = 0; |
| 566 | int recow; | ||
| 564 | int ret; | 567 | int ret; |
| 565 | 568 | ||
| 566 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 569 | btrfs_drop_extent_cache(inode, start, end - 1, 0); |
| @@ -568,6 +571,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | |||
| 568 | path = btrfs_alloc_path(); | 571 | path = btrfs_alloc_path(); |
| 569 | BUG_ON(!path); | 572 | BUG_ON(!path); |
| 570 | again: | 573 | again: |
| 574 | recow = 0; | ||
| 571 | split = start; | 575 | split = start; |
| 572 | key.objectid = inode->i_ino; | 576 | key.objectid = inode->i_ino; |
| 573 | key.type = BTRFS_EXTENT_DATA_KEY; | 577 | key.type = BTRFS_EXTENT_DATA_KEY; |
| @@ -591,12 +595,60 @@ again: | |||
| 591 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 595 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
| 592 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); | 596 | num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); |
| 593 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); | 597 | orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); |
| 598 | memcpy(&new_key, &key, sizeof(new_key)); | ||
| 599 | |||
| 600 | if (start == key.offset && end < extent_end) { | ||
| 601 | other_start = 0; | ||
| 602 | other_end = start; | ||
| 603 | if (extent_mergeable(leaf, path->slots[0] - 1, | ||
| 604 | inode->i_ino, bytenr, orig_offset, | ||
| 605 | &other_start, &other_end)) { | ||
| 606 | new_key.offset = end; | ||
| 607 | btrfs_set_item_key_safe(trans, root, path, &new_key); | ||
| 608 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
| 609 | struct btrfs_file_extent_item); | ||
| 610 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
| 611 | extent_end - end); | ||
| 612 | btrfs_set_file_extent_offset(leaf, fi, | ||
| 613 | end - orig_offset); | ||
| 614 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, | ||
| 615 | struct btrfs_file_extent_item); | ||
| 616 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
| 617 | end - other_start); | ||
| 618 | btrfs_mark_buffer_dirty(leaf); | ||
| 619 | goto out; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | if (start > key.offset && end == extent_end) { | ||
| 624 | other_start = end; | ||
| 625 | other_end = 0; | ||
| 626 | if (extent_mergeable(leaf, path->slots[0] + 1, | ||
| 627 | inode->i_ino, bytenr, orig_offset, | ||
| 628 | &other_start, &other_end)) { | ||
| 629 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
| 630 | struct btrfs_file_extent_item); | ||
| 631 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
| 632 | start - key.offset); | ||
| 633 | path->slots[0]++; | ||
| 634 | new_key.offset = start; | ||
| 635 | btrfs_set_item_key_safe(trans, root, path, &new_key); | ||
| 636 | |||
| 637 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
| 638 | struct btrfs_file_extent_item); | ||
| 639 | btrfs_set_file_extent_num_bytes(leaf, fi, | ||
| 640 | other_end - start); | ||
| 641 | btrfs_set_file_extent_offset(leaf, fi, | ||
| 642 | start - orig_offset); | ||
| 643 | btrfs_mark_buffer_dirty(leaf); | ||
| 644 | goto out; | ||
| 645 | } | ||
| 646 | } | ||
| 594 | 647 | ||
| 595 | while (start > key.offset || end < extent_end) { | 648 | while (start > key.offset || end < extent_end) { |
| 596 | if (key.offset == start) | 649 | if (key.offset == start) |
| 597 | split = end; | 650 | split = end; |
| 598 | 651 | ||
| 599 | memcpy(&new_key, &key, sizeof(new_key)); | ||
| 600 | new_key.offset = split; | 652 | new_key.offset = split; |
| 601 | ret = btrfs_duplicate_item(trans, root, path, &new_key); | 653 | ret = btrfs_duplicate_item(trans, root, path, &new_key); |
| 602 | if (ret == -EAGAIN) { | 654 | if (ret == -EAGAIN) { |
| @@ -631,15 +683,18 @@ again: | |||
| 631 | path->slots[0]--; | 683 | path->slots[0]--; |
| 632 | extent_end = end; | 684 | extent_end = end; |
| 633 | } | 685 | } |
| 686 | recow = 1; | ||
| 634 | } | 687 | } |
| 635 | 688 | ||
| 636 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
| 637 | struct btrfs_file_extent_item); | ||
| 638 | |||
| 639 | other_start = end; | 689 | other_start = end; |
| 640 | other_end = 0; | 690 | other_end = 0; |
| 641 | if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, | 691 | if (extent_mergeable(leaf, path->slots[0] + 1, |
| 642 | bytenr, &other_start, &other_end)) { | 692 | inode->i_ino, bytenr, orig_offset, |
| 693 | &other_start, &other_end)) { | ||
| 694 | if (recow) { | ||
| 695 | btrfs_release_path(root, path); | ||
| 696 | goto again; | ||
| 697 | } | ||
| 643 | extent_end = other_end; | 698 | extent_end = other_end; |
| 644 | del_slot = path->slots[0] + 1; | 699 | del_slot = path->slots[0] + 1; |
| 645 | del_nr++; | 700 | del_nr++; |
| @@ -650,8 +705,13 @@ again: | |||
| 650 | } | 705 | } |
| 651 | other_start = 0; | 706 | other_start = 0; |
| 652 | other_end = start; | 707 | other_end = start; |
| 653 | if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino, | 708 | if (extent_mergeable(leaf, path->slots[0] - 1, |
| 654 | bytenr, &other_start, &other_end)) { | 709 | inode->i_ino, bytenr, orig_offset, |
| 710 | &other_start, &other_end)) { | ||
| 711 | if (recow) { | ||
| 712 | btrfs_release_path(root, path); | ||
| 713 | goto again; | ||
| 714 | } | ||
| 655 | key.offset = other_start; | 715 | key.offset = other_start; |
| 656 | del_slot = path->slots[0]; | 716 | del_slot = path->slots[0]; |
| 657 | del_nr++; | 717 | del_nr++; |
| @@ -661,21 +721,23 @@ again: | |||
| 661 | BUG_ON(ret); | 721 | BUG_ON(ret); |
| 662 | } | 722 | } |
| 663 | if (del_nr == 0) { | 723 | if (del_nr == 0) { |
| 724 | fi = btrfs_item_ptr(leaf, path->slots[0], | ||
| 725 | struct btrfs_file_extent_item); | ||
| 664 | btrfs_set_file_extent_type(leaf, fi, | 726 | btrfs_set_file_extent_type(leaf, fi, |
| 665 | BTRFS_FILE_EXTENT_REG); | 727 | BTRFS_FILE_EXTENT_REG); |
| 666 | btrfs_mark_buffer_dirty(leaf); | 728 | btrfs_mark_buffer_dirty(leaf); |
| 667 | goto out; | 729 | } else { |
| 668 | } | 730 | fi = btrfs_item_ptr(leaf, del_slot - 1, |
| 669 | 731 | struct btrfs_file_extent_item); | |
| 670 | fi = btrfs_item_ptr(leaf, del_slot - 1, | 732 | btrfs_set_file_extent_type(leaf, fi, |
| 671 | struct btrfs_file_extent_item); | 733 | BTRFS_FILE_EXTENT_REG); |
| 672 | btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); | 734 | btrfs_set_file_extent_num_bytes(leaf, fi, |
| 673 | btrfs_set_file_extent_num_bytes(leaf, fi, | 735 | extent_end - key.offset); |
| 674 | extent_end - key.offset); | 736 | btrfs_mark_buffer_dirty(leaf); |
| 675 | btrfs_mark_buffer_dirty(leaf); | ||
| 676 | 737 | ||
| 677 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); | 738 | ret = btrfs_del_items(trans, root, path, del_slot, del_nr); |
| 678 | BUG_ON(ret); | 739 | BUG_ON(ret); |
| 740 | } | ||
| 679 | out: | 741 | out: |
| 680 | btrfs_free_path(path); | 742 | btrfs_free_path(path); |
| 681 | return 0; | 743 | return 0; |
| @@ -1073,7 +1135,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
| 1073 | } | 1135 | } |
| 1074 | mutex_lock(&dentry->d_inode->i_mutex); | 1136 | mutex_lock(&dentry->d_inode->i_mutex); |
| 1075 | out: | 1137 | out: |
| 1076 | return ret > 0 ? EIO : ret; | 1138 | return ret > 0 ? -EIO : ret; |
| 1077 | } | 1139 | } |
| 1078 | 1140 | ||
| 1079 | static const struct vm_operations_struct btrfs_file_vm_ops = { | 1141 | static const struct vm_operations_struct btrfs_file_vm_ops = { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5440bab23635..4deb280f8969 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -483,7 +483,8 @@ again: | |||
| 483 | nr_pages_ret = 0; | 483 | nr_pages_ret = 0; |
| 484 | 484 | ||
| 485 | /* flag the file so we don't compress in the future */ | 485 | /* flag the file so we don't compress in the future */ |
| 486 | BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; | 486 | if (!btrfs_test_opt(root, FORCE_COMPRESS)) |
| 487 | BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; | ||
| 487 | } | 488 | } |
| 488 | if (will_compress) { | 489 | if (will_compress) { |
| 489 | *num_added += 1; | 490 | *num_added += 1; |
| @@ -1680,24 +1681,6 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
| 1680 | * before we start the transaction. It limits the amount of btree | 1681 | * before we start the transaction. It limits the amount of btree |
| 1681 | * reads required while inside the transaction. | 1682 | * reads required while inside the transaction. |
| 1682 | */ | 1683 | */ |
| 1683 | static noinline void reada_csum(struct btrfs_root *root, | ||
| 1684 | struct btrfs_path *path, | ||
| 1685 | struct btrfs_ordered_extent *ordered_extent) | ||
| 1686 | { | ||
| 1687 | struct btrfs_ordered_sum *sum; | ||
| 1688 | u64 bytenr; | ||
| 1689 | |||
| 1690 | sum = list_entry(ordered_extent->list.next, struct btrfs_ordered_sum, | ||
| 1691 | list); | ||
| 1692 | bytenr = sum->sums[0].bytenr; | ||
| 1693 | |||
| 1694 | /* | ||
| 1695 | * we don't care about the results, the point of this search is | ||
| 1696 | * just to get the btree leaves into ram | ||
| 1697 | */ | ||
| 1698 | btrfs_lookup_csum(NULL, root->fs_info->csum_root, path, bytenr, 0); | ||
| 1699 | } | ||
| 1700 | |||
| 1701 | /* as ordered data IO finishes, this gets called so we can finish | 1684 | /* as ordered data IO finishes, this gets called so we can finish |
| 1702 | * an ordered extent if the range of bytes in the file it covers are | 1685 | * an ordered extent if the range of bytes in the file it covers are |
| 1703 | * fully written. | 1686 | * fully written. |
| @@ -1708,7 +1691,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 1708 | struct btrfs_trans_handle *trans; | 1691 | struct btrfs_trans_handle *trans; |
| 1709 | struct btrfs_ordered_extent *ordered_extent = NULL; | 1692 | struct btrfs_ordered_extent *ordered_extent = NULL; |
| 1710 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 1693 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
| 1711 | struct btrfs_path *path; | ||
| 1712 | int compressed = 0; | 1694 | int compressed = 0; |
| 1713 | int ret; | 1695 | int ret; |
| 1714 | 1696 | ||
| @@ -1716,32 +1698,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 1716 | if (!ret) | 1698 | if (!ret) |
| 1717 | return 0; | 1699 | return 0; |
| 1718 | 1700 | ||
| 1719 | /* | 1701 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); |
| 1720 | * before we join the transaction, try to do some of our IO. | ||
| 1721 | * This will limit the amount of IO that we have to do with | ||
| 1722 | * the transaction running. We're unlikely to need to do any | ||
| 1723 | * IO if the file extents are new, the disk_i_size checks | ||
| 1724 | * covers the most common case. | ||
| 1725 | */ | ||
| 1726 | if (start < BTRFS_I(inode)->disk_i_size) { | ||
| 1727 | path = btrfs_alloc_path(); | ||
| 1728 | if (path) { | ||
| 1729 | ret = btrfs_lookup_file_extent(NULL, root, path, | ||
| 1730 | inode->i_ino, | ||
| 1731 | start, 0); | ||
| 1732 | ordered_extent = btrfs_lookup_ordered_extent(inode, | ||
| 1733 | start); | ||
| 1734 | if (!list_empty(&ordered_extent->list)) { | ||
| 1735 | btrfs_release_path(root, path); | ||
| 1736 | reada_csum(root, path, ordered_extent); | ||
| 1737 | } | ||
| 1738 | btrfs_free_path(path); | ||
| 1739 | } | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | if (!ordered_extent) | ||
| 1743 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); | ||
| 1744 | BUG_ON(!ordered_extent); | 1702 | BUG_ON(!ordered_extent); |
| 1703 | |||
| 1745 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) { | 1704 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) { |
| 1746 | BUG_ON(!list_empty(&ordered_extent->list)); | 1705 | BUG_ON(!list_empty(&ordered_extent->list)); |
| 1747 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); | 1706 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
| @@ -3995,7 +3954,11 @@ skip: | |||
| 3995 | 3954 | ||
| 3996 | /* Reached end of directory/root. Bump pos past the last item. */ | 3955 | /* Reached end of directory/root. Bump pos past the last item. */ |
| 3997 | if (key_type == BTRFS_DIR_INDEX_KEY) | 3956 | if (key_type == BTRFS_DIR_INDEX_KEY) |
| 3998 | filp->f_pos = INT_LIMIT(off_t); | 3957 | /* |
| 3958 | * 32-bit glibc will use getdents64, but then strtol - | ||
| 3959 | * so the last number we can serve is this. | ||
| 3960 | */ | ||
| 3961 | filp->f_pos = 0x7fffffff; | ||
| 3999 | else | 3962 | else |
| 4000 | filp->f_pos++; | 3963 | filp->f_pos++; |
| 4001 | nopos: | 3964 | nopos: |
| @@ -5789,7 +5752,7 @@ out_fail: | |||
| 5789 | } | 5752 | } |
| 5790 | 5753 | ||
| 5791 | static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | 5754 | static int prealloc_file_range(struct inode *inode, u64 start, u64 end, |
| 5792 | u64 alloc_hint, int mode) | 5755 | u64 alloc_hint, int mode, loff_t actual_len) |
| 5793 | { | 5756 | { |
| 5794 | struct btrfs_trans_handle *trans; | 5757 | struct btrfs_trans_handle *trans; |
| 5795 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5758 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| @@ -5798,6 +5761,7 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | |||
| 5798 | u64 cur_offset = start; | 5761 | u64 cur_offset = start; |
| 5799 | u64 num_bytes = end - start; | 5762 | u64 num_bytes = end - start; |
| 5800 | int ret = 0; | 5763 | int ret = 0; |
| 5764 | u64 i_size; | ||
| 5801 | 5765 | ||
| 5802 | while (num_bytes > 0) { | 5766 | while (num_bytes > 0) { |
| 5803 | alloc_size = min(num_bytes, root->fs_info->max_extent); | 5767 | alloc_size = min(num_bytes, root->fs_info->max_extent); |
| @@ -5835,9 +5799,15 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | |||
| 5835 | inode->i_ctime = CURRENT_TIME; | 5799 | inode->i_ctime = CURRENT_TIME; |
| 5836 | BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC; | 5800 | BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC; |
| 5837 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 5801 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
| 5838 | cur_offset > inode->i_size) { | 5802 | (actual_len > inode->i_size) && |
| 5839 | i_size_write(inode, cur_offset); | 5803 | (cur_offset > inode->i_size)) { |
| 5840 | btrfs_ordered_update_i_size(inode, cur_offset, NULL); | 5804 | |
| 5805 | if (cur_offset > actual_len) | ||
| 5806 | i_size = actual_len; | ||
| 5807 | else | ||
| 5808 | i_size = cur_offset; | ||
| 5809 | i_size_write(inode, i_size); | ||
| 5810 | btrfs_ordered_update_i_size(inode, i_size, NULL); | ||
| 5841 | } | 5811 | } |
| 5842 | 5812 | ||
| 5843 | ret = btrfs_update_inode(trans, root, inode); | 5813 | ret = btrfs_update_inode(trans, root, inode); |
| @@ -5930,7 +5900,7 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
| 5930 | !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { | 5900 | !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { |
| 5931 | ret = prealloc_file_range(inode, | 5901 | ret = prealloc_file_range(inode, |
| 5932 | cur_offset, last_byte, | 5902 | cur_offset, last_byte, |
| 5933 | alloc_hint, mode); | 5903 | alloc_hint, mode, offset+len); |
| 5934 | if (ret < 0) { | 5904 | if (ret < 0) { |
| 5935 | free_extent_map(em); | 5905 | free_extent_map(em); |
| 5936 | break; | 5906 | break; |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index b10a49d4bc6a..5c2a9e78a949 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -626,6 +626,8 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
| 626 | 626 | ||
| 627 | if (ordered) | 627 | if (ordered) |
| 628 | offset = entry_end(ordered); | 628 | offset = entry_end(ordered); |
| 629 | else | ||
| 630 | offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize); | ||
| 629 | 631 | ||
| 630 | mutex_lock(&tree->mutex); | 632 | mutex_lock(&tree->mutex); |
| 631 | disk_i_size = BTRFS_I(inode)->disk_i_size; | 633 | disk_i_size = BTRFS_I(inode)->disk_i_size; |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index a9728680eca8..ab7ab5318745 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -3281,8 +3281,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
| 3281 | return -ENOMEM; | 3281 | return -ENOMEM; |
| 3282 | 3282 | ||
| 3283 | path = btrfs_alloc_path(); | 3283 | path = btrfs_alloc_path(); |
| 3284 | if (!path) | 3284 | if (!path) { |
| 3285 | kfree(cluster); | ||
| 3285 | return -ENOMEM; | 3286 | return -ENOMEM; |
| 3287 | } | ||
| 3286 | 3288 | ||
| 3287 | rc->extents_found = 0; | 3289 | rc->extents_found = 0; |
| 3288 | rc->extents_skipped = 0; | 3290 | rc->extents_skipped = 0; |
| @@ -3762,7 +3764,8 @@ out: | |||
| 3762 | BTRFS_DATA_RELOC_TREE_OBJECTID); | 3764 | BTRFS_DATA_RELOC_TREE_OBJECTID); |
| 3763 | if (IS_ERR(fs_root)) | 3765 | if (IS_ERR(fs_root)) |
| 3764 | err = PTR_ERR(fs_root); | 3766 | err = PTR_ERR(fs_root); |
| 3765 | btrfs_orphan_cleanup(fs_root); | 3767 | else |
| 3768 | btrfs_orphan_cleanup(fs_root); | ||
| 3766 | } | 3769 | } |
| 3767 | return err; | 3770 | return err; |
| 3768 | } | 3771 | } |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3f9b45704fcd..8a1ea6e64575 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -66,7 +66,8 @@ enum { | |||
| 66 | Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow, | 66 | Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow, |
| 67 | Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, | 67 | Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, |
| 68 | Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, | 68 | Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, |
| 69 | Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit, | 69 | Opt_compress, Opt_compress_force, Opt_notreelog, Opt_ratio, |
| 70 | Opt_flushoncommit, | ||
| 70 | Opt_discard, Opt_err, | 71 | Opt_discard, Opt_err, |
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| @@ -82,6 +83,7 @@ static match_table_t tokens = { | |||
| 82 | {Opt_alloc_start, "alloc_start=%s"}, | 83 | {Opt_alloc_start, "alloc_start=%s"}, |
| 83 | {Opt_thread_pool, "thread_pool=%d"}, | 84 | {Opt_thread_pool, "thread_pool=%d"}, |
| 84 | {Opt_compress, "compress"}, | 85 | {Opt_compress, "compress"}, |
| 86 | {Opt_compress_force, "compress-force"}, | ||
| 85 | {Opt_ssd, "ssd"}, | 87 | {Opt_ssd, "ssd"}, |
| 86 | {Opt_ssd_spread, "ssd_spread"}, | 88 | {Opt_ssd_spread, "ssd_spread"}, |
| 87 | {Opt_nossd, "nossd"}, | 89 | {Opt_nossd, "nossd"}, |
| @@ -173,6 +175,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 173 | printk(KERN_INFO "btrfs: use compression\n"); | 175 | printk(KERN_INFO "btrfs: use compression\n"); |
| 174 | btrfs_set_opt(info->mount_opt, COMPRESS); | 176 | btrfs_set_opt(info->mount_opt, COMPRESS); |
| 175 | break; | 177 | break; |
| 178 | case Opt_compress_force: | ||
| 179 | printk(KERN_INFO "btrfs: forcing compression\n"); | ||
| 180 | btrfs_set_opt(info->mount_opt, FORCE_COMPRESS); | ||
| 181 | btrfs_set_opt(info->mount_opt, COMPRESS); | ||
| 182 | break; | ||
| 176 | case Opt_ssd: | 183 | case Opt_ssd: |
| 177 | printk(KERN_INFO "btrfs: use ssd allocation scheme\n"); | 184 | printk(KERN_INFO "btrfs: use ssd allocation scheme\n"); |
| 178 | btrfs_set_opt(info->mount_opt, SSD); | 185 | btrfs_set_opt(info->mount_opt, SSD); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 198cff28766d..41ecbb2347f2 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -1135,7 +1135,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
| 1135 | root->fs_info->avail_metadata_alloc_bits; | 1135 | root->fs_info->avail_metadata_alloc_bits; |
| 1136 | 1136 | ||
| 1137 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && | 1137 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && |
| 1138 | root->fs_info->fs_devices->rw_devices <= 4) { | 1138 | root->fs_info->fs_devices->num_devices <= 4) { |
| 1139 | printk(KERN_ERR "btrfs: unable to go below four devices " | 1139 | printk(KERN_ERR "btrfs: unable to go below four devices " |
| 1140 | "on raid10\n"); | 1140 | "on raid10\n"); |
| 1141 | ret = -EINVAL; | 1141 | ret = -EINVAL; |
| @@ -1143,7 +1143,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
| 1143 | } | 1143 | } |
| 1144 | 1144 | ||
| 1145 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && | 1145 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && |
| 1146 | root->fs_info->fs_devices->rw_devices <= 2) { | 1146 | root->fs_info->fs_devices->num_devices <= 2) { |
| 1147 | printk(KERN_ERR "btrfs: unable to go below two " | 1147 | printk(KERN_ERR "btrfs: unable to go below two " |
| 1148 | "devices on raid1\n"); | 1148 | "devices on raid1\n"); |
| 1149 | ret = -EINVAL; | 1149 | ret = -EINVAL; |
| @@ -1434,8 +1434,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1434 | return -EINVAL; | 1434 | return -EINVAL; |
| 1435 | 1435 | ||
| 1436 | bdev = open_bdev_exclusive(device_path, 0, root->fs_info->bdev_holder); | 1436 | bdev = open_bdev_exclusive(device_path, 0, root->fs_info->bdev_holder); |
| 1437 | if (!bdev) | 1437 | if (IS_ERR(bdev)) |
| 1438 | return -EIO; | 1438 | return PTR_ERR(bdev); |
| 1439 | 1439 | ||
| 1440 | if (root->fs_info->fs_devices->seeding) { | 1440 | if (root->fs_info->fs_devices->seeding) { |
| 1441 | seeding_dev = 1; | 1441 | seeding_dev = 1; |
| @@ -2538,6 +2538,11 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset) | |||
| 2538 | if (!em) | 2538 | if (!em) |
| 2539 | return 1; | 2539 | return 1; |
| 2540 | 2540 | ||
| 2541 | if (btrfs_test_opt(root, DEGRADED)) { | ||
| 2542 | free_extent_map(em); | ||
| 2543 | return 0; | ||
| 2544 | } | ||
| 2545 | |||
| 2541 | map = (struct map_lookup *)em->bdev; | 2546 | map = (struct map_lookup *)em->bdev; |
| 2542 | for (i = 0; i < map->num_stripes; i++) { | 2547 | for (i = 0; i < map->num_stripes; i++) { |
| 2543 | if (!map->stripes[i].dev->writeable) { | 2548 | if (!map->stripes[i].dev->writeable) { |
| @@ -2649,8 +2654,10 @@ again: | |||
| 2649 | em = lookup_extent_mapping(em_tree, logical, *length); | 2654 | em = lookup_extent_mapping(em_tree, logical, *length); |
| 2650 | read_unlock(&em_tree->lock); | 2655 | read_unlock(&em_tree->lock); |
| 2651 | 2656 | ||
| 2652 | if (!em && unplug_page) | 2657 | if (!em && unplug_page) { |
| 2658 | kfree(multi); | ||
| 2653 | return 0; | 2659 | return 0; |
| 2660 | } | ||
| 2654 | 2661 | ||
| 2655 | if (!em) { | 2662 | if (!em) { |
| 2656 | printk(KERN_CRIT "unable to find logical %llu len %llu\n", | 2663 | printk(KERN_CRIT "unable to find logical %llu len %llu\n", |
