Btrfs: dirindex optimizations
[safe/jmp/linux-2.6] / fs / btrfs / inode-map.c
1 #include <linux/module.h>
2 #include "ctree.h"
3 #include "disk-io.h"
4 #include "transaction.h"
5
6 int btrfs_find_highest_inode(struct btrfs_root *fs_root, u64 *objectid)
7 {
8         struct btrfs_path *path;
9         int ret;
10         struct btrfs_leaf *l;
11         struct btrfs_root *root = fs_root->fs_info->inode_root;
12         struct btrfs_key search_key;
13         int slot;
14
15         path = btrfs_alloc_path();
16         BUG_ON(!path);
17
18         search_key.objectid = (u64)-1;
19         search_key.offset = (u64)-1;
20         ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
21         if (ret < 0)
22                 goto error;
23         BUG_ON(ret == 0);
24         if (path->slots[0] > 0) {
25                 slot = path->slots[0] - 1;
26                 l = btrfs_buffer_leaf(path->nodes[0]);
27                 *objectid = btrfs_disk_key_objectid(&l->items[slot].key);
28         } else {
29                 *objectid = BTRFS_FIRST_FREE_OBJECTID;
30         }
31         ret = 0;
32 error:
33         btrfs_free_path(path);
34         return ret;
35 }
36
37 /*
38  * walks the btree of allocated inodes and find a hole.
39  */
40 int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
41                              struct btrfs_root *fs_root,
42                              u64 dirid, u64 *objectid)
43 {
44         struct btrfs_path *path;
45         struct btrfs_key key;
46         int ret;
47         u64 hole_size = 0;
48         int slot = 0;
49         u64 last_ino = 0;
50         int start_found;
51         struct btrfs_leaf *l;
52         struct btrfs_root *root = fs_root->fs_info->inode_root;
53         struct btrfs_key search_key;
54         u64 search_start = dirid;
55
56         path = btrfs_alloc_path();
57         BUG_ON(!path);
58         search_key.flags = 0;
59         btrfs_set_key_type(&search_key, BTRFS_INODE_MAP_ITEM_KEY);
60
61         search_start = fs_root->fs_info->last_inode_alloc;
62         search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
63         search_key.objectid = search_start;
64         search_key.offset = 0;
65
66         btrfs_init_path(path);
67         start_found = 0;
68         ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0);
69         if (ret < 0)
70                 goto error;
71
72         if (path->slots[0] > 0)
73                 path->slots[0]--;
74
75         while (1) {
76                 l = btrfs_buffer_leaf(path->nodes[0]);
77                 slot = path->slots[0];
78                 if (slot >= btrfs_header_nritems(&l->header)) {
79                         ret = btrfs_next_leaf(root, path);
80                         if (ret == 0)
81                                 continue;
82                         if (ret < 0)
83                                 goto error;
84                         if (!start_found) {
85                                 *objectid = search_start;
86                                 start_found = 1;
87                                 goto found;
88                         }
89                         *objectid = last_ino > search_start ?
90                                 last_ino : search_start;
91                         goto found;
92                 }
93                 btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
94                 if (key.objectid >= search_start) {
95                         if (start_found) {
96                                 if (last_ino < search_start)
97                                         last_ino = search_start;
98                                 hole_size = key.objectid - last_ino;
99                                 if (hole_size > 0) {
100                                         *objectid = last_ino;
101                                         goto found;
102                                 }
103                         }
104                 }
105                 start_found = 1;
106                 last_ino = key.objectid + 1;
107                 path->slots[0]++;
108         }
109         // FIXME -ENOSPC
110 found:
111         root->fs_info->last_inode_alloc = *objectid;
112         btrfs_release_path(root, path);
113         btrfs_free_path(path);
114         BUG_ON(*objectid < search_start);
115         return 0;
116 error:
117         btrfs_release_path(root, path);
118         btrfs_free_path(path);
119         return ret;
120 }
121
122 int btrfs_insert_inode_map(struct btrfs_trans_handle *trans,
123                            struct btrfs_root *fs_root,
124                            u64 objectid, struct btrfs_key *location)
125 {
126         int ret = 0;
127         struct btrfs_path *path;
128         struct btrfs_inode_map_item *inode_item;
129         struct btrfs_key key;
130         struct btrfs_root *inode_root = fs_root->fs_info->inode_root;
131
132         key.objectid = objectid;
133         key.flags = 0;
134         btrfs_set_key_type(&key, BTRFS_INODE_MAP_ITEM_KEY);
135         key.offset = 0;
136         path = btrfs_alloc_path();
137         BUG_ON(!path);
138         btrfs_init_path(path);
139         ret = btrfs_insert_empty_item(trans, inode_root, path, &key,
140                                       sizeof(struct btrfs_inode_map_item));
141         if (ret)
142                 goto out;
143
144         inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
145                                     path->slots[0], struct btrfs_inode_map_item);
146         btrfs_cpu_key_to_disk(&inode_item->key, location);
147         btrfs_mark_buffer_dirty(path->nodes[0]);
148         if (objectid > fs_root->fs_info->highest_inode)
149                 fs_root->fs_info->highest_inode = objectid;
150 out:
151         btrfs_release_path(inode_root, path);
152         btrfs_free_path(path);
153         return ret;
154 }
155
156 int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans,
157                            struct btrfs_root *fs_root, struct btrfs_path *path,
158                            u64 objectid, int mod)
159 {
160         int ret;
161         struct btrfs_key key;
162         int ins_len = mod < 0 ? -1 : 0;
163         int cow = mod != 0;
164         struct btrfs_root *inode_root = fs_root->fs_info->inode_root;
165
166         key.objectid = objectid;
167         key.flags = 0;
168         key.offset = 0;
169         btrfs_set_key_type(&key, BTRFS_INODE_MAP_ITEM_KEY);
170         ret = btrfs_search_slot(trans, inode_root, &key, path, ins_len, cow);
171         return ret;
172 }
173