btrfs-progs: use BTRFS_SUPER_INFO_SIZE to replace raw 4096 in btrfs-image
[platform/upstream/btrfs-progs.git] / cmds-inspect.c
index 2f0228f..cd9d2c6 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdint.h>
 #include <sys/ioctl.h>
 #include <errno.h>
 
 #include "kerncompat.h"
 #include "ioctl.h"
+#include "utils.h"
+#include "ctree.h"
+#include "send-utils.h"
 
 #include "commands.h"
-
-/* btrfs-list.c */
-char *path_for_root(int fd, u64 root);
+#include "btrfs-list.h"
 
 static const char * const inspect_cmd_group_usage[] = {
        "btrfs inspect-internal <command> <args>",
@@ -42,11 +44,12 @@ static int __ino_to_path_fd(u64 inum, int fd, int verbose, const char *prepend)
 
        fspath = malloc(4096);
        if (!fspath)
-               return 1;
+               return -ENOMEM;
 
+       memset(fspath, 0, sizeof(*fspath));
        ipa.inum = inum;
        ipa.size = 4096;
-       ipa.fspath = (u64)fspath;
+       ipa.fspath = (uintptr_t)fspath;
 
        ret = ioctl(fd, BTRFS_IOC_INO_PATHS, &ipa);
        if (ret) {
@@ -62,22 +65,27 @@ static int __ino_to_path_fd(u64 inum, int fd, int verbose, const char *prepend)
                        fspath->elem_cnt, fspath->elem_missed);
 
        for (i = 0; i < fspath->elem_cnt; ++i) {
-               char **str = (char **)fspath->val;
-               str[i] += (unsigned long)fspath->val;
+               u64 ptr;
+               char *str;
+               ptr = (u64)(unsigned long)fspath->val;
+               ptr += fspath->val[i];
+               str = (char *)(unsigned long)ptr;
                if (prepend)
-                       printf("%s/%s\n", prepend, str[i]);
+                       printf("%s/%s\n", prepend, str);
                else
-                       printf("%s\n", str[i]);
+                       printf("%s\n", str);
        }
 
 out:
        free(fspath);
-       return ret;
+       return !!ret;
 }
 
 static const char * const cmd_inode_resolve_usage[] = {
        "btrfs inspect-internal inode-resolve [-v] <inode> <path>",
        "Get file system paths for the given inode",
+       "",
+       "-v   verbose mode",
        NULL
 };
 
@@ -85,6 +93,8 @@ static int cmd_inode_resolve(int argc, char **argv)
 {
        int fd;
        int verbose = 0;
+       int ret;
+       DIR *dirstream = NULL;
 
        optind = 1;
        while (1) {
@@ -104,19 +114,27 @@ static int cmd_inode_resolve(int argc, char **argv)
        if (check_argc_exact(argc - optind, 2))
                usage(cmd_inode_resolve_usage);
 
-       fd = open_file_or_dir(argv[optind+1]);
+       fd = open_file_or_dir(argv[optind+1], &dirstream);
        if (fd < 0) {
                fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind+1]);
-               return 12;
+               return 1;
        }
 
-       return __ino_to_path_fd(atoll(argv[optind]), fd, verbose,
-                               argv[optind+1]);
+       ret = __ino_to_path_fd(arg_strtou64(argv[optind]), fd, verbose,
+                              argv[optind+1]);
+       close_file_or_dir(fd, dirstream);
+       return !!ret;
+
 }
 
 static const char * const cmd_logical_resolve_usage[] = {
-       "btrfs inspect-internal logical-resolve [-Pv] <logical> <path>",
+       "btrfs inspect-internal logical-resolve [-Pv] [-s bufsize] <logical> <path>",
        "Get file system paths for the given logical address",
+       "-P          skip the path resolving and print the inodes instead",
+       "-v          verbose mode",
+       "-s bufsize  set inode container's size. This is used to increase inode",
+       "            container's size in case it is not enough to read all the ",
+       "            resolved results. The max value one can set is 64k",
        NULL
 };
 
@@ -130,12 +148,14 @@ static int cmd_logical_resolve(int argc, char **argv)
        int bytes_left;
        struct btrfs_ioctl_logical_ino_args loi;
        struct btrfs_data_container *inodes;
+       u64 size = 4096;
        char full_path[4096];
        char *path_ptr;
+       DIR *dirstream = NULL;
 
        optind = 1;
        while (1) {
-               int c = getopt(argc, argv, "Pv");
+               int c = getopt(argc, argv, "Pvs:");
                if (c < 0)
                        break;
 
@@ -146,6 +166,9 @@ static int cmd_logical_resolve(int argc, char **argv)
                case 'v':
                        verbose = 1;
                        break;
+               case 's':
+                       size = arg_strtou64(optarg);
+                       break;
                default:
                        usage(cmd_logical_resolve_usage);
                }
@@ -154,15 +177,17 @@ static int cmd_logical_resolve(int argc, char **argv)
        if (check_argc_exact(argc - optind, 2))
                usage(cmd_logical_resolve_usage);
 
-       inodes = malloc(4096);
+       size = min(size, (u64)64 * 1024);
+       inodes = malloc(size);
        if (!inodes)
                return 1;
 
-       loi.logical = atoll(argv[optind]);
-       loi.size = 4096;
-       loi.inodes = (u64)inodes;
+       memset(inodes, 0, sizeof(*inodes));
+       loi.logical = arg_strtou64(argv[optind]);
+       loi.size = size;
+       loi.inodes = (uintptr_t)inodes;
 
-       fd = open_file_or_dir(argv[optind+1]);
+       fd = open_file_or_dir(argv[optind+1], &dirstream);
        if (fd < 0) {
                fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind+1]);
                ret = 12;
@@ -176,8 +201,9 @@ static int cmd_logical_resolve(int argc, char **argv)
        }
 
        if (verbose)
-               printf("ioctl ret=%d, bytes_left=%lu, bytes_missing=%lu, "
-                       "cnt=%d, missed=%d\n", ret,
+               printf("ioctl ret=%d, total_size=%llu, bytes_left=%lu, "
+                       "bytes_missing=%lu, cnt=%d, missed=%d\n",
+                       ret, size,
                        (unsigned long)inodes->bytes_left,
                        (unsigned long)inodes->bytes_missing,
                        inodes->elem_cnt, inodes->elem_missed);
@@ -194,11 +220,14 @@ static int cmd_logical_resolve(int argc, char **argv)
                u64 root = inodes->val[i+2];
                int path_fd;
                char *name;
+               DIR *dirs = NULL;
 
                if (getpath) {
-                       name = path_for_root(fd, root);
-                       if (IS_ERR(name))
-                               return PTR_ERR(name);
+                       name = btrfs_list_path_for_root(fd, root);
+                       if (IS_ERR(name)) {
+                               ret = PTR_ERR(name);
+                               goto out;
+                       }
                        if (!name) {
                                path_ptr[-1] = '\0';
                                path_fd = fd;
@@ -208,7 +237,7 @@ static int cmd_logical_resolve(int argc, char **argv)
                                                name);
                                BUG_ON(ret >= bytes_left);
                                free(name);
-                               path_fd = open_file_or_dir(full_path);
+                               path_fd = open_file_or_dir(full_path, &dirs);
                                if (path_fd < 0) {
                                        fprintf(stderr, "ERROR: can't access "
                                                "'%s'\n", full_path);
@@ -216,6 +245,8 @@ static int cmd_logical_resolve(int argc, char **argv)
                                }
                        }
                        __ino_to_path_fd(inum, path_fd, verbose, full_path);
+                       if (path_fd != fd)
+                               close_file_or_dir(path_fd, dirs);
                } else {
                        printf("inode %llu offset %llu root %llu\n", inum,
                                offset, root);
@@ -223,8 +254,88 @@ static int cmd_logical_resolve(int argc, char **argv)
        }
 
 out:
+       close_file_or_dir(fd, dirstream);
        free(inodes);
-       return ret;
+       return !!ret;
+}
+
+static const char * const cmd_subvolid_resolve_usage[] = {
+       "btrfs inspect-internal subvolid-resolve <subvolid> <path>",
+       "Get file system paths for the given subvolume ID.",
+       NULL
+};
+
+static int cmd_subvolid_resolve(int argc, char **argv)
+{
+       int ret;
+       int fd = -1;
+       u64 subvol_id;
+       char path[BTRFS_PATH_NAME_MAX + 1];
+       DIR *dirstream = NULL;
+
+       if (check_argc_exact(argc, 3))
+               usage(cmd_subvolid_resolve_usage);
+
+       fd = open_file_or_dir(argv[2], &dirstream);
+       if (fd < 0) {
+               fprintf(stderr, "ERROR: can't access '%s'\n", argv[2]);
+               ret = -ENOENT;
+               goto out;
+       }
+
+       subvol_id = arg_strtou64(argv[1]);
+       ret = btrfs_subvolid_resolve(fd, path, sizeof(path), subvol_id);
+
+       if (ret) {
+               fprintf(stderr,
+                       "%s: btrfs_subvolid_resolve(subvol_id %llu) failed with ret=%d\n",
+                       argv[0], (unsigned long long)subvol_id, ret);
+               goto out;
+       }
+
+       path[BTRFS_PATH_NAME_MAX] = '\0';
+       printf("%s\n", path);
+
+out:
+       close_file_or_dir(fd, dirstream);
+       return ret ? 1 : 0;
+}
+
+static const char* const cmd_rootid_usage[] = {
+       "btrfs inspect-internal rootid <path>",
+       "Get tree ID of the containing subvolume of path.",
+       NULL
+};
+
+static int cmd_rootid(int argc, char **argv)
+{
+       int ret;
+       int fd = -1;
+       u64 rootid;
+       DIR *dirstream = NULL;
+
+       if (check_argc_exact(argc, 2))
+               usage(cmd_rootid_usage);
+
+       fd = open_file_or_dir(argv[1], &dirstream);
+       if (fd < 0) {
+               fprintf(stderr, "ERROR: can't access '%s'\n", argv[1]);
+               ret = -ENOENT;
+               goto out;
+       }
+
+       ret = lookup_ino_rootid(fd, &rootid);
+       if (ret) {
+               fprintf(stderr, "%s: rootid failed with ret=%d\n",
+                       argv[0], ret);
+               goto out;
+       }
+
+       printf("%llu\n", (unsigned long long)rootid);
+out:
+       close_file_or_dir(fd, dirstream);
+
+       return !!ret;
 }
 
 const struct cmd_group inspect_cmd_group = {
@@ -233,7 +344,10 @@ const struct cmd_group inspect_cmd_group = {
                        NULL, 0 },
                { "logical-resolve", cmd_logical_resolve,
                        cmd_logical_resolve_usage, NULL, 0 },
-               { 0, 0, 0, 0, 0 }
+               { "subvolid-resolve", cmd_subvolid_resolve,
+                       cmd_subvolid_resolve_usage, NULL, 0 },
+               { "rootid", cmd_rootid, cmd_rootid_usage, NULL, 0 },
+               NULL_CMD_STRUCT
        }
 };