diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/compression.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/ctree.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 12 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 15 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 59 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 112 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 10 | 
12 files changed, 90 insertions, 204 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 629880ec8ac..396039b3a8a 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -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;  } diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 8e29260cd0b..6795a713b20 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -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); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8a6518a3f04..746a7248678 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -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; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e57ded75d91..e7b8f2c89cc 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -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: diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fa2907d531a..9e23ffea7f5 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -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;  } diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 0adceb52516..d2d03684fab 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -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); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2fe494c84e6..2bfdc641d4e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -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) { diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9b3d73a0fdc..e84ef60ffe3 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -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)) { diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index ecb22ff7d1f..a127c0ebb2d 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -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;  } diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 693a664318f..1866dff0538 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -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); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c0d0e3e7bc6..2cb116099b9 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -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,79 +777,59 @@ 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); -	old = btrfs_lock_root_node(root); -	btrfs_cow_block(trans, root, old, NULL, 0, &old); -	btrfs_set_lock_blocking(old); - -	btrfs_copy_root(trans, root, old, &tmp, objectid); -	btrfs_tree_unlock(old); -	free_extent_buffer(old); - -	btrfs_set_root_node(new_root_item, tmp); -	ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, -				new_root_item); -	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); +	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); - -	if (ret) -		goto fail; +	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); + +	btrfs_copy_root(trans, root, old, &tmp, objectid); +	btrfs_tree_unlock(old); +	free_extent_buffer(old); + +	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); +  	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; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1692ec9cd7b..aa7dc36dac7 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -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];  |