finish off inode indexing in dirs, add overflows
[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 int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root
11                             *root, struct btrfs_path *path, struct btrfs_key
12                             *cpu_key, u32 data_size)
13 {
14         int overflow;
15         int ret;
16
17         ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
18         overflow = btrfs_key_overflow(cpu_key);
19
20         while(ret == -EEXIST && overflow < BTRFS_KEY_OVERFLOW_MAX) {
21                 overflow++;
22                 btrfs_set_key_overflow(cpu_key, overflow);
23                 btrfs_release_path(root, path);
24                 ret = btrfs_insert_empty_item(trans, root, path, cpu_key,
25                                               data_size);
26         }
27         return ret;
28 }
29
30 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
31                           *root, char *name, int name_len, u64 dir, u64
32                           objectid, u8 type)
33 {
34         int ret = 0;
35         struct btrfs_path path;
36         struct btrfs_dir_item *dir_item;
37         char *name_ptr;
38         struct btrfs_key key;
39         u32 data_size;
40
41         key.objectid = dir;
42         key.flags = 0;
43         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
44         if (name_len == 1 && *name == '.')
45                 key.offset = 1;
46         else if (name_len == 2 && name[0] == '.' && name[1] == '.')
47                 key.offset = 2;
48         else
49                 ret = btrfs_name_hash(name, name_len, &key.offset);
50         BUG_ON(ret);
51         btrfs_init_path(&path);
52         data_size = sizeof(*dir_item) + name_len;
53         ret = insert_with_overflow(trans, root, &path, &key, data_size);
54         if (ret)
55                 goto out;
56
57         dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0],
58                                   struct btrfs_dir_item);
59         btrfs_set_dir_objectid(dir_item, objectid);
60         btrfs_set_dir_type(dir_item, type);
61         btrfs_set_dir_flags(dir_item, 0);
62         btrfs_set_dir_name_len(dir_item, name_len);
63         name_ptr = (char *)(dir_item + 1);
64         memcpy(name_ptr, name, name_len);
65
66         btrfs_release_path(root, &path);
67         btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
68         key.offset = objectid;
69         ret = insert_with_overflow(trans, root, &path, &key, data_size);
70         if (ret)
71                 goto out;
72
73         dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0],
74                                   struct btrfs_dir_item);
75         btrfs_set_dir_objectid(dir_item, objectid);
76         btrfs_set_dir_type(dir_item, type);
77         btrfs_set_dir_flags(dir_item, 0);
78         btrfs_set_dir_name_len(dir_item, name_len);
79         name_ptr = (char *)(dir_item + 1);
80         memcpy(name_ptr, name, name_len);
81 out:
82         btrfs_release_path(root, &path);
83         return ret;
84 }
85
86 int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
87                           *root, struct btrfs_path *path, u64 dir, char *name,
88                           int name_len, int mod)
89 {
90         int ret;
91         struct btrfs_key key;
92         int ins_len = mod < 0 ? -1 : 0;
93         int cow = mod != 0;
94
95         key.objectid = dir;
96         key.flags = 0;
97         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
98         btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX);
99         ret = btrfs_name_hash(name, name_len, &key.offset);
100         BUG_ON(ret);
101         ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
102         return ret;
103 }
104
105 int btrfs_match_dir_item_name(struct btrfs_root *root,
106                               struct btrfs_path *path, char
107                               *name, int name_len)
108 {
109         struct btrfs_dir_item *dir_item;
110         char *name_ptr;
111
112         dir_item = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0],
113                                   struct btrfs_dir_item);
114         if (btrfs_dir_name_len(dir_item) != name_len)
115                 return 0;
116         name_ptr = (char *)(dir_item + 1);
117         if (memcmp(name_ptr, name, name_len))
118                 return 0;
119         return 1;
120 }