blob: f665221409ac7efab140609e7f93cdd07b8d83f6 [file] [log] [blame]
Chris Mason2e635a22007-03-21 11:12:56 -04001#include <linux/module.h>
Chris Mason9f5fae22007-03-20 14:38:32 -04002#include "ctree.h"
3#include "disk-io.h"
4#include "transaction.h"
5
Chris Mason5be6f7f2007-04-05 13:35:25 -04006int 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;
32error:
33 btrfs_free_path(path);
34 return ret;
35}
36
Chris Mason9f5fae22007-03-20 14:38:32 -040037/*
38 * walks the btree of allocated inodes and find a hole.
39 */
40int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
41 struct btrfs_root *fs_root,
42 u64 dirid, u64 *objectid)
43{
Chris Mason7cfcc172007-04-02 14:53:59 -040044 struct btrfs_path *path;
Chris Mason9f5fae22007-03-20 14:38:32 -040045 struct btrfs_key key;
46 int ret;
47 u64 hole_size = 0;
48 int slot = 0;
Chris Masone20d96d2007-03-22 12:13:20 -040049 u64 last_ino = 0;
Chris Mason9f5fae22007-03-20 14:38:32 -040050 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
Chris Mason7cfcc172007-04-02 14:53:59 -040056 path = btrfs_alloc_path();
57 BUG_ON(!path);
Chris Masonb1a4d962007-04-04 15:27:52 -040058 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;
Chris Masonb1a4d962007-04-04 15:27:52 -040062 search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
63 search_key.objectid = search_start;
64 search_key.offset = 0;
65
Chris Mason7cfcc172007-04-02 14:53:59 -040066 btrfs_init_path(path);
Chris Mason9f5fae22007-03-20 14:38:32 -040067 start_found = 0;
Chris Mason7cfcc172007-04-02 14:53:59 -040068 ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0);
Chris Mason9f5fae22007-03-20 14:38:32 -040069 if (ret < 0)
70 goto error;
71
Chris Mason7cfcc172007-04-02 14:53:59 -040072 if (path->slots[0] > 0)
73 path->slots[0]--;
Chris Mason9f5fae22007-03-20 14:38:32 -040074
75 while (1) {
Chris Mason7cfcc172007-04-02 14:53:59 -040076 l = btrfs_buffer_leaf(path->nodes[0]);
77 slot = path->slots[0];
Chris Mason9f5fae22007-03-20 14:38:32 -040078 if (slot >= btrfs_header_nritems(&l->header)) {
Chris Mason7cfcc172007-04-02 14:53:59 -040079 ret = btrfs_next_leaf(root, path);
Chris Mason9f5fae22007-03-20 14:38:32 -040080 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;
Chris Mason7cfcc172007-04-02 14:53:59 -0400107 path->slots[0]++;
Chris Mason9f5fae22007-03-20 14:38:32 -0400108 }
109 // FIXME -ENOSPC
110found:
111 root->fs_info->last_inode_alloc = *objectid;
Chris Mason7cfcc172007-04-02 14:53:59 -0400112 btrfs_release_path(root, path);
113 btrfs_free_path(path);
Chris Mason9f5fae22007-03-20 14:38:32 -0400114 BUG_ON(*objectid < search_start);
115 return 0;
116error:
Chris Mason7cfcc172007-04-02 14:53:59 -0400117 btrfs_release_path(root, path);
118 btrfs_free_path(path);
Chris Mason9f5fae22007-03-20 14:38:32 -0400119 return ret;
120}
121
122int 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;
Chris Mason7cfcc172007-04-02 14:53:59 -0400127 struct btrfs_path *path;
Chris Mason9f5fae22007-03-20 14:38:32 -0400128 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;
Chris Mason7cfcc172007-04-02 14:53:59 -0400136 path = btrfs_alloc_path();
137 BUG_ON(!path);
138 btrfs_init_path(path);
139 ret = btrfs_insert_empty_item(trans, inode_root, path, &key,
Chris Mason9f5fae22007-03-20 14:38:32 -0400140 sizeof(struct btrfs_inode_map_item));
141 if (ret)
142 goto out;
143
Chris Mason7cfcc172007-04-02 14:53:59 -0400144 inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
145 path->slots[0], struct btrfs_inode_map_item);
Chris Mason9f5fae22007-03-20 14:38:32 -0400146 btrfs_cpu_key_to_disk(&inode_item->key, location);
Chris Mason7cfcc172007-04-02 14:53:59 -0400147 btrfs_mark_buffer_dirty(path->nodes[0]);
Chris Mason5be6f7f2007-04-05 13:35:25 -0400148 if (objectid > fs_root->fs_info->highest_inode)
149 fs_root->fs_info->highest_inode = objectid;
Chris Mason9f5fae22007-03-20 14:38:32 -0400150out:
Chris Mason7cfcc172007-04-02 14:53:59 -0400151 btrfs_release_path(inode_root, path);
152 btrfs_free_path(path);
Chris Mason9f5fae22007-03-20 14:38:32 -0400153 return ret;
154}
155
156int 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