diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2011-07-07 10:48:38 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2011-09-29 06:54:28 -0400 |
commit | d7728c960dccf775b92f2c4139f1216275a45c44 (patch) | |
tree | 76d8ea34fe47a1557f0cf5e558aa3cb525f39c70 | |
parent | 0ef8e45158f97dde4801b535e25f70f7caf01a27 (diff) |
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 <list.btrfs@jan-o-sch.net>
-rw-r--r-- | fs/btrfs/ioctl.c | 143 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 19 |
2 files changed, 162 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 538f65a79ec5..7f57efa76d11 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "volumes.h" | 51 | #include "volumes.h" |
52 | #include "locking.h" | 52 | #include "locking.h" |
53 | #include "inode-map.h" | 53 | #include "inode-map.h" |
54 | #include "backref.h" | ||
54 | 55 | ||
55 | /* Mask out flags that are inappropriate for the given type of inode. */ | 56 | /* Mask out flags that are inappropriate for the given type of inode. */ |
56 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 57 | 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, | |||
2855 | return ret; | 2856 | return ret; |
2856 | } | 2857 | } |
2857 | 2858 | ||
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 | |||
2858 | long btrfs_ioctl(struct file *file, unsigned int | 2997 | long btrfs_ioctl(struct file *file, unsigned int |
2859 | cmd, unsigned long arg) | 2998 | cmd, unsigned long arg) |
2860 | { | 2999 | { |
@@ -2912,6 +3051,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
2912 | return btrfs_ioctl_tree_search(file, argp); | 3051 | return btrfs_ioctl_tree_search(file, argp); |
2913 | case BTRFS_IOC_INO_LOOKUP: | 3052 | case BTRFS_IOC_INO_LOOKUP: |
2914 | return btrfs_ioctl_ino_lookup(file, argp); | 3053 | 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); | ||
2915 | case BTRFS_IOC_SPACE_INFO: | 3058 | case BTRFS_IOC_SPACE_INFO: |
2916 | return btrfs_ioctl_space_info(root, argp); | 3059 | return btrfs_ioctl_space_info(root, argp); |
2917 | case BTRFS_IOC_SYNC: | 3060 | case BTRFS_IOC_SYNC: |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 1857e3871843..2da30d4950e6 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -204,6 +204,20 @@ struct btrfs_data_container { | |||
204 | }; | 204 | }; |
205 | }; | 205 | }; |
206 | 206 | ||
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 | |||
207 | #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ | 221 | #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ |
208 | struct btrfs_ioctl_vol_args) | 222 | struct btrfs_ioctl_vol_args) |
209 | #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ | 223 | #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ |
@@ -259,4 +273,9 @@ struct btrfs_data_container { | |||
259 | struct btrfs_ioctl_dev_info_args) | 273 | struct btrfs_ioctl_dev_info_args) |
260 | #define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ | 274 | #define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ |
261 | struct btrfs_ioctl_fs_info_args) | 275 | 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 | |||
262 | #endif | 281 | #endif |