Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 274705
b: refs/heads/master
c: d7728c9
h: refs/heads/master
i:
  274703: 14842a4
v: v3
  • Loading branch information
Jan Schmidt committed Sep 29, 2011
1 parent e99144c commit 54bab32
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0ef8e45158f97dde4801b535e25f70f7caf01a27
refs/heads/master: d7728c960dccf775b92f2c4139f1216275a45c44
143 changes: 143 additions & 0 deletions trunk/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 trunk/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 54bab32

Please sign in to comment.