diff --git a/tune/main.c b/tune/main.c
index c49c24298187..fe814fccc675 100644
--- a/tune/main.c
+++ b/tune/main.c
@@ -130,12 +130,54 @@ static const struct cmd_struct tune_cmd = {
 	.usagestr = tune_usage
 };
 
+enum btrfstune_group_enum {
+	/* Extent/block group tree feature. */
+	EXTENT_TREE,
+
+	/* V1/v2 free space cache. */
+	SPACE_CACHE,
+
+	/* Metadata UUID. */
+	METADATA_UUID,
+
+	/* FSID change. */
+	FSID_CHANGE,
+
+	/* Seed device. */
+	SEED,
+
+	/* Csum conversion */
+	CSUM_CHANGE,
+
+	/*
+	 * Legacy features (which later become default), including:
+	 * - no-holes
+	 * - extref
+	 * - skinny-metadata
+	 */
+	LEGACY,
+
+	BTRFSTUNE_NR_GROUPS,
+};
+
+static bool btrfstune_cmd_groups[BTRFSTUNE_NR_GROUPS] = { 0 };
+
+static unsigned int btrfstune_count_set_groups()
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < BTRFSTUNE_NR_GROUPS; i++) {
+		if (btrfstune_cmd_groups[i])
+			ret++;
+	}
+	return ret;
+}
+
 int BOX_MAIN(btrfstune)(int argc, char *argv[])
 {
 	struct btrfs_root *root;
 	unsigned ctree_flags = OPEN_CTREE_WRITES;
-	int success = 0;
-	int total = 0;
 	int seeding_flag = 0;
 	u64 seeding_value = 0;
 	int random_fsid = 0;
@@ -177,15 +219,19 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 		case 'S':
 			seeding_flag = 1;
 			seeding_value = arg_strtou64(optarg);
+			btrfstune_cmd_groups[SEED] = true;
 			break;
 		case 'r':
 			super_flags |= BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF;
+			btrfstune_cmd_groups[LEGACY] = true;
 			break;
 		case 'x':
 			super_flags |= BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA;
+			btrfstune_cmd_groups[LEGACY] = true;
 			break;
 		case 'n':
 			super_flags |= BTRFS_FEATURE_INCOMPAT_NO_HOLES;
+			btrfstune_cmd_groups[LEGACY] = true;
 			break;
 		case 'f':
 			force = 1;
@@ -193,28 +239,35 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 		case 'U':
 			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
 			new_fsid_str = optarg;
+			btrfstune_cmd_groups[FSID_CHANGE] = true;
 			break;
 		case 'u':
 			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
 			random_fsid = 1;
+			btrfstune_cmd_groups[FSID_CHANGE] = true;
 			break;
 		case 'M':
 			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
 			change_metadata_uuid = 1;
 			new_fsid_str = optarg;
+			btrfstune_cmd_groups[METADATA_UUID] = true;
 			break;
 		case 'm':
 			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
 			change_metadata_uuid = 1;
+			btrfstune_cmd_groups[METADATA_UUID] = true;
 			break;
 		case GETOPT_VAL_ENABLE_BLOCK_GROUP_TREE:
 			to_bg_tree = true;
+			btrfstune_cmd_groups[EXTENT_TREE] = true;
 			break;
 		case GETOPT_VAL_DISABLE_BLOCK_GROUP_TREE:
 			to_extent_tree = true;
+			btrfstune_cmd_groups[EXTENT_TREE] = true;
 			break;
 		case GETOPT_VAL_ENABLE_FREE_SPACE_TREE:
 			to_fst = true;
+			btrfstune_cmd_groups[SPACE_CACHE] = true;
 			break;
 #if EXPERIMENTAL
 		case GETOPT_VAL_CSUM:
@@ -222,6 +275,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 				"Switching checksums is experimental, do not use for valuable data!");
 			ctree_flags |= OPEN_CTREE_SKIP_CSUM_CHECK;
 			csum_type = parse_csum_type(optarg);
+			btrfstune_cmd_groups[CSUM_CHANGE] = true;
 			break;
 #endif
 		case GETOPT_VAL_HELP:
@@ -237,20 +291,23 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 		goto free_out;
 	}
 
-	if (random_fsid && new_fsid_str) {
-		error("random fsid can't be used with specified fsid");
-		ret = 1;
-		goto free_out;
-	}
-	if (!super_flags && !seeding_flag && !(random_fsid || new_fsid_str) &&
-	    !change_metadata_uuid && csum_type == -1 && !to_bg_tree &&
-	    !to_extent_tree && !to_fst) {
+	if (btrfstune_count_set_groups() == 0) {
 		error("at least one option should be specified");
 		usage(&tune_cmd, 1);
 		ret = 1;
 		goto free_out;
 	}
-
+	if (btrfstune_count_set_groups() > 1) {
+		error("too many conflicting options specified");
+		usage(&tune_cmd, 1);
+		ret = 1;
+		goto free_out;
+	}
+	if (random_fsid && new_fsid_str) {
+		error("random fsid can't be used with specified fsid");
+		ret = 1;
+		goto free_out;
+	}
 	if (new_fsid_str) {
 		uuid_t tmp;
 
@@ -319,17 +376,17 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
  	if (to_bg_tree) {
 		if (to_extent_tree) {
 			error("option --convert-to-block-group-tree conflicts with --convert-from-block-group-tree");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 		if (btrfs_fs_compat_ro(root->fs_info, BLOCK_GROUP_TREE)) {
 			error("the filesystem already has block group tree feature");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 		if (!btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE_VALID)) {
 			error("the filesystem doesn't have space cache v2, needs to be mounted with \"-o space_cache=v2\" first");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 		ret = convert_to_bg_tree(root->fs_info);
@@ -342,7 +399,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 	if (to_fst) {
 		if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE_VALID)) {
 			error("filesystem already has free-space-tree feature");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 		ret = convert_to_fst(root->fs_info);
@@ -353,12 +410,12 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 	if (to_extent_tree) {
 		if (to_bg_tree) {
 			error("option --convert-to-block-group-tree conflicts with --convert-from-block-group-tree");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 		if (!btrfs_fs_compat_ro(root->fs_info, BLOCK_GROUP_TREE)) {
 			error("filesystem doesn't have block-group-tree feature");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 		ret = convert_to_extent_tree(root->fs_info);
@@ -371,7 +428,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 	if (seeding_flag) {
 		if (btrfs_fs_incompat(root->fs_info, METADATA_UUID)) {
 			error("SEED flag cannot be changed on a metadata-uuid changed fs");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 
@@ -381,34 +438,30 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 			ret = ask_user("We are going to clear the seeding flag, are you sure?");
 			if (!ret) {
 				error("clear seeding flag canceled");
-				ret = 1;
+				ret = -EINVAL;
 				goto out;
 			}
 		}
 
 		ret = update_seeding_flag(root, device, seeding_value, force);
-		if (!ret)
-			success++;
-		total++;
+		goto out;
 	}
 
 	if (super_flags) {
 		ret = set_super_incompat_flags(root, super_flags);
-		if (!ret)
-			success++;
-		total++;
+		goto out;
 	}
 
 	if (csum_type != -1) {
-		/* TODO: check conflicting flags */
 		pr_verbose(LOG_DEFAULT, "Proceed to switch checksums\n");
 		ret = btrfs_change_csum_type(root->fs_info, csum_type);
+		goto out;
 	}
 
 	if (change_metadata_uuid) {
 		if (seeding_flag) {
 			error("not allowed to set both seeding flag and uuid metadata");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 
@@ -417,10 +470,8 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 		else
 			ret = set_metadata_uuid(root, NULL);
 
-		if (!ret)
-			success++;
-		total++;
 		btrfs_register_all_devices();
+		goto out;
 	}
 
 	if (random_fsid || (new_fsid_str && !change_metadata_uuid)) {
@@ -429,7 +480,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 			error(
 		"Cannot rewrite fsid while METADATA_UUID flag is active. \n"
 		"Ensure fsid and metadata_uuid match before retrying.");
-			ret = 1;
+			ret = -EINVAL;
 			goto out;
 		}
 
@@ -441,24 +492,19 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
 			ret = ask_user("We are going to change UUID, are your sure?");
 			if (!ret) {
 				error("UUID change canceled");
-				ret = 1;
+				ret = -EINVAL;
 				goto out;
 			}
 		}
 		ret = change_uuid(root->fs_info, new_fsid_str);
-		if (!ret)
-			success++;
-		total++;
+		goto out;
 	}
-
-	if (success == total) {
-		ret = 0;
-	} else {
+out:
+	if (ret < 0) {
 		root->fs_info->readonly = 1;
 		ret = 1;
 		error("btrfstune failed");
 	}
-out:
 	close_ctree(root);
 	btrfs_close_all_devices();
 
