From 4b844b08204ab9cd7caeb446950257ad6702717a Mon Sep 17 00:00:00 2001
From: Arvin Schnell <aschnell@suse.de>
Date: Thu, 16 Jan 2025 14:28:15 +0100
Subject: [PATCH] allow to print flags of subvolumes

---
 Documentation/btrfs-subvolume.rst |  2 ++
 cmds/subvolume-list.c             | 25 ++++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/Documentation/btrfs-subvolume.rst b/Documentation/btrfs-subvolume.rst
index eed602f9bf..4de77bafec 100644
--- a/Documentation/btrfs-subvolume.rst
+++ b/Documentation/btrfs-subvolume.rst
@@ -174,6 +174,8 @@ list [options] [-G [\+|-]<value>] [-C [+|-]<value>] [--sort=rootid,gen,ogen,path
                 (*parent* here means subvolume of which this subvolume is a snapshot).
         -R
                 print the UUID of the sent subvolume, where the subvolume is the result of a receive operation.
+        -F
+                print the flags of the subvolume.
 
         Type filtering:
 
diff --git a/cmds/subvolume-list.c b/cmds/subvolume-list.c
index 24e5c6856f..2a07a53f52 100644
--- a/cmds/subvolume-list.c
+++ b/cmds/subvolume-list.c
@@ -68,6 +68,7 @@ static const char * const cmd_subvolume_list_usage[] = {
 	OPTLINE("-u", "print the uuid of subvolumes (and snapshots)"),
 	OPTLINE("-q", "print the parent uuid of the snapshots"),
 	OPTLINE("-R", "print the uuid of the received snapshots"),
+	OPTLINE("-F", "print the flags of the subvolume"),
 	"",
 	"Type filtering:",
 	OPTLINE("-s", "list only snapshots"),
@@ -189,6 +190,7 @@ enum btrfs_list_column_enum {
 	BTRFS_LIST_PUUID,
 	BTRFS_LIST_RUUID,
 	BTRFS_LIST_UUID,
+	BTRFS_LIST_FLAGS,
 	BTRFS_LIST_PATH,
 	BTRFS_LIST_ALL,
 };
@@ -280,6 +282,11 @@ static struct {
 		.column_name	= "UUID",
 		.need_print	= 0,
 	},
+	{
+		.name		= "flags",
+		.column_name	= "Flags",
+		.need_print	= 0,
+	},
 	{
 		.name		= "path",
 		.column_name	= "Path",
@@ -1193,6 +1200,13 @@ static void print_subvolume_column(struct root_info *subv,
 			uuid_unparse(subv->ruuid, uuidparse);
 		pr_verbose(LOG_DEFAULT, "%-36s", uuidparse);
 		break;
+	case BTRFS_LIST_FLAGS:
+		if (subv->flags & BTRFS_ROOT_SUBVOL_RDONLY)
+			strcpy(tstr, "readonly");
+		else
+			strcpy(tstr, "-");
+		pr_verbose(LOG_DEFAULT, "%s", tstr);
+		break;
 	case BTRFS_LIST_PATH:
 		BUG_ON(!subv->full_path);
 		pr_verbose(LOG_DEFAULT, "%s", subv->full_path);
@@ -1321,6 +1335,12 @@ static void print_subvol_json_key(struct format_ctx *fctx,
 	case BTRFS_LIST_RUUID:
 		fmt_print(fctx, column_name, subv->ruuid);
 		break;
+	case BTRFS_LIST_FLAGS:
+		fmt_print_start_group(fctx, "flags", JSON_TYPE_ARRAY);
+		if (subv->flags & BTRFS_ROOT_SUBVOL_RDONLY)
+		    fmt_print(fctx, "flag-list-item", "readonly");
+		fmt_print_end_group(fctx, "flags");
+		break;
 	case BTRFS_LIST_PATH:
 		BUG_ON(!subv->full_path);
 		fmt_print(fctx, column_name, subv->full_path);
@@ -1602,7 +1622,7 @@ static int cmd_subvolume_list(const struct cmd_struct *cmd, int argc, char **arg
 		};
 
 		c = getopt_long(argc, argv,
-				    "acdgopqsurRG:C:t", long_options, NULL);
+				    "acdgopqsurRFG:C:t", long_options, NULL);
 		if (c < 0)
 			break;
 
@@ -1646,6 +1666,9 @@ static int cmd_subvolume_list(const struct cmd_struct *cmd, int argc, char **arg
 		case 'R':
 			btrfs_list_setup_print_column(BTRFS_LIST_RUUID);
 			break;
+		case 'F':
+			btrfs_list_setup_print_column(BTRFS_LIST_FLAGS);
+			break;
 		case 'r':
 			flags |= BTRFS_ROOT_SUBVOL_RDONLY;
 			break;