Btrfs-progs: added ioctls and commands to resolve inodes and logical addrs

two new commands that make use of the new path resolving functions
implemented for scrub, doing the resolving in-kernel. the result for both
commands is a list of files belonging to that inode / logical address.

Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
master
Jan Schmidt 2011-11-02 11:42:30 -04:00 committed by Chris Mason
parent dcdbc1ce18
commit 6055e73604
5 changed files with 262 additions and 1 deletions

View File

@ -899,3 +899,38 @@ int find_updated_files(int fd, u64 root_id, u64 oldest_gen)
printf("transid marker was %llu\n", (unsigned long long)max_found);
return ret;
}
char *path_for_root(int fd, u64 root)
{
struct root_lookup root_lookup;
struct rb_node *n;
char *ret_path = NULL;
int ret;
ret = __list_subvol_search(fd, &root_lookup);
if (ret < 0)
return ERR_PTR(ret);
ret = __list_subvol_fill_paths(fd, &root_lookup);
if (ret < 0)
return ERR_PTR(ret);
n = rb_last(&root_lookup.root);
while (n) {
struct root_info *entry;
u64 root_id;
u64 parent_id;
u64 level;
char *path;
entry = rb_entry(n, struct root_info, rb_node);
resolve_root(&root_lookup, entry, &root_id, &parent_id, &level,
&path);
if (root_id == root)
ret_path = path;
else
free(path);
n = rb_prev(n);
}
return ret_path;
}

10
btrfs.c
View File

@ -169,6 +169,16 @@ static struct Command commands[] = {
"Remove a device from a filesystem.",
NULL
},
{ do_ino_to_path, -2,
"inspect-internal inode-resolve", "[-v] <inode> <path>\n"
"get file system paths for the given inode.",
NULL
},
{ do_logical_to_ino, -2,
"inspect-internal logical-resolve", "[-v] [-P] <logical> <path>\n"
"get file system paths for the given logical address.",
NULL
},
{ 0, 0, 0, 0 }
};

View File

@ -1121,3 +1121,187 @@ int do_df_filesystem(int nargs, char **argv)
return 0;
}
static int __ino_to_path_fd(u64 inum, int fd, int verbose, const char *prepend)
{
int ret;
int i;
struct btrfs_ioctl_ino_path_args ipa;
struct btrfs_data_container *fspath;
fspath = malloc(4096);
if (!fspath)
return 1;
ipa.inum = inum;
ipa.size = 4096;
ipa.fspath = (u64)fspath;
ret = ioctl(fd, BTRFS_IOC_INO_PATHS, &ipa);
if (ret) {
printf("ioctl ret=%d, error: %s\n", ret, strerror(errno));
goto out;
}
if (verbose)
printf("ioctl ret=%d, bytes_left=%lu, bytes_missing=%lu, "
"cnt=%d, missed=%d\n", ret,
(unsigned long)fspath->bytes_left,
(unsigned long)fspath->bytes_missing,
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;
if (prepend)
printf("%s/%s\n", prepend, str[i]);
else
printf("%s\n", str[i]);
}
out:
free(fspath);
return ret;
}
int do_ino_to_path(int nargs, char **argv)
{
int fd;
int verbose = 0;
optind = 1;
while (1) {
int c = getopt(nargs, argv, "v");
if (c < 0)
break;
switch (c) {
case 'v':
verbose = 1;
break;
default:
fprintf(stderr, "invalid arguments for ipath\n");
return 1;
}
}
if (nargs - optind != 2) {
fprintf(stderr, "invalid arguments for ipath\n");
return 1;
}
fd = open_file_or_dir(argv[optind+1]);
if (fd < 0) {
fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind+1]);
return 12;
}
return __ino_to_path_fd(atoll(argv[optind]), fd, verbose,
argv[optind+1]);
}
int do_logical_to_ino(int nargs, char **argv)
{
int ret;
int fd;
int i;
int verbose = 0;
int getpath = 1;
int bytes_left;
struct btrfs_ioctl_logical_ino_args loi;
struct btrfs_data_container *inodes;
char full_path[4096];
char *path_ptr;
optind = 1;
while (1) {
int c = getopt(nargs, argv, "Pv");
if (c < 0)
break;
switch (c) {
case 'P':
getpath = 0;
break;
case 'v':
verbose = 1;
break;
default:
fprintf(stderr, "invalid arguments for ipath\n");
return 1;
}
}
if (nargs - optind != 2) {
fprintf(stderr, "invalid arguments for ipath\n");
return 1;
}
inodes = malloc(4096);
if (!inodes)
return 1;
loi.logical = atoll(argv[optind]);
loi.size = 4096;
loi.inodes = (u64)inodes;
fd = open_file_or_dir(argv[optind+1]);
if (fd < 0) {
fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind+1]);
ret = 12;
goto out;
}
ret = ioctl(fd, BTRFS_IOC_LOGICAL_INO, &loi);
if (ret) {
printf("ioctl ret=%d, error: %s\n", ret, strerror(errno));
goto out;
}
if (verbose)
printf("ioctl ret=%d, bytes_left=%lu, bytes_missing=%lu, "
"cnt=%d, missed=%d\n", ret,
(unsigned long)inodes->bytes_left,
(unsigned long)inodes->bytes_missing,
inodes->elem_cnt, inodes->elem_missed);
bytes_left = sizeof(full_path);
ret = snprintf(full_path, bytes_left, "%s/", argv[optind+1]);
path_ptr = full_path + ret;
bytes_left -= ret + 1;
BUG_ON(bytes_left < 0);
for (i = 0; i < inodes->elem_cnt; i += 3) {
u64 inum = inodes->val[i];
u64 offset = inodes->val[i+1];
u64 root = inodes->val[i+2];
int path_fd;
char *name;
if (getpath) {
name = path_for_root(fd, root);
if (IS_ERR(name))
return PTR_ERR(name);
if (!name) {
path_ptr[-1] = '\0';
path_fd = fd;
} else {
path_ptr[-1] = '/';
ret = snprintf(path_ptr, bytes_left, "%s",
name);
BUG_ON(ret >= bytes_left);
free(name);
path_fd = open_file_or_dir(full_path);
if (path_fd < 0) {
fprintf(stderr, "ERROR: can't access "
"'%s'\n", full_path);
goto out;
}
}
__ino_to_path_fd(inum, path_fd, verbose, full_path);
} else {
printf("inode %llu offset %llu root %llu\n", inum,
offset, root);
}
}
out:
free(inodes);
return ret;
}

View File

@ -39,3 +39,6 @@ int find_updated_files(int fd, u64 root_id, u64 oldest_gen);
int do_find_newer(int argc, char **argv);
int do_change_label(int argc, char **argv);
int open_file_or_dir(const char *fname);
int do_ino_to_path(int nargs, char **argv);
int do_logical_to_ino(int nargs, char **argv);
char *path_for_root(int fd, u64 root);

31
ioctl.h
View File

@ -200,6 +200,30 @@ struct btrfs_ioctl_space_args {
struct btrfs_ioctl_space_info spaces[0];
};
struct btrfs_data_container {
__u32 bytes_left; /* out -- bytes not needed to deliver output */
__u32 bytes_missing; /* out -- additional bytes needed for result */
__u32 elem_cnt; /* out */
__u32 elem_missed; /* out */
__u64 val[0]; /* out */
};
struct btrfs_ioctl_ino_path_args {
__u64 inum; /* in */
__u64 size; /* in */
__u64 reserved[4];
/* struct btrfs_data_container *fspath; out */
__u64 fspath; /* out */
};
struct btrfs_ioctl_logical_ino_args {
__u64 logical; /* in */
__u64 size; /* in */
__u64 reserved[4];
/* struct btrfs_data_container *inodes; out */
__u64 inodes;
};
/* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
struct btrfs_ioctl_vol_args)
@ -248,5 +272,10 @@ struct btrfs_ioctl_space_args {
#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \
struct btrfs_ioctl_dev_info_args)
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
struct btrfs_ioctl_fs_info_args)
struct btrfs_ioctl_fs_info_args)
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
struct btrfs_ioctl_ino_path_args)
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
struct btrfs_ioctl_ino_path_args)
#endif