diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 645a17927a8f..ac2a28f4fa1a 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. */ |
| 53 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 54 | static 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 | */ | ||
| 751 | static 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; | ||
| 832 | out: | ||
| 833 | btrfs_free_path(path); | ||
| 834 | kfree(name_stack); | ||
| 835 | return ret; | ||
| 836 | } | ||
| 837 | |||
| 746 | static noinline int btrfs_ioctl_snap_destroy(struct file *file, | 838 | static noinline int btrfs_ioctl_snap_destroy(struct file *file, |
| 747 | void __user *arg) | 839 | void __user *arg) |
| 748 | { | 840 | { |
