start of support for subvolumes
[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,
32                           struct btrfs_key *location, 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_cpu_key_to_disk(&dir_item->location, location);
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         /* FIXME, use some real flag for selecting the extra index */
67         if (root == root->fs_info->tree_root)
68                 goto out;
69
70         btrfs_release_path(root, &path);
71         btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
72         key.offset = location->objectid;
73         ret = insert_with_overflow(trans, root, &path, &key, data_size);
74         if (ret)
75                 goto out;
76
77         dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0],
78                                   struct btrfs_dir_item);
79         btrfs_cpu_key_to_disk(&dir_item->location, location);
80         btrfs_set_dir_type(dir_item, type);
81         btrfs_set_dir_flags(dir_item, 0);
82         btrfs_set_dir_name_len(dir_item, name_len);
83         name_ptr = (char *)(dir_item + 1);
84         memcpy(name_ptr, name, name_len);
85 out:
86         btrfs_release_path(root, &path);
87         return ret;
88 }
89
90 int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
91                           *root, struct btrfs_path *path, u64 dir, char *name,
92                           int name_len, int mod)
93 {
94         int ret;
95         struct btrfs_key key;
96         int ins_len = mod < 0 ? -1 : 0;
97         int cow = mod != 0;
98
99         key.objectid = dir;
100         key.flags = 0;
101         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
102         btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX);
103         ret = btrfs_name_hash(name, name_len, &key.offset);
104         BUG_ON(ret);
105         ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
106         return ret;
107 }
108
109 int btrfs_match_dir_item_name(struct btrfs_root *root,
110                               struct btrfs_path *path, char
111                               *name, int name_len)
112 {
113         struct btrfs_dir_item *dir_item;
114         char *name_ptr;
115
116         dir_item = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0],
117                                   struct btrfs_dir_item);
118         if (btrfs_dir_name_len(dir_item) != name_len)
119                 return 0;
120         name_ptr = (char *)(dir_item + 1);
121         if (memcmp(name_ptr, name, name_len))
122                 return 0;
123         return 1;
124 }