diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/ctree.c | 52 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 4 | 
4 files changed, 47 insertions, 17 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index a4cb4b642987..da519c1b6ad0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -682,18 +682,30 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,  	u64 search_start;  	int ret; -	if (test_bit(BTRFS_ROOT_DELETING, &root->state)) -		btrfs_err(fs_info, -			"COW'ing blocks on a fs root that's being dropped"); - -	if (trans->transaction != fs_info->running_transaction) -		WARN(1, KERN_CRIT "trans %llu running %llu\n", -		       trans->transid, -		       fs_info->running_transaction->transid); +	if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) { +		btrfs_abort_transaction(trans, -EUCLEAN); +		btrfs_crit(fs_info, +		   "attempt to COW block %llu on root %llu that is being deleted", +			   buf->start, btrfs_root_id(root)); +		return -EUCLEAN; +	} -	if (trans->transid != fs_info->generation) -		WARN(1, KERN_CRIT "trans %llu running %llu\n", -		       trans->transid, fs_info->generation); +	/* +	 * COWing must happen through a running transaction, which always +	 * matches the current fs generation (it's a transaction with a state +	 * less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs +	 * into error state to prevent the commit of any transaction. +	 */ +	if (unlikely(trans->transaction != fs_info->running_transaction || +		     trans->transid != fs_info->generation)) { +		btrfs_abort_transaction(trans, -EUCLEAN); +		btrfs_crit(fs_info, +"unexpected transaction when attempting to COW block %llu on root %llu, transaction %llu running transaction %llu fs generation %llu", +			   buf->start, btrfs_root_id(root), trans->transid, +			   fs_info->running_transaction->transid, +			   fs_info->generation); +		return -EUCLEAN; +	}  	if (!should_cow_block(trans, root, buf)) {  		*cow_ret = buf; @@ -805,8 +817,22 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,  	int progress_passed = 0;  	struct btrfs_disk_key disk_key; -	WARN_ON(trans->transaction != fs_info->running_transaction); -	WARN_ON(trans->transid != fs_info->generation); +	/* +	 * COWing must happen through a running transaction, which always +	 * matches the current fs generation (it's a transaction with a state +	 * less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs +	 * into error state to prevent the commit of any transaction. +	 */ +	if (unlikely(trans->transaction != fs_info->running_transaction || +		     trans->transid != fs_info->generation)) { +		btrfs_abort_transaction(trans, -EUCLEAN); +		btrfs_crit(fs_info, +"unexpected transaction when attempting to reallocate parent %llu for root %llu, transaction %llu running transaction %llu fs generation %llu", +			   parent->start, btrfs_root_id(root), trans->transid, +			   fs_info->running_transaction->transid, +			   fs_info->generation); +		return -EUCLEAN; +	}  	parent_nritems = btrfs_header_nritems(parent);  	blocksize = fs_info->nodesize; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 75ab766fe156..8e7d03bc1b56 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2978,7 +2978,7 @@ static void get_block_group_info(struct list_head *groups_list,  static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info,  				   void __user *arg)  { -	struct btrfs_ioctl_space_args space_args; +	struct btrfs_ioctl_space_args space_args = { 0 };  	struct btrfs_ioctl_space_info space;  	struct btrfs_ioctl_space_info *dest;  	struct btrfs_ioctl_space_info *dest_orig; @@ -4338,7 +4338,7 @@ static int _btrfs_ioctl_send(struct inode *inode, void __user *argp, bool compat  	if (compat) {  #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) -		struct btrfs_ioctl_send_args_32 args32; +		struct btrfs_ioctl_send_args_32 args32 = { 0 };  		ret = copy_from_user(&args32, argp, sizeof(args32));  		if (ret) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1a093ec0f7e3..f49e597e197f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -954,6 +954,10 @@ static int btrfs_parse_subvol_options(const char *options, char **subvol_name,  			*subvol_objectid = subvolid;  			break; +		case Opt_err: +			btrfs_err(NULL, "unrecognized mount option '%s'", p); +			error = -EINVAL; +			goto out;  		default:  			break;  		} diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 6b309f8a99a8..93869cda6af9 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h @@ -219,8 +219,8 @@ do {								\  			(errno))) {					\  			/* Stack trace printed. */			\  		} else {						\ -			btrfs_debug((trans)->fs_info,			\ -				    "Transaction aborted (error %d)", \ +			btrfs_err((trans)->fs_info,			\ +				  "Transaction aborted (error %d)",	\  				  (errno));			\  		}						\  	}							\  | 
