bring back the inode number directory index
[platform/upstream/btrfs-progs.git] / dir-item.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "kerncompat.h"
4 #include "radix-tree.h"
5 #include "ctree.h"
6 #include "disk-io.h"
7 #include "hash.h"
8 #include "transaction.h"
9
10 static struct btrfs_dir_item *insert_with_overflow(struct
11                                                    btrfs_trans_handle *trans,
12                                                    struct btrfs_root *root,
13                                                    struct btrfs_path *path,
14                                                    struct btrfs_key *cpu_key,
15                                                    u32 data_size)
16 {
17         int ret;
18         char *ptr;
19         struct btrfs_item *item;
20         struct btrfs_leaf *leaf;
21
22         ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
23         if (ret == -EEXIST) {
24                 ret = btrfs_extend_item(trans, root, path, data_size);
25                 BUG_ON(ret > 0);
26                 if (ret)
27                         return NULL;
28         }
29         BUG_ON(ret > 0);
30         leaf = &path->nodes[0]->leaf;
31         item = leaf->items + path->slots[0];
32         ptr = btrfs_item_ptr(leaf, path->slots[0], char);
33         BUG_ON(data_size > btrfs_item_size(item));
34         ptr += btrfs_item_size(item) - data_size;
35         return (struct btrfs_dir_item *)ptr;
36 }
37
38 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
39                           *root, char *name, int name_len, u64 dir,
40                           struct btrfs_key *location, u8 type)
41 {
42         int ret = 0;
43         struct btrfs_path path;
44         struct btrfs_dir_item *dir_item;
45         char *name_ptr;
46         struct btrfs_key key;
47         u32 data_size;
48
49         key.objectid = dir;
50         key.flags = 0;
51         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
52         if (name_len == 1 && *name == '.')
53                 key.offset = 1;
54         else if (name_len == 2 && name[0] == '.' && name[1] == '.')
55                 key.offset = 2;
56         else
57                 ret = btrfs_name_hash(name, name_len, &key.offset);
58         BUG_ON(ret);
59         btrfs_init_path(&path);
60         data_size = sizeof(*dir_item) + name_len;
61         dir_item = insert_with_overflow(trans, root, &path, &key, data_size);
62         if (!dir_item) {
63                 ret = -1;
64                 goto out;
65         }
66         btrfs_cpu_key_to_disk(&dir_item->location, location);
67         btrfs_set_dir_type(dir_item, type);
68         btrfs_set_dir_flags(dir_item, 0);
69         btrfs_set_dir_name_len(dir_item, name_len);
70         name_ptr = (char *)(dir_item + 1);
71         memcpy(name_ptr, name, name_len);
72
73         /* FIXME, use some real flag for selecting the extra index */
74         if (root == root->fs_info->tree_root)
75                 goto out;
76
77         btrfs_release_path(root, &path);
78         btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
79         key.offset = location->objectid;
80         dir_item = insert_with_overflow(trans, root, &path, &key, data_size);
81         if (!dir_item) {
82                 ret = -1;
83                 goto out;
84         }
85         btrfs_cpu_key_to_disk(&dir_item->location, location);
86         btrfs_set_dir_type(dir_item, type);
87         btrfs_set_dir_flags(dir_item, 0);
88         btrfs_set_dir_name_len(dir_item, name_len);
89         name_ptr = (char *)(dir_item + 1);
90         memcpy(name_ptr, name, name_len);
91 out:
92         btrfs_release_path(root, &path);
93         return ret;
94 }
95
96 int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
97                           *root, struct btrfs_path *path, u64 dir, char *name,
98                           int name_len, int mod)
99 {
100         int ret;
101         struct btrfs_key key;
102         int ins_len = mod < 0 ? -1 : 0;
103         int cow = mod != 0;
104
105         key.objectid = dir;
106         key.flags = 0;
107         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
108         ret = btrfs_name_hash(name, name_len, &key.offset);
109         BUG_ON(ret);
110         ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
111         return ret;
112 }
113
114 int btrfs_match_dir_item_name(struct btrfs_root *root,
115                               struct btrfs_path *path, char
116                               *name, int name_len)
117 {
118         struct btrfs_dir_item *dir_item;
119         char *name_ptr;
120
121         dir_item = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0],
122                                   struct btrfs_dir_item);
123         if (btrfs_dir_name_len(dir_item) != name_len)
124                 return 0;
125         name_ptr = (char *)(dir_item + 1);
126         if (memcmp(name_ptr, name, name_len))
127                 return 0;
128         return 1;
129 }