Skip to content

Commit

Permalink
btrfs: new ioctls to do logical->inode and inode->path resolving
Browse files Browse the repository at this point in the history
these ioctls make use of the new functions initially added for scrub. they
return all inodes belonging to a logical address (BTRFS_IOC_LOGICAL_INO) and
all paths belonging to an inode (BTRFS_IOC_INO_PATHS).

Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
  • Loading branch information
Jan Schmidt committed Sep 29, 2011
1 parent 0ef8e45 commit d7728c9
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
143 changes: 143 additions & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "volumes.h"
#include "locking.h"
#include "inode-map.h"
#include "backref.h"

/* Mask out flags that are inappropriate for the given type of inode. */
static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
Expand Down Expand Up @@ -2855,6 +2856,144 @@ static long btrfs_ioctl_scrub_progress(struct btrfs_root *root,
return ret;
}

static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
{
int ret = 0;
int i;
unsigned long rel_ptr;
int size;
struct btrfs_ioctl_ino_path_args *ipa;
struct inode_fs_paths *ipath = NULL;
struct btrfs_path *path;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

path = btrfs_alloc_path();
if (!path) {
ret = -ENOMEM;
goto out;
}

ipa = memdup_user(arg, sizeof(*ipa));
if (IS_ERR(ipa)) {
ret = PTR_ERR(ipa);
ipa = NULL;
goto out;
}

size = min_t(u32, ipa->size, 4096);
ipath = init_ipath(size, root, path);
if (IS_ERR(ipath)) {
ret = PTR_ERR(ipath);
ipath = NULL;
goto out;
}

ret = paths_from_inode(ipa->inum, ipath);
if (ret < 0)
goto out;

for (i = 0; i < ipath->fspath->elem_cnt; ++i) {
rel_ptr = ipath->fspath->str[i] - (char *)ipath->fspath->str;
ipath->fspath->str[i] = (void *)rel_ptr;
}

ret = copy_to_user(ipa->fspath, ipath->fspath, size);
if (ret) {
ret = -EFAULT;
goto out;
}

out:
btrfs_free_path(path);
free_ipath(ipath);
kfree(ipa);

return ret;
}

static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
{
struct btrfs_data_container *inodes = ctx;
const size_t c = 3 * sizeof(u64);

if (inodes->bytes_left >= c) {
inodes->bytes_left -= c;
inodes->val[inodes->elem_cnt] = inum;
inodes->val[inodes->elem_cnt + 1] = offset;
inodes->val[inodes->elem_cnt + 2] = root;
inodes->elem_cnt += 3;
} else {
inodes->bytes_missing += c - inodes->bytes_left;
inodes->bytes_left = 0;
inodes->elem_missed += 3;
}

return 0;
}

static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
void __user *arg)
{
int ret = 0;
int size;
u64 extent_offset;
struct btrfs_ioctl_logical_ino_args *loi;
struct btrfs_data_container *inodes = NULL;
struct btrfs_path *path = NULL;
struct btrfs_key key;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

loi = memdup_user(arg, sizeof(*loi));
if (IS_ERR(loi)) {
ret = PTR_ERR(loi);
loi = NULL;
goto out;
}

path = btrfs_alloc_path();
if (!path) {
ret = -ENOMEM;
goto out;
}

size = min_t(u32, loi->size, 4096);
inodes = init_data_container(size);
if (IS_ERR(inodes)) {
ret = PTR_ERR(inodes);
inodes = NULL;
goto out;
}

ret = extent_from_logical(root->fs_info, loi->logical, path, &key);

if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
ret = -ENOENT;
if (ret < 0)
goto out;

extent_offset = loi->logical - key.objectid;
ret = iterate_extent_inodes(root->fs_info, path, key.objectid,
extent_offset, build_ino_list, inodes);

if (ret < 0)
goto out;

ret = copy_to_user(loi->inodes, inodes, size);
if (ret)
ret = -EFAULT;

out:
btrfs_free_path(path);
kfree(inodes);
kfree(loi);

return ret;
}

long btrfs_ioctl(struct file *file, unsigned int
cmd, unsigned long arg)
{
Expand Down Expand Up @@ -2912,6 +3051,10 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_tree_search(file, argp);
case BTRFS_IOC_INO_LOOKUP:
return btrfs_ioctl_ino_lookup(file, argp);
case BTRFS_IOC_INO_PATHS:
return btrfs_ioctl_ino_to_path(root, argp);
case BTRFS_IOC_LOGICAL_INO:
return btrfs_ioctl_logical_to_ino(root, argp);
case BTRFS_IOC_SPACE_INFO:
return btrfs_ioctl_space_info(root, argp);
case BTRFS_IOC_SYNC:
Expand Down
19 changes: 19 additions & 0 deletions fs/btrfs/ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,20 @@ struct btrfs_data_container {
};
};

struct btrfs_ioctl_ino_path_args {
__u64 inum; /* in */
__u32 size; /* in */
__u64 reserved[4];
struct btrfs_data_container *fspath; /* out */
};

struct btrfs_ioctl_logical_ino_args {
__u64 logical; /* in */
__u32 size; /* in */
__u64 reserved[4];
struct btrfs_data_container *inodes; /* out */
};

#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
Expand Down Expand Up @@ -259,4 +273,9 @@ struct btrfs_data_container {
struct btrfs_ioctl_dev_info_args)
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
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

0 comments on commit d7728c9

Please sign in to comment.