Re: [PATCH v5 8/8] btrfs: new ioctls to do logical-inode and inode-path resolving

2011-07-22 Thread Jan Schmidt
On 21.07.2011 22:14, Andi Kleen wrote:
 Jan Schmidt list.bt...@jan-o-sch.net writes:
 +
 +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;
 
 This really needs to be root-only for obvious reasons.
 The same for the ino_path function
 
 +
 +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(loi-size, 4096);
 
 This is likely a root hole. loi-size is signed! Consider the case
 of a negative value being passed in.
 
 Same for the earlier function.

Sigh. Thanks for pointing these out. Shouldn't release code that was
fine for development without carefully reconsidering such things. I'll
send a v6.

-Jan
--
To unsubscribe from this list: send the line unsubscribe linux-btrfs in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 8/8] btrfs: new ioctls to do logical-inode and inode-path resolving

2011-07-21 Thread Jan Schmidt
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.bt...@jan-o-sch.net
---
 fs/btrfs/ioctl.c |  134 ++
 fs/btrfs/ioctl.h |   19 
 2 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index a3c4751..5299b40 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -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)
@@ -2836,6 +2837,135 @@ 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;
+
+   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(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;
+
+   inodes-size -= 3 * sizeof(u64);
+   if (inodes-size  0) {
+   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-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;
+
+   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(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)
 {
@@ -2893,6 +3023,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:
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h

Re: [PATCH v5 8/8] btrfs: new ioctls to do logical-inode and inode-path resolving

2011-07-21 Thread Andi Kleen
Jan Schmidt list.bt...@jan-o-sch.net writes:
 +
 +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;

This really needs to be root-only for obvious reasons.
The same for the ino_path function

 +
 + 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(loi-size, 4096);

This is likely a root hole. loi-size is signed! Consider the case
of a negative value being passed in.

Same for the earlier function.

-Andi
-- 
a...@linux.intel.com -- Speaking for myself only
--
To unsubscribe from this list: send the line unsubscribe linux-btrfs in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html