diff --git a/btrfstune.c b/btrfstune.c
index ea04159a81ce..697285ef3bf6 100644
--- a/btrfstune.c
+++ b/btrfstune.c
@@ -73,6 +73,101 @@ static int update_seeding_flag(struct btrfs_root *root, int set_flag)
 	return ret;
 }
 
+/*
+ * Return 0 for no unfinished fsid change.
+ * Return >0 for unfinished fsid change, and restore unfinished fsid/
+ * chunk_tree_id into fsid_ret/chunk_id_ret.
+ */
+static int check_unfinished_fsid_change(struct btrfs_fs_info *fs_info,
+					uuid_t fsid_ret, uuid_t chunk_id_ret)
+{
+	struct btrfs_root *tree_root = fs_info->tree_root;
+	u64 flags = btrfs_super_flags(fs_info->super_copy);
+
+	if (flags & BTRFS_SUPER_FLAG_CHANGING_FSID) {
+		memcpy(fsid_ret, fs_info->super_copy->fsid, BTRFS_FSID_SIZE);
+		read_extent_buffer(tree_root->node, chunk_id_ret,
+				btrfs_header_chunk_tree_uuid(tree_root->node),
+				BTRFS_UUID_SIZE);
+		return 1;
+	}
+	return 0;
+}
+
+static int set_metadata_uuid(struct btrfs_root *root, const char *uuid_string)
+{
+	struct btrfs_super_block *disk_super;
+	uuid_t new_fsid, unused1, unused2;
+	struct btrfs_trans_handle *trans;
+	bool new_uuid = true;
+	u64 incompat_flags;
+	bool uuid_changed;
+	u64 super_flags;
+	int ret;
+
+	disk_super = root->fs_info->super_copy;
+	super_flags = btrfs_super_flags(disk_super);
+	incompat_flags = btrfs_super_incompat_flags(disk_super);
+	uuid_changed = incompat_flags & BTRFS_FEATURE_INCOMPAT_METADATA_UUID;
+
+	if (super_flags & BTRFS_SUPER_FLAG_SEEDING) {
+		fprintf(stderr, "Cannot set metadata UUID on a seed device\n");
+		return 1;
+	}
+
+	if (check_unfinished_fsid_change(root->fs_info, unused1, unused2)) {
+		fprintf(stderr, "UUID rewrite in progress, cannot change "
+			"fsid\n");
+		return 1;
+	}
+
+	if (uuid_string)
+		uuid_parse(uuid_string, new_fsid);
+	else
+		uuid_generate(new_fsid);
+
+	new_uuid = (memcmp(new_fsid, disk_super->fsid, BTRFS_FSID_SIZE) != 0);
+
+	if (new_uuid && uuid_changed && memcmp(disk_super->metadata_uuid,
+					       new_fsid, BTRFS_FSID_SIZE) == 0) {
+		/*
+		 * Changing fsid to be the same as metadata uuid, so just
+		 * disable the flag
+		 */
+		memcpy(disk_super->fsid, &new_fsid, BTRFS_FSID_SIZE);
+		incompat_flags &= ~BTRFS_FEATURE_INCOMPAT_METADATA_UUID;
+		btrfs_set_super_incompat_flags(disk_super, incompat_flags);
+		memset(disk_super->metadata_uuid, 0, BTRFS_FSID_SIZE);
+	} else if (new_uuid && uuid_changed && memcmp(disk_super->metadata_uuid,
+						new_fsid, BTRFS_FSID_SIZE)) {
+		/*
+		 * Changing fsid on an already changed FS, in this case we
+		 * only change the fsid and don't touch metadata uuid as it
+		 * has already the correct value
+		 */
+		memcpy(disk_super->fsid, &new_fsid, BTRFS_FSID_SIZE);
+	} else if (new_uuid && !uuid_changed) {
+		/*
+		 * First time changing the fsid, copy the fsid to
+		 * metadata_uuid
+		 */
+		incompat_flags |= BTRFS_FEATURE_INCOMPAT_METADATA_UUID;
+		btrfs_set_super_incompat_flags(disk_super, incompat_flags);
+		memcpy(disk_super->metadata_uuid, disk_super->fsid,
+		       BTRFS_FSID_SIZE);
+		memcpy(disk_super->fsid, &new_fsid, BTRFS_FSID_SIZE);
+	} else {
+		/* Setting the same fsid as current NOOP */
+		return 0;
+	}
+
+	trans = btrfs_start_transaction(root, 1);
+	BUG_ON(IS_ERR(trans));
+	ret = btrfs_commit_transaction(trans, root);
+
+	return ret;
+}
+
 static int set_super_incompat_flags(struct btrfs_root *root, u64 flags)
 {
 	struct btrfs_trans_handle *trans;
@@ -268,26 +363,6 @@ static int change_fsid_done(struct btrfs_fs_info *fs_info)
 	return write_all_supers(fs_info);
 }
 
-/*
- * Return 0 for no unfinished fsid change.
- * Return >0 for unfinished fsid change, and restore unfinished fsid/
- * chunk_tree_id into fsid_ret/chunk_id_ret.
- */
-static int check_unfinished_fsid_change(struct btrfs_fs_info *fs_info,
-					uuid_t fsid_ret, uuid_t chunk_id_ret)
-{
-	struct btrfs_root *tree_root = fs_info->tree_root;
-	u64 flags = btrfs_super_flags(fs_info->super_copy);
-
-	if (flags & BTRFS_SUPER_FLAG_CHANGING_FSID) {
-		memcpy(fsid_ret, fs_info->super_copy->fsid, BTRFS_FSID_SIZE);
-		read_extent_buffer(tree_root->node, chunk_id_ret,
-				btrfs_header_chunk_tree_uuid(tree_root->node),
-				BTRFS_UUID_SIZE);
-		return 1;
-	}
-	return 0;
-}
 
 /*
  * Change fsid of a given fs.
@@ -381,8 +456,10 @@ static void print_usage(void)
 	printf("\t-x \t\tenable skinny metadata extent refs\n");
 	printf("\t-n \t\tenable no-holes feature (more efficient sparse file representation)\n");
 	printf("\t-f \t\tforce to do dangerous operation, make sure that you are aware of the dangers\n");
-	printf("\t-u \t\tchange fsid, use a random one\n");
-	printf("\t-U UUID\t\tchange fsid to UUID\n");
+	printf("\t-u \t\trewrite fsid, use a random one\n");
+	printf("\t-U UUID\t\trewrite fsid to UUID\n");
+	printf("\t-m \t\tChange only user-facing uuid (lighterweight than -u|-U\n");
+	printf("\t-M UUID\t\tchange fsid to UUID\n");
 }
 
 int main(int argc, char *argv[])
@@ -394,6 +471,7 @@ int main(int argc, char *argv[])
 	int seeding_flag = 0;
 	u64 seeding_value = 0;
 	int random_fsid = 0;
+	int change_metadata_uuid = 0;
 	char *new_fsid_str = NULL;
 	int ret;
 	u64 super_flags = 0;
@@ -404,7 +482,7 @@ int main(int argc, char *argv[])
 			{ "help", no_argument, NULL, GETOPT_VAL_HELP},
 			{ NULL, 0, NULL, 0 }
 		};
-		int c = getopt_long(argc, argv, "S:rxfuU:n", long_options, NULL);
+		int c = getopt_long(argc, argv, "S:rxfuU:nmM:", long_options, NULL);
 
 		if (c < 0)
 			break;
@@ -433,6 +511,15 @@ int main(int argc, char *argv[])
 			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
 			random_fsid = 1;
 			break;
+		case 'M':
+			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
+			change_metadata_uuid = 1;
+			new_fsid_str = optarg;
+			break;
+		case 'm':
+			ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
+			change_metadata_uuid = 1;
+			break;
 		case GETOPT_VAL_HELP:
 		default:
 			print_usage();
@@ -451,7 +538,8 @@ int main(int argc, char *argv[])
 		error("random fsid can't be used with specified fsid");
 		return 1;
 	}
-	if (!super_flags && !seeding_flag && !(random_fsid || new_fsid_str)) {
+	if (!super_flags && !seeding_flag && !(random_fsid || new_fsid_str) &&
+	    !change_metadata_uuid) {
 		error("at least one option should be specified");
 		print_usage();
 		return 1;
@@ -497,6 +585,12 @@ int main(int argc, char *argv[])
 	}
 
 	if (seeding_flag) {
+		if (btrfs_fs_incompat(root->fs_info, METADATA_UUID)) {
+			fprintf(stderr, "SEED flag cannot be changed on a metadata-uuid changed fs\n");
+			ret = 1;
+			goto out;
+		}
+
 		if (!seeding_value && !force) {
 			warning(
 "this is dangerous, clearing the seeding flag may cause the derived device not to be mountable!");
@@ -521,7 +615,31 @@ int main(int argc, char *argv[])
 		total++;
 	}
 
-	if (random_fsid || new_fsid_str) {
+	if (change_metadata_uuid) {
+		if (seeding_flag) {
+			fprintf(stderr, "Not allowed to set both seeding flag and uuid metadata\n");
+			ret = 1;
+			goto out;
+		}
+
+		if (new_fsid_str)
+			ret = set_metadata_uuid(root, new_fsid_str);
+		else
+			ret = set_metadata_uuid(root, NULL);
+
+		if (!ret)
+			success++;
+		total++;
+	}
+
+	if (random_fsid || (new_fsid_str && !change_metadata_uuid)) {
+		if (btrfs_fs_incompat(root->fs_info, METADATA_UUID)) {
+			fprintf(stderr, "Cannot rewrite fsid while METADATA_UUID flag is active."
+				"Ensure fsid and metadata_uuid match before retrying.\n");
+			ret = 1;
+			goto out;
+		}
+
 		if (!force) {
 			warning(
 	"it's highly recommended to run 'btrfs check' before this operation");
