aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 645a17927a8..ac2a28f4fa1 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -48,6 +48,7 @@
48#include "print-tree.h" 48#include "print-tree.h"
49#include "volumes.h" 49#include "volumes.h"
50#include "locking.h" 50#include "locking.h"
51#include "ctree.h"
51 52
52/* Mask out flags that are inappropriate for the given type of inode. */ 53/* Mask out flags that are inappropriate for the given type of inode. */
53static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) 54static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
@@ -743,6 +744,97 @@ out:
743 return ret; 744 return ret;
744} 745}
745 746
747/*
748 Search INODE_REFs to identify path name of 'dirid' directory
749 in a 'tree_id' tree. and sets path name to 'name'.
750*/
751static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
752 u64 tree_id, u64 dirid, char *name)
753{
754 struct btrfs_root *root;
755 struct btrfs_key key;
756 char *name_stack, *ptr;
757 int ret = -1;
758 int slot;
759 int len;
760 int total_len = 0;
761 struct btrfs_inode_ref *iref;
762 struct extent_buffer *l;
763 struct btrfs_path *path;
764
765 if (dirid == BTRFS_FIRST_FREE_OBJECTID) {
766 name[0]='\0';
767 return 0;
768 }
769
770 path = btrfs_alloc_path();
771 if (!path)
772 return -ENOMEM;
773
774 name_stack = kzalloc(BTRFS_PATH_NAME_MAX+1, GFP_NOFS);
775 if (!name_stack) {
776 btrfs_free_path(path);
777 return -ENOMEM;
778 }
779
780 ptr = &name_stack[BTRFS_PATH_NAME_MAX];
781
782 key.objectid = tree_id;
783 key.type = BTRFS_ROOT_ITEM_KEY;
784 key.offset = (u64)-1;
785 root = btrfs_read_fs_root_no_name(info, &key);
786 if (IS_ERR(root)) {
787 printk(KERN_ERR "could not find root %llu\n", tree_id);
788 return -ENOENT;
789 }
790
791 key.objectid = dirid;
792 key.type = BTRFS_INODE_REF_KEY;
793 key.offset = 0;
794
795 while(1) {
796 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
797 if (ret < 0)
798 goto out;
799
800 l = path->nodes[0];
801 slot = path->slots[0];
802 btrfs_item_key_to_cpu(l, &key, slot);
803
804 if (ret > 0 && (key.objectid != dirid ||
805 key.type != BTRFS_INODE_REF_KEY))
806 goto out;
807
808 iref = btrfs_item_ptr(l, slot, struct btrfs_inode_ref);
809 len = btrfs_inode_ref_name_len(l, iref);
810 ptr -= len + 1;
811 total_len += len + 1;
812 if (ptr < name_stack)
813 goto out;
814
815 *(ptr + len) = '/';
816 read_extent_buffer(l, ptr,(unsigned long)(iref + 1), len);
817
818 if (key.offset == BTRFS_FIRST_FREE_OBJECTID)
819 break;
820
821 btrfs_release_path(root, path);
822 key.objectid = key.offset;
823 key.offset = 0;
824 dirid = key.objectid;
825
826 }
827 if (ptr < name_stack)
828 goto out;
829 strncpy(name, ptr, total_len);
830 name[total_len]='\0';
831 ret = 0;
832out:
833 btrfs_free_path(path);
834 kfree(name_stack);
835 return ret;
836}
837
746static noinline int btrfs_ioctl_snap_destroy(struct file *file, 838static noinline int btrfs_ioctl_snap_destroy(struct file *file,
747 void __user *arg) 839 void __user *arg)
748{ 840{