linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Anand jain <Anand.Jain@oracle.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 5/5] Btrfs-progs: Add -x option to btrfs subvol list to display snapshots in tree format
Date: Sat, 15 Dec 2012 19:52:08 +0800	[thread overview]
Message-ID: <1355572328-32281-6-git-send-email-Anand.Jain@oracle.com> (raw)
In-Reply-To: <1355572328-32281-1-git-send-email-Anand.Jain@oracle.com>

From: Anand Jain <anand.jain@oracle.com>

This will add new option -x to the btrfs subvol list
sub-command to display the snapshots under its parent subvol
with appropriate indentation.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 btrfs-list.c     |  135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cmds-subvolume.c |    6 ++-
 man/btrfs.8.in   |    4 +-
 3 files changed, 143 insertions(+), 2 deletions(-)

diff --git a/btrfs-list.c b/btrfs-list.c
index 571efd0..43c279c 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -150,6 +150,11 @@ struct {
 	},
 };
 
+struct str_print {
+	char path[BTRFS_PATH_NAME_MAX];
+	char otime[256];
+};
+
 static btrfs_list_filter_func all_filter_funcs[];
 static btrfs_list_comp_func all_comp_funcs[];
 
@@ -1414,6 +1419,133 @@ static void print_single_volume_info_default(struct root_info *subv)
 	printf("\n");
 }
 
+static void print_single_volume_info_tree(struct root_info *subv,
+	struct str_print *sp)
+{
+	char tstr[256];
+
+	sprintf(sp->path, "%s", subv->full_path);
+	if (subv->otime)
+		strftime(tstr, 256, "%X %d-%m-%Y", localtime(&subv->otime));
+	else
+		strcpy(tstr, "-");
+	sprintf(sp->otime, "%s", tstr);
+}
+
+int snapshot_is_orphan(struct root_lookup *root_tree, void *uuid)
+{
+	struct rb_node *n;
+	struct root_info *entry;
+
+	n = rb_first(&root_tree->root);
+	while (n) {
+		entry = rb_entry(n, struct root_info, sort_node);
+		if ( ! uuid_compare(entry->uuid, uuid)) {
+			return 0;
+		}
+		n = rb_next(n);
+	}
+	return 1;
+}
+
+void * print_snapshots_of(struct root_lookup *root_tree, void *uuid,
+	int indent, struct str_print *sp)
+{
+	struct rb_node *n;
+	struct root_info *entry;
+	int i = indent;
+	char ispace[BTRFS_PATH_NAME_MAX + 256];
+	char *ispacep = ispace;
+
+	n = rb_first(&root_tree->root);
+	while (n) {
+		entry = rb_entry(n, struct root_info, sort_node);
+		if ( ! uuid_compare(entry->puuid, uuid)) {
+			while(i--) {
+				sprintf(ispacep,"%s"," ");
+				ispacep++;
+			}
+			print_single_volume_info_tree(entry, sp);
+			strcat(ispace, sp->path);
+			strcpy(sp->path, ispace);
+			sp++;
+			sp = (struct str_print *) print_snapshots_of(root_tree,
+				entry->uuid, indent+1, sp);
+		}
+		i = indent;
+		n = rb_next(n);
+	}
+	return sp;
+}
+
+void print_subvol_tree(struct root_lookup *root_tree)
+{
+	struct rb_node *n;
+	struct root_info *entry;
+	int listlen = 0;
+	int max_slen = 0;
+	int pad;
+	int stmp;
+	int i;
+	struct str_print *head;
+	struct str_print *cur;
+
+	n = rb_first(&root_tree->root);
+	while (n) {
+		listlen++;
+		n = rb_next(n);
+	}
+	head = (struct str_print *) malloc(sizeof(struct str_print)*listlen);
+	memset(head, 0, sizeof(struct str_print)*listlen);
+
+	cur = head;
+	n = rb_first(&root_tree->root);
+	while (n) {
+		entry = rb_entry(n, struct root_info, sort_node);
+		if ( uuid_is_null(entry->puuid)) {
+			print_single_volume_info_tree(entry, cur);
+			cur++;
+			cur = (struct str_print *) print_snapshots_of(root_tree,
+					entry->uuid, 1, cur);
+		}
+		n = rb_next(n);
+	}
+	n = rb_first(&root_tree->root);
+	while (n) {
+		entry = rb_entry(n, struct root_info, sort_node);
+		if ( !uuid_is_null(entry->puuid)
+			&& snapshot_is_orphan(root_tree, entry->puuid)) {
+			print_single_volume_info_tree(entry, cur);
+			cur++;
+			cur = (struct str_print *) print_snapshots_of(root_tree,
+					entry->uuid, 1, cur);
+		}
+		n = rb_next(n);
+	}
+	//BUG_ON(cur != (head + (sizeof(struct str_print) * listlen)));
+
+	cur = head;
+	for (i=0; i < listlen; i++) {
+		stmp = strlen(cur->path);
+		if (stmp > max_slen)
+			max_slen = stmp;
+		cur++;
+	}
+
+	cur = head;
+	for (i=0; i < listlen; i++) {
+		printf("%s", cur->path);
+		pad = max_slen - strlen(cur->path) + 1;
+		while(pad--)
+			printf("%s"," ");
+		printf("%s"," ");
+		printf("%s", cur->otime);
+		printf("\n");
+		cur++;
+	}
+	free(head);
+}
+
 static void print_all_volume_info_tab_head()
 {
 	int i;
@@ -1467,6 +1599,9 @@ static void print_all_volume_info(struct root_lookup *sorted_tree,
 			n = rb_next(n);
 		}
 		break;
+	case 2: // tree format
+		print_subvol_tree(sorted_tree);
+		break;
 	default:
 		printf("ERROR: default switch print_all_volume_info\n");
 		return;
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index 411a5de..4f2704f 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -281,6 +281,7 @@ static const char * const cmd_subvol_list_usage[] = {
 	"-u           print the uuid of subvolumes (and snapshots)",
 	"-q           print the parent uuid of snapshots",
 	"-t           print the result as a table",
+	"-x           print the result as a tree",
 	"-s           list snapshots only in the filesystem",
 	"-r           list readonly subvolumes (including snapshots)",
 	"-g [+|-]value",
@@ -319,7 +320,7 @@ static int cmd_subvol_list(int argc, char **argv)
 	optind = 1;
 	while(1) {
 		c = getopt_long(argc, argv,
-				    "apsuqrg:c:t", long_options, NULL);
+				    "apsuqrg:c:tx", long_options, NULL);
 		if (c < 0)
 			break;
 
@@ -333,6 +334,9 @@ static int cmd_subvol_list(int argc, char **argv)
 		case 't':
 			layout = 1;
 			break;
+		case 'x':
+			layout = 2;
+			break;
 		case 's':
 			btrfs_list_setup_filter(&filter_set,
 						BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
diff --git a/man/btrfs.8.in b/man/btrfs.8.in
index 9222580..1bb0415 100644
--- a/man/btrfs.8.in
+++ b/man/btrfs.8.in
@@ -11,7 +11,7 @@ btrfs \- control a btrfs filesystem
 .PP
 \fBbtrfs\fP \fBsubvolume create\fP\fI [<dest>/]<name>\fP
 .PP
-\fBbtrfs\fP \fBsubvolume list\fP\fI [-aprts] [-g [+|-]value] [-c [+|-]value] [--rootid=rootid,gen,ogen,path] <path>\fP
+\fBbtrfs\fP \fBsubvolume list\fP\fI [-aprtxs] [-g [+|-]value] [-c [+|-]value] [--rootid=rootid,gen,ogen,path] <path>\fP
 .PP
 \fBbtrfs\fP \fBsubvolume set-default\fP\fI <id> <path>\fP
 .PP
@@ -124,6 +124,8 @@ and top level. The parent's ID may be used at mount time via the
 
 \fB-t\fP print the result as a table.
 
+\fB-x\fP print the result as a tree.
+
 \fB-a\fP print all the subvolumes in the filesystem.
 
 \fB-r\fP only readonly subvolumes in the filesystem wille be listed.
-- 
1.7.1


      parent reply	other threads:[~2012-12-15 11:46 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-15 11:52 [PATCH 0/5] add tree format display for btrfs subvol list subcommand Anand jain
2012-12-15 11:52 ` [PATCH 1/5] Btrfs-progs: add parent uuid for snapshots Anand jain
2012-12-15 11:52 ` [PATCH 2/5] Btrfs-progs: maintain similar case in heading prefix Anand jain
2012-12-15 11:52 ` [PATCH 3/5] Btrfs-progs: Move printing outside of btrfs_list_subvols Anand jain
2012-12-15 11:52 ` [PATCH 4/5] Btrfs-progs: make provision to print subvol list tree format Anand jain
2012-12-15 11:52 ` Anand jain [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1355572328-32281-6-git-send-email-Anand.Jain@oracle.com \
    --to=anand.jain@oracle.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).