Skip to content

Commit d7728c9

Browse files
author
Jan Schmidt
committed
btrfs: new ioctls to do logical->inode and inode->path resolving
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 <[email protected]>
1 parent 0ef8e45 commit d7728c9

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

fs/btrfs/ioctl.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "volumes.h"
5252
#include "locking.h"
5353
#include "inode-map.h"
54+
#include "backref.h"
5455

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

2859+
static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
2860+
{
2861+
int ret = 0;
2862+
int i;
2863+
unsigned long rel_ptr;
2864+
int size;
2865+
struct btrfs_ioctl_ino_path_args *ipa;
2866+
struct inode_fs_paths *ipath = NULL;
2867+
struct btrfs_path *path;
2868+
2869+
if (!capable(CAP_SYS_ADMIN))
2870+
return -EPERM;
2871+
2872+
path = btrfs_alloc_path();
2873+
if (!path) {
2874+
ret = -ENOMEM;
2875+
goto out;
2876+
}
2877+
2878+
ipa = memdup_user(arg, sizeof(*ipa));
2879+
if (IS_ERR(ipa)) {
2880+
ret = PTR_ERR(ipa);
2881+
ipa = NULL;
2882+
goto out;
2883+
}
2884+
2885+
size = min_t(u32, ipa->size, 4096);
2886+
ipath = init_ipath(size, root, path);
2887+
if (IS_ERR(ipath)) {
2888+
ret = PTR_ERR(ipath);
2889+
ipath = NULL;
2890+
goto out;
2891+
}
2892+
2893+
ret = paths_from_inode(ipa->inum, ipath);
2894+
if (ret < 0)
2895+
goto out;
2896+
2897+
for (i = 0; i < ipath->fspath->elem_cnt; ++i) {
2898+
rel_ptr = ipath->fspath->str[i] - (char *)ipath->fspath->str;
2899+
ipath->fspath->str[i] = (void *)rel_ptr;
2900+
}
2901+
2902+
ret = copy_to_user(ipa->fspath, ipath->fspath, size);
2903+
if (ret) {
2904+
ret = -EFAULT;
2905+
goto out;
2906+
}
2907+
2908+
out:
2909+
btrfs_free_path(path);
2910+
free_ipath(ipath);
2911+
kfree(ipa);
2912+
2913+
return ret;
2914+
}
2915+
2916+
static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
2917+
{
2918+
struct btrfs_data_container *inodes = ctx;
2919+
const size_t c = 3 * sizeof(u64);
2920+
2921+
if (inodes->bytes_left >= c) {
2922+
inodes->bytes_left -= c;
2923+
inodes->val[inodes->elem_cnt] = inum;
2924+
inodes->val[inodes->elem_cnt + 1] = offset;
2925+
inodes->val[inodes->elem_cnt + 2] = root;
2926+
inodes->elem_cnt += 3;
2927+
} else {
2928+
inodes->bytes_missing += c - inodes->bytes_left;
2929+
inodes->bytes_left = 0;
2930+
inodes->elem_missed += 3;
2931+
}
2932+
2933+
return 0;
2934+
}
2935+
2936+
static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
2937+
void __user *arg)
2938+
{
2939+
int ret = 0;
2940+
int size;
2941+
u64 extent_offset;
2942+
struct btrfs_ioctl_logical_ino_args *loi;
2943+
struct btrfs_data_container *inodes = NULL;
2944+
struct btrfs_path *path = NULL;
2945+
struct btrfs_key key;
2946+
2947+
if (!capable(CAP_SYS_ADMIN))
2948+
return -EPERM;
2949+
2950+
loi = memdup_user(arg, sizeof(*loi));
2951+
if (IS_ERR(loi)) {
2952+
ret = PTR_ERR(loi);
2953+
loi = NULL;
2954+
goto out;
2955+
}
2956+
2957+
path = btrfs_alloc_path();
2958+
if (!path) {
2959+
ret = -ENOMEM;
2960+
goto out;
2961+
}
2962+
2963+
size = min_t(u32, loi->size, 4096);
2964+
inodes = init_data_container(size);
2965+
if (IS_ERR(inodes)) {
2966+
ret = PTR_ERR(inodes);
2967+
inodes = NULL;
2968+
goto out;
2969+
}
2970+
2971+
ret = extent_from_logical(root->fs_info, loi->logical, path, &key);
2972+
2973+
if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
2974+
ret = -ENOENT;
2975+
if (ret < 0)
2976+
goto out;
2977+
2978+
extent_offset = loi->logical - key.objectid;
2979+
ret = iterate_extent_inodes(root->fs_info, path, key.objectid,
2980+
extent_offset, build_ino_list, inodes);
2981+
2982+
if (ret < 0)
2983+
goto out;
2984+
2985+
ret = copy_to_user(loi->inodes, inodes, size);
2986+
if (ret)
2987+
ret = -EFAULT;
2988+
2989+
out:
2990+
btrfs_free_path(path);
2991+
kfree(inodes);
2992+
kfree(loi);
2993+
2994+
return ret;
2995+
}
2996+
28582997
long btrfs_ioctl(struct file *file, unsigned int
28592998
cmd, unsigned long arg)
28602999
{
@@ -2912,6 +3051,10 @@ long btrfs_ioctl(struct file *file, unsigned int
29123051
return btrfs_ioctl_tree_search(file, argp);
29133052
case BTRFS_IOC_INO_LOOKUP:
29143053
return btrfs_ioctl_ino_lookup(file, argp);
3054+
case BTRFS_IOC_INO_PATHS:
3055+
return btrfs_ioctl_ino_to_path(root, argp);
3056+
case BTRFS_IOC_LOGICAL_INO:
3057+
return btrfs_ioctl_logical_to_ino(root, argp);
29153058
case BTRFS_IOC_SPACE_INFO:
29163059
return btrfs_ioctl_space_info(root, argp);
29173060
case BTRFS_IOC_SYNC:

fs/btrfs/ioctl.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,20 @@ struct btrfs_data_container {
204204
};
205205
};
206206

207+
struct btrfs_ioctl_ino_path_args {
208+
__u64 inum; /* in */
209+
__u32 size; /* in */
210+
__u64 reserved[4];
211+
struct btrfs_data_container *fspath; /* out */
212+
};
213+
214+
struct btrfs_ioctl_logical_ino_args {
215+
__u64 logical; /* in */
216+
__u32 size; /* in */
217+
__u64 reserved[4];
218+
struct btrfs_data_container *inodes; /* out */
219+
};
220+
207221
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
208222
struct btrfs_ioctl_vol_args)
209223
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -259,4 +273,9 @@ struct btrfs_data_container {
259273
struct btrfs_ioctl_dev_info_args)
260274
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
261275
struct btrfs_ioctl_fs_info_args)
276+
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
277+
struct btrfs_ioctl_ino_path_args)
278+
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
279+
struct btrfs_ioctl_ino_path_args)
280+
262281
#endif

0 commit comments

Comments
 (0)