All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2 v3] fi show, dev scan and lblkid
@ 2013-09-13 11:32 Anand Jain
  2013-09-13 11:32 ` [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function Anand Jain
  2013-09-13 11:32 ` [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks Anand Jain
  0 siblings, 2 replies; 8+ messages in thread
From: Anand Jain @ 2013-09-13 11:32 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

  This patch set is about
  use of lblkid for the btrfs disk scan and
  using this lblkid scan for the fi show and dev scan cli

  This includes the comments from David (to use lblkid)
  and Zach to show (btrfs fi show) info from kernel when
  disk is mounted and from the disks directly when disk
  is unmounted by default

v3:
  rebase on to 20130909
  accepts Davids review comments

v2:
  In an effort fix checkpath.pl errors as suggested in
  Wang's review, the two patches as below is merged
  into one

  btrfs-progs: read from the kernel when disk is mounted
  btrfs-progs: use lblkid to scan and filesystem show improvements


Anand Jain (2):
  btrfs-progs: move out print in cmd_df to another function
  btrfs-progs: use kernel for mounted and lblkid to scan disks

 cmds-device.c     |  19 ++-
 cmds-filesystem.c | 354 ++++++++++++++++++++++++++++++++++++++----------------
 ctree.h           |  11 ++
 man/btrfs.8.in    |  17 +--
 utils.c           |  55 ++++++++-
 utils.h           |   5 +
 6 files changed, 338 insertions(+), 123 deletions(-)

-- 
1.8.4.rc4.1.g0d8beaa


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function
  2013-09-13 11:32 [PATCH 0/2 v3] fi show, dev scan and lblkid Anand Jain
@ 2013-09-13 11:32 ` Anand Jain
  2013-09-13 17:01   ` David Sterba
  2013-09-13 11:32 ` [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks Anand Jain
  1 sibling, 1 reply; 8+ messages in thread
From: Anand Jain @ 2013-09-13 11:32 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This is a prepatory work for the btrfs fi show command
fixes. So that we have a function get_df to get the fs sizes

v5:
 rebase on 20130909
 accepts Davids review comments
v4:
 fixes checkpatch.pl errors as suggested by Wang
v3:
 accepts Zach review comments
v2:
combined the other patches as below and rebase
 btrfs-progs: get string for the group profile and type

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 cmds-filesystem.c | 183 +++++++++++++++++++++++++++++-------------------------
 ctree.h           |  11 ++++
 2 files changed, 108 insertions(+), 86 deletions(-)

diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index 815d59a..e1db9e7 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -44,32 +44,53 @@ static const char * const cmd_df_usage[] = {
 	NULL
 };
 
-static int cmd_df(int argc, char **argv)
+static char *group_type_str(u64 flag)
 {
-	struct btrfs_ioctl_space_args *sargs, *sargs_orig;
-	u64 count = 0, i;
-	int ret;
-	int fd;
-	int e;
-	char *path;
-	DIR  *dirstream = NULL;
-
-	if (check_argc_exact(argc, 2))
-		usage(cmd_df_usage);
-
-	path = argv[1];
-
-	fd = open_file_or_dir(path, &dirstream);
-	if (fd < 0) {
-		fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-		return 1;
+	switch (flag & BTRFS_BLOCK_GROUP_TYPE_MASK) {
+	case BTRFS_BLOCK_GROUP_DATA:
+		return "Data";
+	case BTRFS_BLOCK_GROUP_SYSTEM:
+		return "System";
+	case BTRFS_BLOCK_GROUP_METADATA:
+		return "Metadata";
+	case BTRFS_BLOCK_GROUP_DATA|BTRFS_BLOCK_GROUP_METADATA:
+		return "Data+Metadata";
+	default:
+		return "unknown";
 	}
+}
 
-	sargs_orig = sargs = malloc(sizeof(struct btrfs_ioctl_space_args));
-	if (!sargs) {
-		ret = -ENOMEM;
-		goto out;
+static char *group_profile_str(u64 flag)
+{
+	switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+	case 0:
+		return "single";
+	case BTRFS_BLOCK_GROUP_RAID0:
+		return "RAID0";
+	case BTRFS_BLOCK_GROUP_RAID1:
+		return "RAID1";
+	case BTRFS_BLOCK_GROUP_RAID5:
+		return "RAID5";
+	case BTRFS_BLOCK_GROUP_RAID6:
+		return "RAID6";
+	case BTRFS_BLOCK_GROUP_DUP:
+		return "DUP";
+	case BTRFS_BLOCK_GROUP_RAID10:
+		return "RAID10";
+	default:
+		return "unknown";
 	}
+}
+
+static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
+{
+	u64 count = 0;
+	int ret, e;
+	struct btrfs_ioctl_space_args *sargs;
+
+	sargs = malloc(sizeof(struct btrfs_ioctl_space_args));
+	if (!sargs)
+		return -ENOMEM;
 
 	sargs->space_slots = 0;
 	sargs->total_spaces = 0;
@@ -77,89 +98,79 @@ static int cmd_df(int argc, char **argv)
 	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
 	e = errno;
 	if (ret) {
-		fprintf(stderr, "ERROR: couldn't get space info on '%s' - %s\n",
-			path, strerror(e));
-		goto out;
+		fprintf(stderr, "ERROR: couldn't get space info - %s\n",
+			strerror(e));
+		free(sargs);
+		return ret;
 	}
 	if (!sargs->total_spaces) {
-		ret = 0;
-		goto out;
+		free(sargs);
+		return 0;
 	}
-
 	count = sargs->total_spaces;
+	free(sargs);
 
-	sargs = realloc(sargs, sizeof(struct btrfs_ioctl_space_args) +
+	sargs = malloc(sizeof(struct btrfs_ioctl_space_args) +
 			(count * sizeof(struct btrfs_ioctl_space_info)));
-	if (!sargs) {
-		sargs = sargs_orig;
+	if (!sargs)
 		ret = -ENOMEM;
-		goto out;
-	}
 
 	sargs->space_slots = count;
 	sargs->total_spaces = 0;
-
 	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
 	e = errno;
 	if (ret) {
-		fprintf(stderr, "ERROR: couldn't get space info on '%s' - %s\n",
-			path, strerror(e));
-		goto out;
+		fprintf(stderr, "ERROR: get space info count %llu - %s\n",
+				count, strerror(e));
+		free(sargs);
+		return ret;
 	}
+	*sargs_ret = sargs;
+	return 0;
+}
 
-	for (i = 0; i < sargs->total_spaces; i++) {
-		char description[80];
-		int written = 0;
-		u64 flags = sargs->spaces[i].flags;
-
-		memset(description, 0, 80);
-
-		if (flags & BTRFS_BLOCK_GROUP_DATA) {
-			if (flags & BTRFS_BLOCK_GROUP_METADATA) {
-				snprintf(description, 14, "%s",
-					 "Data+Metadata");
-				written += 13;
-			} else {
-				snprintf(description, 5, "%s", "Data");
-				written += 4;
-			}
-		} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
-			snprintf(description, 7, "%s", "System");
-			written += 6;
-		} else if (flags & BTRFS_BLOCK_GROUP_METADATA) {
-			snprintf(description, 9, "%s", "Metadata");
-			written += 8;
-		}
+static void print_df(struct btrfs_ioctl_space_args *sargs)
+{
+	u64 i;
+	struct btrfs_ioctl_space_info *sp = sargs->spaces;
+
+	for (i = 0; i < sargs->total_spaces; i++, sp++) {
+		printf("%s, %s: total=%s, used=%s\n",
+			group_type_str(sp->flags),
+			group_profile_str(sp->flags),
+			pretty_size(sp->total_bytes),
+			pretty_size(sp->used_bytes));
+	}
+}
 
-		if (flags & BTRFS_BLOCK_GROUP_RAID0) {
-			snprintf(description+written, 8, "%s", ", RAID0");
-			written += 7;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID1) {
-			snprintf(description+written, 8, "%s", ", RAID1");
-			written += 7;
-		} else if (flags & BTRFS_BLOCK_GROUP_DUP) {
-			snprintf(description+written, 6, "%s", ", DUP");
-			written += 5;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID10) {
-			snprintf(description+written, 9, "%s", ", RAID10");
-			written += 8;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID5) {
-			snprintf(description+written, 9, "%s", ", RAID5");
-			written += 7;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID6) {
-			snprintf(description+written, 9, "%s", ", RAID6");
-			written += 7;
-		}
+static int cmd_df(int argc, char **argv)
+{
+	struct btrfs_ioctl_space_args *sargs = NULL;
+	int ret;
+	int fd;
+	char *path;
+	DIR  *dirstream = NULL;
 
-		printf("%s: total=%s, used=%s\n", description,
-			pretty_size(sargs->spaces[i].total_bytes),
-			pretty_size(sargs->spaces[i].used_bytes));
+	if (check_argc_exact(argc, 2))
+		usage(cmd_df_usage);
+
+	path = argv[1];
+
+	fd = open_file_or_dir(path, &dirstream);
+	if (fd < 0) {
+		fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+		return 1;
 	}
-out:
-	close_file_or_dir(fd, dirstream);
-	free(sargs);
+	ret = get_df(fd, &sargs);
+
+	if (!ret && sargs) {
+		print_df(sargs);
+		free(sargs);
+	} else
+		fprintf(stderr, "ERROR: get_df failed %s\n", strerror(ret));
 
-	return !!ret;
+	close_file_or_dir(fd, dirstream);
+	return ret;
 }
 
 static int uuid_search(struct btrfs_fs_devices *fs_devices, char *search)
diff --git a/ctree.h b/ctree.h
index 3d6596c..e928a8e 100644
--- a/ctree.h
+++ b/ctree.h
@@ -836,6 +836,17 @@ struct btrfs_csum_item {
 #define BTRFS_BLOCK_GROUP_RAID6    (1ULL << 8)
 #define BTRFS_BLOCK_GROUP_RESERVED	BTRFS_AVAIL_ALLOC_BIT_SINGLE
 
+#define BTRFS_BLOCK_GROUP_TYPE_MASK	(BTRFS_BLOCK_GROUP_DATA |    \
+					 BTRFS_BLOCK_GROUP_SYSTEM |  \
+					 BTRFS_BLOCK_GROUP_METADATA)
+
+#define BTRFS_BLOCK_GROUP_PROFILE_MASK	(BTRFS_BLOCK_GROUP_RAID0 |   \
+					 BTRFS_BLOCK_GROUP_RAID1 |   \
+					 BTRFS_BLOCK_GROUP_RAID5 |   \
+					 BTRFS_BLOCK_GROUP_RAID6 |   \
+					 BTRFS_BLOCK_GROUP_DUP |     \
+					 BTRFS_BLOCK_GROUP_RAID10)
+
 /* used in struct btrfs_balance_args fields */
 #define BTRFS_AVAIL_ALLOC_BIT_SINGLE	(1ULL << 48)
 
-- 
1.8.4.rc4.1.g0d8beaa


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks
  2013-09-13 11:32 [PATCH 0/2 v3] fi show, dev scan and lblkid Anand Jain
  2013-09-13 11:32 ` [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function Anand Jain
@ 2013-09-13 11:32 ` Anand Jain
  2013-09-13 17:25   ` David Sterba
  1 sibling, 1 reply; 8+ messages in thread
From: Anand Jain @ 2013-09-13 11:32 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

As of now btrfs filesystem show reads directly from
disks. So sometimes output can be stale, mainly when
user wants to cross verify their operation like,
label or device delete or add... etc. so this
patch will read from the kernel ioctl if it finds
that disk is mounted.

Further, to scan for the disks this patch will use
lblkid which would replace the our own scan of
/proc/partitions

Further, this patch adds new parameters mounted and
group profile info in the filesystem show output
---------------
btrfs fi show
Label: none  uuid: a2446ecf-68c5-4815-8b63-099d10fc373c mounted: /btrfs
	Group profile: metadata: single  metadata: DUP  data: single
	Total devices 1 FS bytes used 32.00KiB
	devid    1 size 1.98GiB used 238.25MiB path /dev/mapper/mpatha

Label: none  uuid: aea4f4a7-39f2-43dc-bee1-03533551c1a0 (unmounted)
	Total devices 1 FS bytes used 28.00KiB
	devid    1 size 2.00GiB used 240.75MiB path /dev/mapper/mpathb
------------

v2:
  accepts David suggested

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 cmds-device.c     |  19 ++++--
 cmds-filesystem.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++-------
 man/btrfs.8.in    |  17 +++---
 utils.c           |  55 +++++++++++++++++-
 utils.h           |   5 ++
 5 files changed, 230 insertions(+), 37 deletions(-)

diff --git a/cmds-device.c b/cmds-device.c
index 800a050..94ba2f2 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -179,7 +179,7 @@ static const char * const cmd_scan_dev_usage[] = {
 static int cmd_scan_dev(int argc, char **argv)
 {
 	int	i, fd, e;
-	int	where = BTRFS_SCAN_PROC;
+	int	where = 0;
 	int	devstart = 1;
 
 	if( argc > 1 && !strcmp(argv[1],"--all-devices")){
@@ -193,14 +193,21 @@ static int cmd_scan_dev(int argc, char **argv)
 	if(argc<=devstart){
 		int ret;
 		printf("Scanning for Btrfs filesystems\n");
-		ret = scan_for_btrfs(where, 1);
-		if (ret){
-			fprintf(stderr, "ERROR: error %d while scanning\n", ret);
-			return 1;
-		}
+		if (where == BTRFS_SCAN_DEV) {
+			ret = scan_for_btrfs(BTRFS_SCAN_DEV,
+						BTRFS_UPDATE_KERNEL);
+			if (ret) {
+				fprintf(stderr,
+					"ERROR: %d while scanning\n", ret);
+				return 1;
+			}
+		} else
+			scan_for_btrfs_v2(BTRFS_UPDATE_KERNEL);
+
 		return 0;
 	}
 
+	/* if its here that means scan the specificed device/file */
 	fd = open("/dev/btrfs-control", O_RDWR);
 	if (fd < 0) {
 		perror("failed to open /dev/btrfs-control");
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index e1db9e7..80b6de1 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -22,6 +22,9 @@
 #include <errno.h>
 #include <uuid/uuid.h>
 #include <ctype.h>
+#include <mntent.h>
+#include <fcntl.h>
+#include <linux/limits.h>
 
 #include "kerncompat.h"
 #include "ctree.h"
@@ -212,8 +215,9 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices)
 
 
 	total = device->total_devs;
-	printf(" uuid: %s\n\tTotal devices %llu FS bytes used %s\n", uuidbuf,
-	       (unsigned long long)total,
+
+	printf(" uuid: %s (unmounted)\n\tTotal devices %llu FS bytes used %s\n",
+		uuidbuf, (unsigned long long)total,
 	       pretty_size(device->super_bytes_used));
 
 	list_for_each(cur, &fs_devices->devices) {
@@ -232,10 +236,98 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices)
 	printf("\n");
 }
 
+/* adds up all the used spaces as reported by the space info ioctl
+ */
+static u64 calc_used_bytes(struct btrfs_ioctl_space_args *si)
+{
+	u64 ret = 0;
+	int i;
+	for (i = 0; i < si->total_spaces; i++)
+		ret += si->spaces[i].used_bytes;
+	return ret;
+}
+
+static int print_one_fs(struct btrfs_ioctl_fs_info_args *fi,
+		struct btrfs_ioctl_dev_info_args *di_n,
+		struct btrfs_ioctl_space_args *si_n, char *label, char *path)
+{
+	int i;
+	char uuidbuf[37];
+	struct btrfs_ioctl_dev_info_args *di = di_n;
+	u64 flags;
+
+	uuid_unparse(fi->fsid, uuidbuf);
+	printf("Label: %s  uuid: %s mounted: %s\n",
+		strlen(label) ? label : "none", uuidbuf, path);
+	printf("\tGroup profile:");
+	for (i = si_n->total_spaces - 1; i >= 0; i--) {
+		flags = si_n->spaces[i].flags;
+		if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
+			continue;
+		printf(" %s: %s", group_type_str(flags),
+					group_profile_str(flags));
+		printf(" ");
+	}
+	printf("\n");
+
+	printf("\tTotal devices %llu FS bytes used %s\n",
+				fi->num_devices,
+			pretty_size(calc_used_bytes(si_n)));
+
+	for (i = 0; i < fi->num_devices; i++) {
+		di = (struct btrfs_ioctl_dev_info_args *)&di_n[i];
+		printf("\tdevid    %llu size %s used %s path %s\n",
+			di->devid,
+			pretty_size(di->total_bytes),
+			pretty_size(di->bytes_used),
+			di->path);
+	}
+
+	printf("\n");
+	return 0;
+}
+
+static int btrfs_scan_kernel()
+{
+	int ret = 0, fd;
+	FILE *f;
+	struct mntent *mnt;
+	struct btrfs_ioctl_fs_info_args fs_info_arg;
+	struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL;
+	struct btrfs_ioctl_space_args *space_info_arg;
+	char label[BTRFS_LABEL_SIZE];
+
+	f = setmntent("/proc/self/mounts", "r");
+	if (f == NULL)
+		return 1;
+
+	while ((mnt = getmntent(f)) != NULL) {
+		if (strcmp(mnt->mnt_type, "btrfs"))
+			continue;
+		ret = get_fs_info(mnt->mnt_dir, &fs_info_arg,
+				&dev_info_arg);
+		if (ret)
+			return ret;
+
+		fd = open(mnt->mnt_dir, O_RDONLY);
+		if (fd > 0 && !get_df(fd, &space_info_arg)) {
+			get_label_mounted(mnt->mnt_dir, label);
+			print_one_fs(&fs_info_arg, dev_info_arg,
+				space_info_arg, label, mnt->mnt_dir);
+			free(space_info_arg);
+		}
+		if (fd > 0)
+			close(fd);
+		free(dev_info_arg);
+	}
+	return ret;
+}
+
 static const char * const cmd_show_usage[] = {
-	"btrfs filesystem show [--all-devices|<uuid>]",
-	"Show the structure of a filesystem",
+	"btrfs filesystem show [--mounted|--all-devices [<uuid>]]",
+	"Show the structure of btrfs filesystem(s)",
 	"If no argument is given, structure of all present filesystems is shown.",
+	"--mounted  show only the mounted btrfs filesystem",
 	NULL
 };
 
@@ -246,34 +338,73 @@ static int cmd_show(int argc, char **argv)
 	struct list_head *cur_uuid;
 	char *search = NULL;
 	int ret;
-	int where = BTRFS_SCAN_PROC;
+	int where = 0;
 	int searchstart = 1;
 
 	if( argc > 1 && !strcmp(argv[1],"--all-devices")){
 		where = BTRFS_SCAN_DEV;
 		searchstart += 1;
+	} else if (argc > 1 && !strcmp(argv[1], "--mounted")) {
+		where = BTRFS_SCAN_MOUNTED;
+		searchstart += 1;
 	}
 
-	if (check_argc_max(argc, searchstart + 1))
-		usage(cmd_show_usage);
-
-	ret = scan_for_btrfs(where, 0);
-
-	if (ret){
-		fprintf(stderr, "ERROR: error %d while scanning\n", ret);
-		return 1;
+	if (where == BTRFS_SCAN_DEV) {
+		if (check_argc_max(argc, searchstart + 1))
+			usage(cmd_show_usage);
+	} else if (where == BTRFS_SCAN_MOUNTED) {
+		if (check_argc_max(argc, searchstart))
+			usage(cmd_show_usage);
+	} else {
+		if (check_argc_max(argc, searchstart))
+			usage(cmd_show_usage);
 	}
-	
+
 	if(searchstart < argc)
 		search = argv[searchstart];
 
-	all_uuids = btrfs_scanned_uuids();
-	list_for_each(cur_uuid, all_uuids) {
-		fs_devices = list_entry(cur_uuid, struct btrfs_fs_devices,
+	switch (where) {
+	case 0:
+		/* no option : show both mounted and unmounted
+		 */
+		/* mounted */
+		ret = btrfs_scan_kernel();
+		if (ret)
+			fprintf(stderr, "ERROR: scan kernel failed, %d\n",
+				ret);
+
+		/* unmounted */
+		scan_for_btrfs_v2(!BTRFS_UPDATE_KERNEL);
+		all_uuids = btrfs_scanned_uuids();
+		list_for_each(cur_uuid, all_uuids) {
+			fs_devices = list_entry(cur_uuid,
+					struct btrfs_fs_devices,
 					list);
-		if (search && uuid_search(fs_devices, search) == 0)
-			continue;
-		print_one_uuid(fs_devices);
+			print_one_uuid(fs_devices);
+		}
+		break;
+	case BTRFS_SCAN_DEV:
+		ret = scan_for_btrfs(BTRFS_SCAN_DEV, !BTRFS_UPDATE_KERNEL);
+		if (ret) {
+			fprintf(stderr, "ERROR: %d while scanning\n", ret);
+			return 1;
+		}
+		all_uuids = btrfs_scanned_uuids();
+		list_for_each(cur_uuid, all_uuids) {
+			fs_devices = list_entry(cur_uuid,
+					struct btrfs_fs_devices,
+					list);
+			if (search && uuid_search(fs_devices, search) == 0)
+				continue;
+			print_one_uuid(fs_devices);
+		}
+		break;
+	case BTRFS_SCAN_MOUNTED:
+		ret = btrfs_scan_kernel();
+		if (ret)
+			fprintf(stderr, "ERROR: scan kernel failed, %d\n",
+				ret);
+		break;
 	}
 	printf("%s\n", BTRFS_BUILD_VERSION);
 	return 0;
diff --git a/man/btrfs.8.in b/man/btrfs.8.in
index 61ffe8d..6a4f5bc 100644
--- a/man/btrfs.8.in
+++ b/man/btrfs.8.in
@@ -25,7 +25,7 @@ btrfs \- control a btrfs filesystem
 .PP
 \fBbtrfs\fP \fBfilesystem df\fP\fI <path>\fP
 .PP
-\fBbtrfs\fP \fBfilesystem show\fP [--all-devices|\fI<uuid>\fP|\fI<label>\fP]\fP
+\fBbtrfs\fP \fBfilesystem show\fP [\fI--mounted\fP|\fI--all-devices\fP|\fI<uuid>\fP]\fP
 .PP
 \fBbtrfs\fP \fBfilesystem sync\fP\fI <path> \fP
 .PP
@@ -51,7 +51,7 @@ btrfs \- control a btrfs filesystem
 .PP
 \fBbtrfs\fP \fBdevice delete\fP \fI<device>\fP [\fI<device>...\fP] \fI<path>\fP
 .PP
-\fBbtrfs\fP \fBdevice scan\fP [--all-devices|\fI<device> \fP[\fI<device>...\fP]
+\fBbtrfs\fP \fBdevice scan\fP [\fI--all-devices\fP|\fI<device> \P[\fI<device>...\fP]
 .PP
 \fBbtrfs\fP \fBdevice ready\fP\fI <device>\fP
 .PP
@@ -259,11 +259,12 @@ Show information of a given subvolume in the \fI<path>\fR.
 Show space usage information for a mount point.
 .TP
 
-\fBfilesystem show\fR [--all-devices|\fI<uuid>\fR|\fI<label>\fR]\fR
-Show the btrfs filesystem with some additional info. If no \fIUUID\fP or
-\fIlabel\fP is passed, \fBbtrfs\fR show info of all the btrfs filesystem.
+\fBfilesystem show\fR [\fI--mounted\fP|\fI--all-devices\fP|\fI<uuid>\fR]\fR
+Show the btrfs filesystem with some additional info. If no option or \fIUUID\fP
+is passed, \fBbtrfs\fR shows information of all the btrfs filesystem both mounted
+and unmounted.
+If \fB--mounted\fP is passed, it would probe btrfs kernel to list mounted btrfs filesystem(s);
 If \fB--all-devices\fP is passed, all the devices under /dev are scanned;
-otherwise the devices list is extracted from the /proc/partitions file.
 .TP
 
 \fBfilesystem sync\fR\fI <path> \fR
@@ -396,8 +397,8 @@ Remove device(s) from a filesystem identified by \fI<path>\fR.
 
 \fBdevice scan\fR [--all-devices|\fI<device> \fP[\fI<device>...\fP]\fR
 If one or more devices are passed, these are scanned for a btrfs filesystem. 
-If no devices are passed, \fBbtrfs\fR scans all the block devices listed
-in the /proc/partitions file.
+If no devices are passed, \fBbtrfs\fR uses block devices containing btrfs
+filesystem as listed by blkid.
 Finally, if \fB--all-devices\fP is passed, all the devices under /dev are 
 scanned.
 .TP
diff --git a/utils.c b/utils.c
index 134bf80..02a2658 100644
--- a/utils.c
+++ b/utils.c
@@ -685,9 +685,9 @@ int is_block_device(const char *path) {
  * Find the mount point for a mounted device.
  * On success, returns 0 with mountpoint in *mp.
  * On failure, returns -errno (not mounted yields -EINVAL)
- * Is noisy on failures, expects to be given a mounted device.
  */
-static int get_btrfs_mount(const char *dev, char *mp, size_t mp_size) {
+int get_btrfs_mount(const char *dev, char *mp, size_t mp_size)
+{
 	int ret;
 	int fd = -1;
 
@@ -712,7 +712,6 @@ static int get_btrfs_mount(const char *dev, char *mp, size_t mp_size) {
 
 	ret = check_mounted_where(fd, dev, mp, mp_size, NULL);
 	if (!ret) {
-		fprintf(stderr, "%s is not a mounted btrfs device\n", dev);
 		ret = -EINVAL;
 	} else { /* mounted, all good */
 		ret = 0;
@@ -1144,6 +1143,56 @@ fail:
 	return ret;
 }
 
+int test_skip_this_disk(char *path)
+{
+	int fd;
+	/* this will eliminate disks which are mounted (btrfs)
+	 * and non-dm disk path when dm is enabled
+	 */
+	fd = open(path, O_RDWR|O_EXCL);
+	if (fd < 0)
+		return 1;
+	close(fd);
+	return 0;
+}
+
+void scan_for_btrfs_v2(int update_kernel)
+{
+	int fd = -1;
+	u64 num_devices;
+	struct btrfs_fs_devices *tmp_devices;
+	blkid_dev_iterate iter = NULL;
+	blkid_dev dev = NULL;
+	blkid_cache cache = NULL;
+	char path[PATH_MAX];
+
+	if (blkid_get_cache(&cache, 0) < 0) {
+		printf("ERROR: lblkid cache get failed\n");
+		return;
+	}
+	blkid_probe_all(cache);
+	iter = blkid_dev_iterate_begin(cache);
+	blkid_dev_set_search(iter, "TYPE", "btrfs");
+	while (blkid_dev_next(iter, &dev) == 0) {
+		dev = blkid_verify(cache, dev);
+		if (!dev)
+			continue;
+		/* if we are here its definitly a btrfs disk*/
+		strcpy(path, blkid_dev_devname(dev));
+		if (test_skip_this_disk(path))
+			continue;
+
+		fd = open(path, O_RDONLY);
+		btrfs_scan_one_device(fd, path, &tmp_devices,
+				&num_devices, BTRFS_SUPER_INFO_OFFSET);
+		close(fd);
+		fd = -1;
+		if (update_kernel)
+			btrfs_register_one_device(path);
+	}
+	blkid_dev_iterate_end(iter);
+}
+
 int btrfs_scan_for_fsid(int run_ioctls)
 {
 	int ret;
diff --git a/utils.h b/utils.h
index 6c2553a..616bae1 100644
--- a/utils.h
+++ b/utils.h
@@ -27,6 +27,9 @@
 
 #define BTRFS_SCAN_PROC	1
 #define BTRFS_SCAN_DEV		2
+#define BTRFS_SCAN_MOUNTED	3
+
+#define BTRFS_UPDATE_KERNEL	1
 
 int make_btrfs(int fd, const char *device, const char *label,
 	       u64 blocks[6], u64 num_bytes, u32 nodesize,
@@ -74,10 +77,12 @@ u64 btrfs_device_size(int fd, struct stat *st);
 #define strncpy_null(dest, src) __strncpy__null(dest, src, sizeof(dest))
 int test_dev_for_mkfs(char *file, int force_overwrite, char *estr);
 int scan_for_btrfs(int where, int update_kernel);
+void scan_for_btrfs_v2(int update_kernel);
 int get_label_mounted(const char *mount_path, char *labelp);
 int test_num_disk_vs_raid(u64 metadata_profile, u64 data_profile,
 	u64 dev_cnt, int mixed, char *estr);
 int is_vol_small(char *file);
 int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
 			   int verify);
+int get_btrfs_mount(const char *dev, char *mp, size_t mp_size);
 #endif
-- 
1.8.4.rc4.1.g0d8beaa


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function
  2013-09-13 11:32 ` [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function Anand Jain
@ 2013-09-13 17:01   ` David Sterba
  0 siblings, 0 replies; 8+ messages in thread
From: David Sterba @ 2013-09-13 17:01 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs, dsterba, wangsl.fnst

On Fri, Sep 13, 2013 at 07:32:22PM +0800, Anand Jain wrote:
> +static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
> +{

This function returns full error codes, that's ok,

> @@ -77,89 +98,79 @@ static int cmd_df(int argc, char **argv)
>  	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
>  	e = errno;
>  	if (ret) {
> -		fprintf(stderr, "ERROR: couldn't get space info on '%s' - %s\n",
> -			path, strerror(e));
> -		goto out;
> +		fprintf(stderr, "ERROR: couldn't get space info - %s\n",
> +			strerror(e));
> +		free(sargs);
> +		return ret;

cmd_df should return the 0-1 normalized value after the cleanup that
Wang Shilong has done. You can leave the common exit block (ie. goto +
free/return as before) and use return !!ret.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks
  2013-09-13 11:32 ` [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks Anand Jain
@ 2013-09-13 17:25   ` David Sterba
  2013-09-15  4:30     ` Anand Jain
  0 siblings, 1 reply; 8+ messages in thread
From: David Sterba @ 2013-09-13 17:25 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs, dsterba

On Fri, Sep 13, 2013 at 07:32:23PM +0800, Anand Jain wrote:
> Further, this patch adds new parameters mounted and
> group profile info in the filesystem show output

Sorry to bother you, but the 'further' part of the patch should be
separated out. The core change of the patch is to use libblkid and the
ioctl.

> ---------------
> btrfs fi show
> Label: none  uuid: a2446ecf-68c5-4815-8b63-099d10fc373c mounted: /btrfs
> 	Group profile: metadata: single  metadata: DUP  data: single

I didn't notice that before, this does not bring much information
without the numbers as 'fi df' does. Please drop the printf lines

> @@ -246,34 +338,73 @@ static int cmd_show(int argc, char **argv)
>  	struct list_head *cur_uuid;
>  	char *search = NULL;
>  	int ret;
> -	int where = BTRFS_SCAN_PROC;
> +	int where = 0;
>  	int searchstart = 1;
>  
>  	if( argc > 1 && !strcmp(argv[1],"--all-devices")){
>  		where = BTRFS_SCAN_DEV;
>  		searchstart += 1;
> +	} else if (argc > 1 && !strcmp(argv[1], "--mounted")) {
> +		where = BTRFS_SCAN_MOUNTED;
> +		searchstart += 1;

getopt was not used here, but with the new options it probably should
be, because

> -	if (check_argc_max(argc, searchstart + 1))
> -		usage(cmd_show_usage);
> -
> -	ret = scan_for_btrfs(where, 0);
> -
> -	if (ret){
> -		fprintf(stderr, "ERROR: error %d while scanning\n", ret);
> -		return 1;
> +	if (where == BTRFS_SCAN_DEV) {
> +		if (check_argc_max(argc, searchstart + 1))
> +			usage(cmd_show_usage);
> +	} else if (where == BTRFS_SCAN_MOUNTED) {
> +		if (check_argc_max(argc, searchstart))
> +			usage(cmd_show_usage);
> +	} else {
> +		if (check_argc_max(argc, searchstart))
> +			usage(cmd_show_usage);

this stops to work:

$ btrfs fi show SOME-UUID
btrfs filesystem show: too many arguments


thanks,
david

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks
  2013-09-13 17:25   ` David Sterba
@ 2013-09-15  4:30     ` Anand Jain
  2013-09-16 15:42       ` David Sterba
  0 siblings, 1 reply; 8+ messages in thread
From: Anand Jain @ 2013-09-15  4:30 UTC (permalink / raw)
  To: dsterba, linux-btrfs

>> ---------------
>> btrfs fi show
>> Label: none  uuid: a2446ecf-68c5-4815-8b63-099d10fc373c mounted: /btrfs
>> 	Group profile: metadata: single  metadata: DUP  data: single
>
> I didn't notice that before, this does not bring much information
> without the numbers as 'fi df' does. Please drop the printf lines

  Thanks for the review.
  IMO group profile is useful info to have it at both the places.
  end user using this new btrfs fi show would surely notice that it
  will reduce other commands normally used following the current
  btrfs fi show command. (like mount and btrfs fi df). of course
  user should use fi df to know detailed info about the sizes.

-------
btrfs fi show
Label: none  uuid: 2c654c36-ba53-4cc8-9c95-f0bee667b9a6 mounted: /btrfs
	Group profile: Data+Metadata: single
	Total devices 2 FS bytes used 3.17MiB
	devid    1 size 1.98GiB used 12.00MiB path /dev/mapper/mpatha
	devid    2 size 2.00GiB used 416.00MiB path /dev/mapper/mpathb
-------

Thanks, Anand




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks
  2013-09-15  4:30     ` Anand Jain
@ 2013-09-16 15:42       ` David Sterba
  0 siblings, 0 replies; 8+ messages in thread
From: David Sterba @ 2013-09-16 15:42 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs

On Sun, Sep 15, 2013 at 12:30:35PM +0800, Anand Jain wrote:
>  IMO group profile is useful info to have it at both the places.
>  end user using this new btrfs fi show would surely notice that it
>  will reduce other commands normally used following the current
>  btrfs fi show command. (like mount and btrfs fi df). of course
>  user should use fi df to know detailed info about the sizes.

Yeah, the output of df/show needs reworking, but please do not mix
unrelated changes to other patches, although it may be too tempting in
this particular case.

david

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function
  2013-08-08  8:07 [PATCH 0/2 v2] introduce btrfs filesystem show --kernel Anand Jain
@ 2013-08-08  8:07 ` Anand Jain
  0 siblings, 0 replies; 8+ messages in thread
From: Anand Jain @ 2013-08-08  8:07 UTC (permalink / raw)
  To: linux-btrfs

This is a prepatory work for the following btrfs fi show command
fixes. So that we have a function get_df to get the fs sizes

v2:
combined the other patches as below and rebase
 btrfs-progs: get string for the group profile and type

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 cmds-filesystem.c | 190 +++++++++++++++++++++++++++++++-----------------------
 ctree.h           |  11 ++++
 2 files changed, 122 insertions(+), 79 deletions(-)

diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index a4e30ea..be8afde 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -44,28 +44,51 @@ static const char * const cmd_df_usage[] = {
 	NULL
 };
 
-static int cmd_df(int argc, char **argv)
+static char * group_type_str(u64 flag)
 {
-	struct btrfs_ioctl_space_args *sargs, *sargs_orig;
-	u64 count = 0, i;
-	int ret;
-	int fd;
-	int e;
-	char *path;
-	DIR  *dirstream = NULL;
-
-	if (check_argc_exact(argc, 2))
-		usage(cmd_df_usage);
-
-	path = argv[1];
+	switch (flag & BTRFS_BLOCK_GROUP_TYPE_MASK) {
+	case BTRFS_BLOCK_GROUP_DATA:
+		return "data";
+	case BTRFS_BLOCK_GROUP_SYSTEM:
+		return "system";
+	case BTRFS_BLOCK_GROUP_METADATA:
+		return "metadata";
+	case BTRFS_BLOCK_GROUP_DATA|BTRFS_BLOCK_GROUP_METADATA:
+		return "mixed";
+	default:
+		return "unknown";
+	}
+}
 
-	fd = open_file_or_dir(path, &dirstream);
-	if (fd < 0) {
-		fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-		return 12;
+static char * group_profile_str(u64 flag)
+{
+	switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+	case 0:
+		return "single";
+	case BTRFS_BLOCK_GROUP_RAID0:
+		return "RAID0";
+	case BTRFS_BLOCK_GROUP_RAID1:
+		return "RAID1";
+	case BTRFS_BLOCK_GROUP_RAID5:
+		return "RAID5";
+	case BTRFS_BLOCK_GROUP_RAID6:
+		return "RAID6";
+	case BTRFS_BLOCK_GROUP_DUP:
+		return "DUP";
+	case BTRFS_BLOCK_GROUP_RAID10:
+		return "RAID10";
+	default:
+		return "unknown";
 	}
+}
+
+static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
+{
+	u64 count = 0;
+	int ret, e;
+	struct btrfs_ioctl_space_args *sargs;
 
-	sargs_orig = sargs = malloc(sizeof(struct btrfs_ioctl_space_args));
+	sargs = malloc(sizeof(struct btrfs_ioctl_space_args));
 	if (!sargs)
 		return -ENOMEM;
 
@@ -75,89 +98,98 @@ static int cmd_df(int argc, char **argv)
 	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
 	e = errno;
 	if (ret) {
-		fprintf(stderr, "ERROR: couldn't get space info on '%s' - %s\n",
-			path, strerror(e));
-		goto out;
+		fprintf(stderr, "ERROR: couldn't get space info - %s\n",
+			strerror(e));
+		free(sargs);
+		return ret;
 	}
 	if (!sargs->total_spaces) {
-		ret = 0;
-		goto out;
+		free(sargs);
+		return 0;
 	}
-
 	count = sargs->total_spaces;
+	free(sargs);
 
-	sargs = realloc(sargs, sizeof(struct btrfs_ioctl_space_args) +
+	sargs = malloc(sizeof(struct btrfs_ioctl_space_args) +
 			(count * sizeof(struct btrfs_ioctl_space_info)));
-	if (!sargs) {
-		sargs = sargs_orig;
+	if (!sargs)
 		ret = -ENOMEM;
-		goto out;
-	}
 
 	sargs->space_slots = count;
 	sargs->total_spaces = 0;
-
 	ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
 	e = errno;
 	if (ret) {
-		fprintf(stderr, "ERROR: couldn't get space info on '%s' - %s\n",
-			path, strerror(e));
-		goto out;
+		fprintf(stderr, "ERROR: get space info count %llu - %s\n",
+				count, strerror(e));
+		free(sargs);
+		return ret;
 	}
+	*sargs_ret = sargs;
+	return 0;
+}
 
-	for (i = 0; i < sargs->total_spaces; i++) {
-		char description[80];
-		int written = 0;
-		u64 flags = sargs->spaces[i].flags;
+static void print_df(struct btrfs_ioctl_space_args *sargs)
+{
+	char description[80];
+	char *total_bytes;
+	char *used_bytes;
+	u64 flags;
+	u64 i;
+	int written;
+	char g_str[64];
+	int g_sz;
 
+	for (i = 0; i < sargs->total_spaces; i++) {
+		flags = sargs->spaces[i].flags;
+		written = 0;
 		memset(description, 0, 80);
 
-		if (flags & BTRFS_BLOCK_GROUP_DATA) {
-			if (flags & BTRFS_BLOCK_GROUP_METADATA) {
-				snprintf(description, 14, "%s",
-					 "Data+Metadata");
-				written += 13;
-			} else {
-				snprintf(description, 5, "%s", "Data");
-				written += 4;
-			}
-		} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
-			snprintf(description, 7, "%s", "System");
-			written += 6;
-		} else if (flags & BTRFS_BLOCK_GROUP_METADATA) {
-			snprintf(description, 9, "%s", "Metadata");
-			written += 8;
-		}
+		strcpy(g_str, group_type_str(flags));
+		g_sz = strlen(g_str);
+		snprintf(description, g_sz + 1, "%s", g_str);
+		written += g_sz;
 
-		if (flags & BTRFS_BLOCK_GROUP_RAID0) {
-			snprintf(description+written, 8, "%s", ", RAID0");
-			written += 7;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID1) {
-			snprintf(description+written, 8, "%s", ", RAID1");
-			written += 7;
-		} else if (flags & BTRFS_BLOCK_GROUP_DUP) {
-			snprintf(description+written, 6, "%s", ", DUP");
-			written += 5;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID10) {
-			snprintf(description+written, 9, "%s", ", RAID10");
-			written += 8;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID5) {
-			snprintf(description+written, 9, "%s", ", RAID5");
-			written += 7;
-		} else if (flags & BTRFS_BLOCK_GROUP_RAID6) {
-			snprintf(description+written, 9, "%s", ", RAID6");
-			written += 7;
-		}
+		strcpy(g_str, group_profile_str(flags));
+		g_sz = strlen(g_str);
+		snprintf(description+written, g_sz + 3, ", %s", g_str);
+		written += g_sz + 2;
 
-		printf("%s: total=%s, used=%s\n", description,
-			pretty_size(sargs->spaces[i].total_bytes),
-			pretty_size(sargs->spaces[i].used_bytes));
+		total_bytes = pretty_size(sargs->spaces[i].total_bytes);
+		used_bytes = pretty_size(sargs->spaces[i].used_bytes);
+		printf("%s: total=%s, used=%s\n", description, total_bytes,
+		       used_bytes);
 	}
-out:
-	close_file_or_dir(fd, dirstream);
-	free(sargs);
+}
 
-	return 0;
+static int cmd_df(int argc, char **argv)
+{
+	struct btrfs_ioctl_space_args *sargs = NULL;
+	int ret;
+	int fd;
+	char *path;
+	DIR  *dirstream = NULL;
+
+	if (check_argc_exact(argc, 2))
+		usage(cmd_df_usage);
+
+	path = argv[1];
+
+	fd = open_file_or_dir(path, &dirstream);
+	if (fd < 0) {
+		fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+		return 12;
+	}
+	ret = get_df(fd, &sargs);
+
+	if (!ret && sargs) {
+		print_df(sargs);
+		free(sargs);
+	} else
+		fprintf(stderr, "ERROR: get_df failed %s\n", strerror(ret));
+
+	close_file_or_dir(fd, dirstream);
+	return ret;
 }
 
 static int uuid_search(struct btrfs_fs_devices *fs_devices, char *search)
diff --git a/ctree.h b/ctree.h
index 257396d..21bfa30 100644
--- a/ctree.h
+++ b/ctree.h
@@ -826,6 +826,17 @@ struct btrfs_csum_item {
 #define BTRFS_BLOCK_GROUP_RAID6    (1ULL << 8)
 #define BTRFS_BLOCK_GROUP_RESERVED	BTRFS_AVAIL_ALLOC_BIT_SINGLE
 
+#define BTRFS_BLOCK_GROUP_TYPE_MASK	(BTRFS_BLOCK_GROUP_DATA |    \
+					 BTRFS_BLOCK_GROUP_SYSTEM |  \
+					 BTRFS_BLOCK_GROUP_METADATA)
+
+#define BTRFS_BLOCK_GROUP_PROFILE_MASK	(BTRFS_BLOCK_GROUP_RAID0 |   \
+					 BTRFS_BLOCK_GROUP_RAID1 |   \
+					 BTRFS_BLOCK_GROUP_RAID5 |   \
+					 BTRFS_BLOCK_GROUP_RAID6 |   \
+					 BTRFS_BLOCK_GROUP_DUP |     \
+					 BTRFS_BLOCK_GROUP_RAID10)
+
 /* used in struct btrfs_balance_args fields */
 #define BTRFS_AVAIL_ALLOC_BIT_SINGLE	(1ULL << 48)
 
-- 
1.8.1.191.g414c78c

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-09-16 15:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-13 11:32 [PATCH 0/2 v3] fi show, dev scan and lblkid Anand Jain
2013-09-13 11:32 ` [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function Anand Jain
2013-09-13 17:01   ` David Sterba
2013-09-13 11:32 ` [PATCH 2/2] btrfs-progs: use kernel for mounted and lblkid to scan disks Anand Jain
2013-09-13 17:25   ` David Sterba
2013-09-15  4:30     ` Anand Jain
2013-09-16 15:42       ` David Sterba
  -- strict thread matches above, loose matches on Subject: below --
2013-08-08  8:07 [PATCH 0/2 v2] introduce btrfs filesystem show --kernel Anand Jain
2013-08-08  8:07 ` [PATCH 1/2] btrfs-progs: move out print in cmd_df to another function Anand Jain

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.