@@ -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"
@@ -256,8 +259,129 @@ 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 cal_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];
+ char *sz1;
+ char *sz2;
+ 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");
+
+ sz1 = pretty_sizes(cal_used_bytes(si_n));
+ printf("\tTotal devices %llu FS bytes used %s\n",
+ fi->num_devices, sz1);
+ free(sz1);
+
+ for (i = 0; i < fi->num_devices; i++) {
+ di = (struct btrfs_ioctl_dev_info_args *)&di_n[i];
+ sz1 = pretty_sizes(di->total_bytes);
+ sz2 = pretty_sizes(di->bytes_used);
+ printf("\tdevid %llu size %s used %s path %s\n",
+ di->devid, sz1, sz2, di->path);
+ free(sz1);
+ free(sz2);
+ }
+
+ printf("\n");
+ return 0;
+}
+
+/* This function checks if the given input parameter is
+ * an uuid or a path
+ * return -1: some error in the given input
+ * return 0: unknow input
+ * return 1: given input is uuid
+ * return 2: given input is path
+ */
+static int check_arg_type(char *input, u8 *processed)
+{
+ int ret = 0;
+ if (!uuid_parse(input, processed))
+ ret = 1;
+ else if (realpath(input, (char *)processed))
+ ret = 2;
+ return ret;
+}
+
+
+static int btrfs_scan_kernel(void *input, int type)
+{
+ int ret = 0, fd;
+ FILE *f;
+ struct mntent *mnt;
+ struct btrfs_ioctl_fs_info_args fi;
+ struct btrfs_ioctl_dev_info_args *di = NULL;
+ struct btrfs_ioctl_space_args *si;
+ char label[BTRFS_LABEL_SIZE];
+
+ if ((f = setmntent ("/proc/mounts", "r")) == NULL)
+ return -errno;
+
+ while ((mnt = getmntent (f)) != NULL) {
+ if (strcmp(mnt->mnt_type, "btrfs"))
+ continue;
+ ret = get_fs_info(mnt->mnt_dir, &fi, &di);
+ if (ret)
+ return ret;
+
+ switch (type) {
+ case 0:
+ break;
+ case 1:
+ if (uuid_compare(fi.fsid, (u8 *)input))
+ continue;
+ break;
+ case 2:
+ if (strcmp(input, mnt->mnt_dir))
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ fd = open(mnt->mnt_dir, O_RDONLY);
+ if (fd > 0 && !get_df(fd, &si)) {
+ get_label_mounted(mnt->mnt_dir, label);
+ print_one_fs(&fi, di, si, label, mnt->mnt_dir);
+ free(si);
+ }
+ if (fd > 0)
+ close(fd);
+ free(di);
+ }
+ return ret;
+}
+
static const char * const cmd_show_usage[] = {
- "btrfs filesystem show [--all-devices|--mapper|<uuid>]",
+ "btrfs filesystem show [--all-devices|--mapper|--kernel|<uuid>]",
"Show the structure of a filesystem",
"If no argument is given, structure of all present filesystems is shown.",
NULL
@@ -269,9 +393,10 @@ static int cmd_show(int argc, char **argv)
struct btrfs_fs_devices *fs_devices;
struct list_head *cur_uuid;
char *search = 0;
- int ret;
+ int ret = 0;
int where = BTRFS_SCAN_PROC;
int searchstart = 1;
+ u8 processed[PATH_MAX];
if (argc > 1 && !strcmp(argv[1],"--all-devices")) {
where = BTRFS_SCAN_DEV;
@@ -279,15 +404,42 @@ static int cmd_show(int argc, char **argv)
} else if (argc > 1 && !strcmp(argv[1],"--mapper")) {
where = BTRFS_SCAN_MAPPER;
searchstart += 1;
+ } else if (argc > 1 && !strcmp(argv[1],"--kernel")) {
+ where = 0;
+ searchstart += 1;
}
- if (check_argc_max(argc, searchstart + 1))
- usage(cmd_show_usage);
+ if (!where) {
+ if (! (searchstart < argc))
+ ret = btrfs_scan_kernel(NULL, 0);
- ret = scan_for_btrfs(where, 0);
+ while (searchstart < argc) {
+ ret = check_arg_type(argv[searchstart], processed);
+ if (ret < 0) {
+ fprintf(stderr, "ERROR at the input %s\n",
+ argv[searchstart]);
+ return 1;
+ }
+ if (!ret) {
+ fprintf(stderr, "ERROR unknown %s\n",
+ argv[searchstart]);
+ return 1;
+ }
- if (ret){
- fprintf(stderr, "ERROR: error %d while scanning\n", ret);
+ ret = btrfs_scan_kernel(processed, ret);
+ if (ret)
+ break;
+ searchstart++;
+ }
+ if (ret)
+ fprintf(stderr, "ERROR: failed to obtain one or more FS %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = scan_for_btrfs(where, 0);
+ if (ret) {
+ fprintf(stderr, "ERROR: %d while scanning\n", ret);
return 18;
}