diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 41 | 
1 files changed, 29 insertions, 12 deletions
| diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c276ac9a0ec..2c679149363 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -18,6 +18,7 @@  #include <linux/sched.h>  #include <linux/slab.h> +#include <linux/blkdev.h>  #include <linux/list_sort.h>  #include "ctree.h"  #include "transaction.h" @@ -279,11 +280,23 @@ static int process_one_buffer(struct btrfs_root *log,  {  	int ret = 0; +	/* +	 * If this fs is mixed then we need to be able to process the leaves to +	 * pin down any logged extents, so we have to read the block. +	 */ +	if (btrfs_fs_incompat(log->fs_info, MIXED_GROUPS)) { +		ret = btrfs_read_buffer(eb, gen); +		if (ret) +			return ret; +	} +  	if (wc->pin)  		ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root,  						      eb->start, eb->len);  	if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) { +		if (wc->pin && btrfs_header_level(eb) == 0) +			ret = btrfs_exclude_logged_extents(log, eb);  		if (wc->write)  			btrfs_write_tree_block(eb);  		if (wc->wait) @@ -2016,13 +2029,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,  					     eb, i, &key);  			if (ret)  				break; -		} else if (key.type == BTRFS_INODE_REF_KEY) { -			ret = add_inode_ref(wc->trans, root, log, path, -					    eb, i, &key); -			if (ret && ret != -ENOENT) -				break; -			ret = 0; -		} else if (key.type == BTRFS_INODE_EXTREF_KEY) { +		} else if (key.type == BTRFS_INODE_REF_KEY || +			   key.type == BTRFS_INODE_EXTREF_KEY) {  			ret = add_inode_ref(wc->trans, root, log, path,  					    eb, i, &key);  			if (ret && ret != -ENOENT) @@ -2358,6 +2366,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  	struct btrfs_root *log = root->log_root;  	struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;  	unsigned long log_transid = 0; +	struct blk_plug plug;  	mutex_lock(&root->log_mutex);  	log_transid = root->log_transid; @@ -2401,8 +2410,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  	/* we start IO on  all the marked extents here, but we don't actually  	 * wait for them until later.  	 */ +	blk_start_plug(&plug);  	ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark);  	if (ret) { +		blk_finish_plug(&plug);  		btrfs_abort_transaction(trans, root, ret);  		btrfs_free_logged_extents(log, log_transid);  		mutex_unlock(&root->log_mutex); @@ -2437,6 +2448,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  	}  	if (ret) { +		blk_finish_plug(&plug);  		if (ret != -ENOSPC) {  			btrfs_abort_transaction(trans, root, ret);  			mutex_unlock(&log_root_tree->log_mutex); @@ -2452,6 +2464,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  	index2 = log_root_tree->log_transid % 2;  	if (atomic_read(&log_root_tree->log_commit[index2])) { +		blk_finish_plug(&plug);  		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);  		wait_log_commit(trans, log_root_tree,  				log_root_tree->log_transid); @@ -2474,6 +2487,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  	 * check the full commit flag again  	 */  	if (root->fs_info->last_trans_log_full_commit == trans->transid) { +		blk_finish_plug(&plug);  		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);  		btrfs_free_logged_extents(log, log_transid);  		mutex_unlock(&log_root_tree->log_mutex); @@ -2481,9 +2495,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  		goto out_wake_log_root;  	} -	ret = btrfs_write_and_wait_marked_extents(log_root_tree, -				&log_root_tree->dirty_log_pages, -				EXTENT_DIRTY | EXTENT_NEW); +	ret = btrfs_write_marked_extents(log_root_tree, +					 &log_root_tree->dirty_log_pages, +					 EXTENT_DIRTY | EXTENT_NEW); +	blk_finish_plug(&plug);  	if (ret) {  		btrfs_abort_transaction(trans, root, ret);  		btrfs_free_logged_extents(log, log_transid); @@ -2491,6 +2506,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  		goto out_wake_log_root;  	}  	btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); +	btrfs_wait_marked_extents(log_root_tree, +				  &log_root_tree->dirty_log_pages, +				  EXTENT_NEW | EXTENT_DIRTY);  	btrfs_wait_logged_extents(log, log_transid);  	btrfs_set_super_log_root(root->fs_info->super_for_commit, @@ -4016,8 +4034,7 @@ again:  		if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID)  			break; -		log = btrfs_read_fs_root_no_radix(log_root_tree, -						  &found_key); +		log = btrfs_read_fs_root(log_root_tree, &found_key);  		if (IS_ERR(log)) {  			ret = PTR_ERR(log);  			btrfs_error(fs_info, ret, | 
