Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: Btrfs: add check for changed leaves in setup_leaf_for_split Btrfs: create snapshot references in same commit as snapshot Btrfs: fix small race with delalloc flushing waitqueue's Btrfs: use add_to_page_cache_lru, use __page_cache_alloc Btrfs: fix chunk allocate size calculation Btrfs: kill max_extent mount option Btrfs: fail to mount if we have problems reading the block groups Btrfs: check btrfs_get_extent return for IS_ERR() Btrfs: handle kmalloc() failure in inode lookup ioctl Btrfs: dereferencing freed memory Btrfs: Simplify num_stripes's calculation logical for __btrfs_alloc_chunk() Btrfs: Add error handle for btrfs_search_slot() in btrfs_read_chunk_tree() Btrfs: Remove unnecessary finish_wait() in wait_current_trans() Btrfs: add NULL check for do_walk_down() Btrfs: remove duplicate include in ioctl.c Fix trivial conflict in fs/btrfs/compression.c due to slab.h include cleanups.
This commit is contained in:
commit
795d580bae
|
@ -31,7 +31,6 @@
|
|||
#include <linux/swap.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/bit_spinlock.h>
|
||||
#include <linux/pagevec.h>
|
||||
#include <linux/slab.h>
|
||||
#include "compat.h"
|
||||
#include "ctree.h"
|
||||
|
@ -446,7 +445,6 @@ static noinline int add_ra_bio_pages(struct inode *inode,
|
|||
unsigned long nr_pages = 0;
|
||||
struct extent_map *em;
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct pagevec pvec;
|
||||
struct extent_map_tree *em_tree;
|
||||
struct extent_io_tree *tree;
|
||||
u64 end;
|
||||
|
@ -462,7 +460,6 @@ static noinline int add_ra_bio_pages(struct inode *inode,
|
|||
|
||||
end_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
while (last_offset < compressed_end) {
|
||||
page_index = last_offset >> PAGE_CACHE_SHIFT;
|
||||
|
||||
|
@ -479,26 +476,17 @@ static noinline int add_ra_bio_pages(struct inode *inode,
|
|||
goto next;
|
||||
}
|
||||
|
||||
page = alloc_page(mapping_gfp_mask(mapping) & ~__GFP_FS);
|
||||
page = __page_cache_alloc(mapping_gfp_mask(mapping) &
|
||||
~__GFP_FS);
|
||||
if (!page)
|
||||
break;
|
||||
|
||||
page->index = page_index;
|
||||
/*
|
||||
* what we want to do here is call add_to_page_cache_lru,
|
||||
* but that isn't exported, so we reproduce it here
|
||||
*/
|
||||
if (add_to_page_cache(page, mapping,
|
||||
page->index, GFP_NOFS)) {
|
||||
if (add_to_page_cache_lru(page, mapping, page_index,
|
||||
GFP_NOFS)) {
|
||||
page_cache_release(page);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* open coding of lru_cache_add, also not exported */
|
||||
page_cache_get(page);
|
||||
if (!pagevec_add(&pvec, page))
|
||||
__pagevec_lru_add_file(&pvec);
|
||||
|
||||
end = last_offset + PAGE_CACHE_SIZE - 1;
|
||||
/*
|
||||
* at this point, we have a locked page in the page cache
|
||||
|
@ -552,8 +540,6 @@ static noinline int add_ra_bio_pages(struct inode *inode,
|
|||
next:
|
||||
last_offset += PAGE_CACHE_SIZE;
|
||||
}
|
||||
if (pagevec_count(&pvec))
|
||||
__pagevec_lru_add_file(&pvec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3041,6 +3041,10 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
|
|||
if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
|
||||
goto err;
|
||||
|
||||
/* the leaf has changed, it now has room. return now */
|
||||
if (btrfs_leaf_free_space(root, path->nodes[0]) >= ins_len)
|
||||
goto err;
|
||||
|
||||
if (key.type == BTRFS_EXTENT_DATA_KEY) {
|
||||
fi = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
|
|
|
@ -835,7 +835,6 @@ struct btrfs_fs_info {
|
|||
u64 last_trans_log_full_commit;
|
||||
u64 open_ioctl_trans;
|
||||
unsigned long mount_opt;
|
||||
u64 max_extent;
|
||||
u64 max_inline;
|
||||
u64 alloc_start;
|
||||
struct btrfs_transaction *running_transaction;
|
||||
|
|
|
@ -1635,7 +1635,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
atomic_set(&fs_info->async_submit_draining, 0);
|
||||
atomic_set(&fs_info->nr_async_bios, 0);
|
||||
fs_info->sb = sb;
|
||||
fs_info->max_extent = (u64)-1;
|
||||
fs_info->max_inline = 8192 * 1024;
|
||||
fs_info->metadata_ratio = 0;
|
||||
|
||||
|
@ -1923,7 +1922,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
|
||||
csum_root->track_dirty = 1;
|
||||
|
||||
btrfs_read_block_groups(extent_root);
|
||||
ret = btrfs_read_block_groups(extent_root);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "Failed to read block groups: %d\n", ret);
|
||||
goto fail_block_groups;
|
||||
}
|
||||
|
||||
fs_info->generation = generation;
|
||||
fs_info->last_trans_committed = generation;
|
||||
|
@ -1933,7 +1936,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
|
||||
"btrfs-cleaner");
|
||||
if (IS_ERR(fs_info->cleaner_kthread))
|
||||
goto fail_csum_root;
|
||||
goto fail_block_groups;
|
||||
|
||||
fs_info->transaction_kthread = kthread_run(transaction_kthread,
|
||||
tree_root,
|
||||
|
@ -2021,7 +2024,8 @@ fail_cleaner:
|
|||
filemap_write_and_wait(fs_info->btree_inode->i_mapping);
|
||||
invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
|
||||
|
||||
fail_csum_root:
|
||||
fail_block_groups:
|
||||
btrfs_free_block_groups(fs_info);
|
||||
free_extent_buffer(csum_root->node);
|
||||
free_extent_buffer(csum_root->commit_root);
|
||||
fail_dev_root:
|
||||
|
|
|
@ -2677,6 +2677,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
|
|||
|
||||
INIT_LIST_HEAD(&found->block_groups);
|
||||
init_rwsem(&found->groups_sem);
|
||||
init_waitqueue_head(&found->flush_wait);
|
||||
init_waitqueue_head(&found->allocate_wait);
|
||||
spin_lock_init(&found->lock);
|
||||
found->flags = flags;
|
||||
found->total_bytes = total_bytes;
|
||||
|
@ -2847,7 +2849,7 @@ int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,
|
|||
}
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
|
||||
BTRFS_I(inode)->reserved_extents--;
|
||||
BTRFS_I(inode)->reserved_extents -= num_items;
|
||||
BUG_ON(BTRFS_I(inode)->reserved_extents < 0);
|
||||
|
||||
if (meta_sinfo->bytes_delalloc < num_bytes) {
|
||||
|
@ -2945,12 +2947,10 @@ static void flush_delalloc(struct btrfs_root *root,
|
|||
|
||||
spin_lock(&info->lock);
|
||||
|
||||
if (!info->flushing) {
|
||||
if (!info->flushing)
|
||||
info->flushing = 1;
|
||||
init_waitqueue_head(&info->flush_wait);
|
||||
} else {
|
||||
else
|
||||
wait = true;
|
||||
}
|
||||
|
||||
spin_unlock(&info->lock);
|
||||
|
||||
|
@ -3012,7 +3012,6 @@ static int maybe_allocate_chunk(struct btrfs_root *root,
|
|||
if (!info->allocating_chunk) {
|
||||
info->force_alloc = 1;
|
||||
info->allocating_chunk = 1;
|
||||
init_waitqueue_head(&info->allocate_wait);
|
||||
} else {
|
||||
wait = true;
|
||||
}
|
||||
|
@ -3112,7 +3111,7 @@ again:
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
BTRFS_I(inode)->reserved_extents++;
|
||||
BTRFS_I(inode)->reserved_extents += num_items;
|
||||
check_force_delalloc(meta_sinfo);
|
||||
spin_unlock(&meta_sinfo->lock);
|
||||
|
||||
|
@ -4171,6 +4170,10 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
|
|||
ins->offset = 0;
|
||||
|
||||
space_info = __find_space_info(root->fs_info, data);
|
||||
if (!space_info) {
|
||||
printk(KERN_ERR "No space info for %d\n", data);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (orig_root->ref_cows || empty_size)
|
||||
allowed_chunk_alloc = 1;
|
||||
|
@ -5206,6 +5209,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
|
|||
next = btrfs_find_tree_block(root, bytenr, blocksize);
|
||||
if (!next) {
|
||||
next = btrfs_find_create_tree_block(root, bytenr, blocksize);
|
||||
if (!next)
|
||||
return -ENOMEM;
|
||||
reada = 1;
|
||||
}
|
||||
btrfs_tree_lock(next);
|
||||
|
@ -5418,7 +5423,8 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
|
|||
if (ret > 0) {
|
||||
path->slots[level]++;
|
||||
continue;
|
||||
}
|
||||
} else if (ret < 0)
|
||||
return ret;
|
||||
level = wc->level;
|
||||
}
|
||||
return 0;
|
||||
|
@ -7370,7 +7376,6 @@ static int find_first_block_group(struct btrfs_root *root,
|
|||
}
|
||||
path->slots[0]++;
|
||||
}
|
||||
ret = -ENOENT;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2678,33 +2678,20 @@ int extent_readpages(struct extent_io_tree *tree,
|
|||
{
|
||||
struct bio *bio = NULL;
|
||||
unsigned page_idx;
|
||||
struct pagevec pvec;
|
||||
unsigned long bio_flags = 0;
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
|
||||
struct page *page = list_entry(pages->prev, struct page, lru);
|
||||
|
||||
prefetchw(&page->flags);
|
||||
list_del(&page->lru);
|
||||
/*
|
||||
* what we want to do here is call add_to_page_cache_lru,
|
||||
* but that isn't exported, so we reproduce it here
|
||||
*/
|
||||
if (!add_to_page_cache(page, mapping,
|
||||
if (!add_to_page_cache_lru(page, mapping,
|
||||
page->index, GFP_KERNEL)) {
|
||||
|
||||
/* open coding of lru_cache_add, also not exported */
|
||||
page_cache_get(page);
|
||||
if (!pagevec_add(&pvec, page))
|
||||
__pagevec_lru_add_file(&pvec);
|
||||
__extent_read_full_page(tree, page, get_extent,
|
||||
&bio, 0, &bio_flags);
|
||||
}
|
||||
page_cache_release(page);
|
||||
}
|
||||
if (pagevec_count(&pvec))
|
||||
__pagevec_lru_add_file(&pvec);
|
||||
BUG_ON(!list_empty(pages));
|
||||
if (bio)
|
||||
submit_one_bio(READ, bio, 0, bio_flags);
|
||||
|
|
|
@ -797,7 +797,7 @@ static noinline int cow_file_range(struct inode *inode,
|
|||
while (disk_num_bytes > 0) {
|
||||
unsigned long op;
|
||||
|
||||
cur_alloc_size = min(disk_num_bytes, root->fs_info->max_extent);
|
||||
cur_alloc_size = disk_num_bytes;
|
||||
ret = btrfs_reserve_extent(trans, root, cur_alloc_size,
|
||||
root->sectorsize, 0, alloc_hint,
|
||||
(u64)-1, &ins, 1);
|
||||
|
@ -1228,30 +1228,9 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
|
|||
static int btrfs_split_extent_hook(struct inode *inode,
|
||||
struct extent_state *orig, u64 split)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
u64 size;
|
||||
|
||||
if (!(orig->state & EXTENT_DELALLOC))
|
||||
return 0;
|
||||
|
||||
size = orig->end - orig->start + 1;
|
||||
if (size > root->fs_info->max_extent) {
|
||||
u64 num_extents;
|
||||
u64 new_size;
|
||||
|
||||
new_size = orig->end - split + 1;
|
||||
num_extents = div64_u64(size + root->fs_info->max_extent - 1,
|
||||
root->fs_info->max_extent);
|
||||
|
||||
/*
|
||||
* if we break a large extent up then leave oustanding_extents
|
||||
* be, since we've already accounted for the large extent.
|
||||
*/
|
||||
if (div64_u64(new_size + root->fs_info->max_extent - 1,
|
||||
root->fs_info->max_extent) < num_extents)
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock(&BTRFS_I(inode)->accounting_lock);
|
||||
BTRFS_I(inode)->outstanding_extents++;
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
|
@ -1269,38 +1248,10 @@ static int btrfs_merge_extent_hook(struct inode *inode,
|
|||
struct extent_state *new,
|
||||
struct extent_state *other)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
u64 new_size, old_size;
|
||||
u64 num_extents;
|
||||
|
||||
/* not delalloc, ignore it */
|
||||
if (!(other->state & EXTENT_DELALLOC))
|
||||
return 0;
|
||||
|
||||
old_size = other->end - other->start + 1;
|
||||
if (new->start < other->start)
|
||||
new_size = other->end - new->start + 1;
|
||||
else
|
||||
new_size = new->end - other->start + 1;
|
||||
|
||||
/* we're not bigger than the max, unreserve the space and go */
|
||||
if (new_size <= root->fs_info->max_extent) {
|
||||
spin_lock(&BTRFS_I(inode)->accounting_lock);
|
||||
BTRFS_I(inode)->outstanding_extents--;
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we grew by another max_extent, just return, we want to keep that
|
||||
* reserved amount.
|
||||
*/
|
||||
num_extents = div64_u64(old_size + root->fs_info->max_extent - 1,
|
||||
root->fs_info->max_extent);
|
||||
if (div64_u64(new_size + root->fs_info->max_extent - 1,
|
||||
root->fs_info->max_extent) > num_extents)
|
||||
return 0;
|
||||
|
||||
spin_lock(&BTRFS_I(inode)->accounting_lock);
|
||||
BTRFS_I(inode)->outstanding_extents--;
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
|
@ -1329,6 +1280,7 @@ static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
|
|||
BTRFS_I(inode)->outstanding_extents++;
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
btrfs_delalloc_reserve_space(root, inode, end - start + 1);
|
||||
|
||||
spin_lock(&root->fs_info->delalloc_lock);
|
||||
BTRFS_I(inode)->delalloc_bytes += end - start + 1;
|
||||
root->fs_info->delalloc_bytes += end - start + 1;
|
||||
|
@ -1357,6 +1309,7 @@ static int btrfs_clear_bit_hook(struct inode *inode,
|
|||
|
||||
if (bits & EXTENT_DO_ACCOUNTING) {
|
||||
spin_lock(&BTRFS_I(inode)->accounting_lock);
|
||||
WARN_ON(!BTRFS_I(inode)->outstanding_extents);
|
||||
BTRFS_I(inode)->outstanding_extents--;
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
|
||||
|
@ -5385,7 +5338,6 @@ free:
|
|||
void btrfs_drop_inode(struct inode *inode)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
|
||||
if (inode->i_nlink > 0 && btrfs_root_refs(&root->root_item) == 0)
|
||||
generic_delete_inode(inode);
|
||||
else
|
||||
|
@ -5789,18 +5741,15 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
|
|||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct btrfs_key ins;
|
||||
u64 alloc_size;
|
||||
u64 cur_offset = start;
|
||||
u64 num_bytes = end - start;
|
||||
int ret = 0;
|
||||
u64 i_size;
|
||||
|
||||
while (num_bytes > 0) {
|
||||
alloc_size = min(num_bytes, root->fs_info->max_extent);
|
||||
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
|
||||
ret = btrfs_reserve_extent(trans, root, alloc_size,
|
||||
ret = btrfs_reserve_extent(trans, root, num_bytes,
|
||||
root->sectorsize, 0, alloc_hint,
|
||||
(u64)-1, &ins, 1);
|
||||
if (ret) {
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "print-tree.h"
|
||||
#include "volumes.h"
|
||||
#include "locking.h"
|
||||
#include "ctree.h"
|
||||
|
||||
/* Mask out flags that are inappropriate for the given type of inode. */
|
||||
static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
|
||||
|
@ -512,7 +511,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len,
|
|||
em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
|
||||
unlock_extent(io_tree, start, start + len - 1, GFP_NOFS);
|
||||
|
||||
if (!em)
|
||||
if (IS_ERR(em))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1212,9 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file,
|
|||
return -EPERM;
|
||||
|
||||
args = kmalloc(sizeof(*args), GFP_KERNEL);
|
||||
if (!args)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(args, argp, sizeof(*args))) {
|
||||
kfree(args);
|
||||
return -EFAULT;
|
||||
|
@ -1376,6 +1378,7 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
|
|||
sizeof(*range))) {
|
||||
ret = -EFAULT;
|
||||
kfree(range);
|
||||
goto out;
|
||||
}
|
||||
/* compression requires us to start the IO */
|
||||
if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
|
||||
|
|
|
@ -302,6 +302,7 @@ static int __btrfs_remove_ordered_extent(struct inode *inode,
|
|||
struct btrfs_ordered_extent *entry)
|
||||
{
|
||||
struct btrfs_ordered_inode_tree *tree;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct rb_node *node;
|
||||
|
||||
tree = &BTRFS_I(inode)->ordered_tree;
|
||||
|
@ -311,12 +312,13 @@ static int __btrfs_remove_ordered_extent(struct inode *inode,
|
|||
set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags);
|
||||
|
||||
spin_lock(&BTRFS_I(inode)->accounting_lock);
|
||||
WARN_ON(!BTRFS_I(inode)->outstanding_extents);
|
||||
BTRFS_I(inode)->outstanding_extents--;
|
||||
spin_unlock(&BTRFS_I(inode)->accounting_lock);
|
||||
btrfs_unreserve_metadata_for_delalloc(BTRFS_I(inode)->root,
|
||||
inode, 1);
|
||||
|
||||
spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
|
||||
spin_lock(&root->fs_info->ordered_extent_lock);
|
||||
list_del_init(&entry->root_extent_list);
|
||||
|
||||
/*
|
||||
|
@ -328,7 +330,7 @@ static int __btrfs_remove_ordered_extent(struct inode *inode,
|
|||
!mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) {
|
||||
list_del_init(&BTRFS_I(inode)->ordered_operations);
|
||||
}
|
||||
spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
|
||||
spin_unlock(&root->fs_info->ordered_extent_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -65,10 +65,9 @@ static void btrfs_put_super(struct super_block *sb)
|
|||
|
||||
enum {
|
||||
Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum,
|
||||
Opt_nodatacow, Opt_max_extent, Opt_max_inline, Opt_alloc_start,
|
||||
Opt_nobarrier, Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool,
|
||||
Opt_noacl, Opt_compress, Opt_compress_force, Opt_notreelog, Opt_ratio,
|
||||
Opt_flushoncommit,
|
||||
Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd,
|
||||
Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress,
|
||||
Opt_compress_force, Opt_notreelog, Opt_ratio, Opt_flushoncommit,
|
||||
Opt_discard, Opt_err,
|
||||
};
|
||||
|
||||
|
@ -80,7 +79,6 @@ static match_table_t tokens = {
|
|||
{Opt_nodatasum, "nodatasum"},
|
||||
{Opt_nodatacow, "nodatacow"},
|
||||
{Opt_nobarrier, "nobarrier"},
|
||||
{Opt_max_extent, "max_extent=%s"},
|
||||
{Opt_max_inline, "max_inline=%s"},
|
||||
{Opt_alloc_start, "alloc_start=%s"},
|
||||
{Opt_thread_pool, "thread_pool=%d"},
|
||||
|
@ -189,18 +187,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
info->thread_pool_size);
|
||||
}
|
||||
break;
|
||||
case Opt_max_extent:
|
||||
num = match_strdup(&args[0]);
|
||||
if (num) {
|
||||
info->max_extent = memparse(num, NULL);
|
||||
kfree(num);
|
||||
|
||||
info->max_extent = max_t(u64,
|
||||
info->max_extent, root->sectorsize);
|
||||
printk(KERN_INFO "btrfs: max_extent at %llu\n",
|
||||
(unsigned long long)info->max_extent);
|
||||
}
|
||||
break;
|
||||
case Opt_max_inline:
|
||||
num = match_strdup(&args[0]);
|
||||
if (num) {
|
||||
|
@ -530,9 +516,6 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|||
seq_puts(seq, ",nodatacow");
|
||||
if (btrfs_test_opt(root, NOBARRIER))
|
||||
seq_puts(seq, ",nobarrier");
|
||||
if (info->max_extent != (u64)-1)
|
||||
seq_printf(seq, ",max_extent=%llu",
|
||||
(unsigned long long)info->max_extent);
|
||||
if (info->max_inline != 8192 * 1024)
|
||||
seq_printf(seq, ",max_inline=%llu",
|
||||
(unsigned long long)info->max_inline);
|
||||
|
|
|
@ -148,18 +148,13 @@ static void wait_current_trans(struct btrfs_root *root)
|
|||
while (1) {
|
||||
prepare_to_wait(&root->fs_info->transaction_wait, &wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
if (cur_trans->blocked) {
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
schedule();
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
finish_wait(&root->fs_info->transaction_wait,
|
||||
&wait);
|
||||
} else {
|
||||
finish_wait(&root->fs_info->transaction_wait,
|
||||
&wait);
|
||||
if (!cur_trans->blocked)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
schedule();
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
}
|
||||
finish_wait(&root->fs_info->transaction_wait, &wait);
|
||||
put_transaction(cur_trans);
|
||||
}
|
||||
}
|
||||
|
@ -761,10 +756,17 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_root_item *new_root_item;
|
||||
struct btrfs_root *tree_root = fs_info->tree_root;
|
||||
struct btrfs_root *root = pending->root;
|
||||
struct btrfs_root *parent_root;
|
||||
struct inode *parent_inode;
|
||||
struct extent_buffer *tmp;
|
||||
struct extent_buffer *old;
|
||||
int ret;
|
||||
u64 objectid;
|
||||
int namelen;
|
||||
u64 index = 0;
|
||||
|
||||
parent_inode = pending->dentry->d_parent->d_inode;
|
||||
parent_root = BTRFS_I(parent_inode)->root;
|
||||
|
||||
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
|
||||
if (!new_root_item) {
|
||||
|
@ -775,15 +777,35 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
record_root_in_trans(trans, root);
|
||||
btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
|
||||
memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
|
||||
|
||||
key.objectid = objectid;
|
||||
/* record when the snapshot was created in key.offset */
|
||||
key.offset = trans->transid;
|
||||
btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
|
||||
|
||||
memcpy(&pending->root_key, &key, sizeof(key));
|
||||
pending->root_key.offset = (u64)-1;
|
||||
|
||||
record_root_in_trans(trans, parent_root);
|
||||
/*
|
||||
* insert the directory item
|
||||
*/
|
||||
namelen = strlen(pending->name);
|
||||
ret = btrfs_set_inode_index(parent_inode, &index);
|
||||
BUG_ON(ret);
|
||||
ret = btrfs_insert_dir_item(trans, parent_root,
|
||||
pending->name, namelen,
|
||||
parent_inode->i_ino,
|
||||
&pending->root_key, BTRFS_FT_DIR, index);
|
||||
BUG_ON(ret);
|
||||
|
||||
btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2);
|
||||
ret = btrfs_update_inode(trans, parent_root, parent_inode);
|
||||
BUG_ON(ret);
|
||||
|
||||
record_root_in_trans(trans, root);
|
||||
btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
|
||||
memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
|
||||
|
||||
old = btrfs_lock_root_node(root);
|
||||
btrfs_cow_block(trans, root, old, NULL, 0, &old);
|
||||
btrfs_set_lock_blocking(old);
|
||||
|
@ -795,59 +817,19 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
|||
btrfs_set_root_node(new_root_item, tmp);
|
||||
ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
|
||||
new_root_item);
|
||||
BUG_ON(ret);
|
||||
btrfs_tree_unlock(tmp);
|
||||
free_extent_buffer(tmp);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
key.offset = (u64)-1;
|
||||
memcpy(&pending->root_key, &key, sizeof(key));
|
||||
fail:
|
||||
kfree(new_root_item);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_pending_snapshot *pending)
|
||||
{
|
||||
int ret;
|
||||
int namelen;
|
||||
u64 index = 0;
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct inode *parent_inode;
|
||||
struct btrfs_root *parent_root;
|
||||
|
||||
parent_inode = pending->dentry->d_parent->d_inode;
|
||||
parent_root = BTRFS_I(parent_inode)->root;
|
||||
trans = btrfs_join_transaction(parent_root, 1);
|
||||
|
||||
/*
|
||||
* insert the directory item
|
||||
*/
|
||||
namelen = strlen(pending->name);
|
||||
ret = btrfs_set_inode_index(parent_inode, &index);
|
||||
ret = btrfs_insert_dir_item(trans, parent_root,
|
||||
pending->name, namelen,
|
||||
parent_inode->i_ino,
|
||||
&pending->root_key, BTRFS_FT_DIR, index);
|
||||
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2);
|
||||
ret = btrfs_update_inode(trans, parent_root, parent_inode);
|
||||
BUG_ON(ret);
|
||||
|
||||
ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root,
|
||||
pending->root_key.objectid,
|
||||
parent_root->root_key.objectid,
|
||||
parent_inode->i_ino, index, pending->name,
|
||||
namelen);
|
||||
|
||||
BUG_ON(ret);
|
||||
|
||||
fail:
|
||||
btrfs_end_transaction(trans, fs_info->fs_root);
|
||||
kfree(new_root_item);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -868,25 +850,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static noinline int finish_pending_snapshots(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_pending_snapshot *pending;
|
||||
struct list_head *head = &trans->transaction->pending_snapshots;
|
||||
int ret;
|
||||
|
||||
while (!list_empty(head)) {
|
||||
pending = list_entry(head->next,
|
||||
struct btrfs_pending_snapshot, list);
|
||||
ret = finish_pending_snapshot(fs_info, pending);
|
||||
BUG_ON(ret);
|
||||
list_del(&pending->list);
|
||||
kfree(pending->name);
|
||||
kfree(pending);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_super_roots(struct btrfs_root *root)
|
||||
{
|
||||
struct btrfs_root_item *root_item;
|
||||
|
@ -1098,9 +1061,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
|||
|
||||
btrfs_finish_extent_commit(trans, root);
|
||||
|
||||
/* do the directory inserts of any pending snapshot creations */
|
||||
finish_pending_snapshots(trans, root->fs_info);
|
||||
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
|
||||
cur_trans->commit_done = 1;
|
||||
|
|
|
@ -2199,9 +2199,9 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||
min_stripes = 2;
|
||||
}
|
||||
if (type & (BTRFS_BLOCK_GROUP_RAID1)) {
|
||||
num_stripes = min_t(u64, 2, fs_devices->rw_devices);
|
||||
if (num_stripes < 2)
|
||||
if (fs_devices->rw_devices < 2)
|
||||
return -ENOSPC;
|
||||
num_stripes = 2;
|
||||
min_stripes = 2;
|
||||
}
|
||||
if (type & (BTRFS_BLOCK_GROUP_RAID10)) {
|
||||
|
@ -2245,8 +2245,10 @@ again:
|
|||
do_div(calc_size, stripe_len);
|
||||
calc_size *= stripe_len;
|
||||
}
|
||||
|
||||
/* we don't want tiny stripes */
|
||||
calc_size = max_t(u64, min_stripe_size, calc_size);
|
||||
if (!looped)
|
||||
calc_size = max_t(u64, min_stripe_size, calc_size);
|
||||
|
||||
do_div(calc_size, stripe_len);
|
||||
calc_size *= stripe_len;
|
||||
|
@ -3390,6 +3392,8 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
|
|||
key.type = 0;
|
||||
again:
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
while (1) {
|
||||
leaf = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
|
|
Loading…
Reference in New Issue