diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/extent_io.c | 35 | ||||
| -rw-r--r-- | fs/btrfs/tree-log.c | 16 | 
2 files changed, 34 insertions, 17 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 380ced84d4b1..cceaf05aada2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3628,6 +3628,13 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)  		       TASK_UNINTERRUPTIBLE);  } +static void end_extent_buffer_writeback(struct extent_buffer *eb) +{ +	clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags); +	smp_mb__after_atomic(); +	wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK); +} +  /*   * Lock eb pages and flush the bio if we can't the locks   * @@ -3699,8 +3706,11 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb  		if (!trylock_page(p)) {  			if (!flush) { -				ret = flush_write_bio(epd); -				if (ret < 0) { +				int err; + +				err = flush_write_bio(epd); +				if (err < 0) { +					ret = err;  					failed_page_nr = i;  					goto err_unlock;  				} @@ -3715,16 +3725,23 @@ err_unlock:  	/* Unlock already locked pages */  	for (i = 0; i < failed_page_nr; i++)  		unlock_page(eb->pages[i]); +	/* +	 * Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it. +	 * Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can +	 * be made and undo everything done before. +	 */ +	btrfs_tree_lock(eb); +	spin_lock(&eb->refs_lock); +	set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); +	end_extent_buffer_writeback(eb); +	spin_unlock(&eb->refs_lock); +	percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len, +				 fs_info->dirty_metadata_batch); +	btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); +	btrfs_tree_unlock(eb);  	return ret;  } -static void end_extent_buffer_writeback(struct extent_buffer *eb) -{ -	clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags); -	smp_mb__after_atomic(); -	wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK); -} -  static void set_btree_ioerr(struct page *page)  {  	struct extent_buffer *eb = (struct extent_buffer *)page->private; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 77b6797fcac3..29b82a795522 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4984,7 +4984,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,  						      BTRFS_I(inode),  						      LOG_OTHER_INODE_ALL,  						      0, LLONG_MAX, ctx); -					iput(inode); +					btrfs_add_delayed_iput(inode);  				}  			}  			continue; @@ -4999,7 +4999,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,  		ret = btrfs_log_inode(trans, root, BTRFS_I(inode),  				      LOG_OTHER_INODE, 0, LLONG_MAX, ctx);  		if (ret) { -			iput(inode); +			btrfs_add_delayed_iput(inode);  			continue;  		} @@ -5008,7 +5008,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,  		key.offset = 0;  		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);  		if (ret < 0) { -			iput(inode); +			btrfs_add_delayed_iput(inode);  			continue;  		} @@ -5055,7 +5055,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,  			}  			path->slots[0]++;  		} -		iput(inode); +		btrfs_add_delayed_iput(inode);  	}  	return ret; @@ -5688,7 +5688,7 @@ process_leaf:  			}  			if (btrfs_inode_in_log(BTRFS_I(di_inode), trans->transid)) { -				iput(di_inode); +				btrfs_add_delayed_iput(di_inode);  				break;  			} @@ -5700,7 +5700,7 @@ process_leaf:  			if (!ret &&  			    btrfs_must_commit_transaction(trans, BTRFS_I(di_inode)))  				ret = 1; -			iput(di_inode); +			btrfs_add_delayed_iput(di_inode);  			if (ret)  				goto next_dir_inode;  			if (ctx->log_new_dentries) { @@ -5847,7 +5847,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,  			if (!ret && ctx && ctx->log_new_dentries)  				ret = log_new_dir_dentries(trans, root,  						   BTRFS_I(dir_inode), ctx); -			iput(dir_inode); +			btrfs_add_delayed_iput(dir_inode);  			if (ret)  				goto out;  		} @@ -5890,7 +5890,7 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,  			ret = btrfs_log_inode(trans, root, BTRFS_I(inode),  					      LOG_INODE_EXISTS,  					      0, LLONG_MAX, ctx); -		iput(inode); +		btrfs_add_delayed_iput(inode);  		if (ret)  			return ret;  | 

