GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / fs / btrfs / dir-item.c
blobfd3e294a67231eae9666d901855ef50ce7a4fe1e
1 /*
2 * Copyright (C) 2007 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include "ctree.h"
20 #include "disk-io.h"
21 #include "hash.h"
22 #include "transaction.h"
25 * insert a name into a directory, doing overflow properly if there is a hash
26 * collision. data_size indicates how big the item inserted should be. On
27 * success a struct btrfs_dir_item pointer is returned, otherwise it is
28 * an ERR_PTR.
30 * The name is not copied into the dir item, you have to do that yourself.
32 static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
33 *trans,
34 struct btrfs_root *root,
35 struct btrfs_path *path,
36 struct btrfs_key *cpu_key,
37 u32 data_size,
38 const char *name,
39 int name_len)
41 int ret;
42 char *ptr;
43 struct btrfs_item *item;
44 struct extent_buffer *leaf;
46 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
47 if (ret == -EEXIST) {
48 struct btrfs_dir_item *di;
49 di = btrfs_match_dir_item_name(root, path, name, name_len);
50 if (di)
51 return ERR_PTR(-EEXIST);
52 ret = btrfs_extend_item(trans, root, path, data_size);
53 WARN_ON(ret > 0);
55 if (ret < 0)
56 return ERR_PTR(ret);
57 WARN_ON(ret > 0);
58 leaf = path->nodes[0];
59 item = btrfs_item_nr(leaf, path->slots[0]);
60 ptr = btrfs_item_ptr(leaf, path->slots[0], char);
61 BUG_ON(data_size > btrfs_item_size(leaf, item));
62 ptr += btrfs_item_size(leaf, item) - data_size;
63 return (struct btrfs_dir_item *)ptr;
67 * xattrs work a lot like directories, this inserts an xattr item
68 * into the tree
70 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
71 struct btrfs_root *root,
72 struct btrfs_path *path, u64 objectid,
73 const char *name, u16 name_len,
74 const void *data, u16 data_len)
76 int ret = 0;
77 struct btrfs_dir_item *dir_item;
78 unsigned long name_ptr, data_ptr;
79 struct btrfs_key key, location;
80 struct btrfs_disk_key disk_key;
81 struct extent_buffer *leaf;
82 u32 data_size;
84 BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));
86 key.objectid = objectid;
87 btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
88 key.offset = btrfs_name_hash(name, name_len);
90 data_size = sizeof(*dir_item) + name_len + data_len;
91 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
92 name, name_len);
93 BUG_ON(IS_ERR(dir_item));
94 memset(&location, 0, sizeof(location));
96 leaf = path->nodes[0];
97 btrfs_cpu_key_to_disk(&disk_key, &location);
98 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
99 btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
100 btrfs_set_dir_name_len(leaf, dir_item, name_len);
101 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
102 btrfs_set_dir_data_len(leaf, dir_item, data_len);
103 name_ptr = (unsigned long)(dir_item + 1);
104 data_ptr = (unsigned long)((char *)name_ptr + name_len);
106 write_extent_buffer(leaf, name, name_ptr, name_len);
107 write_extent_buffer(leaf, data, data_ptr, data_len);
108 btrfs_mark_buffer_dirty(path->nodes[0]);
110 return ret;
114 * insert a directory item in the tree, doing all the magic for
115 * both indexes. 'dir' indicates which objectid to insert it into,
116 * 'location' is the key to stuff into the directory item, 'type' is the
117 * type of the inode we're pointing to, and 'index' is the sequence number
118 * to use for the second index (if one is created).
120 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
121 *root, const char *name, int name_len, u64 dir,
122 struct btrfs_key *location, u8 type, u64 index)
124 int ret = 0;
125 int ret2 = 0;
126 struct btrfs_path *path;
127 struct btrfs_dir_item *dir_item;
128 struct extent_buffer *leaf;
129 unsigned long name_ptr;
130 struct btrfs_key key;
131 struct btrfs_disk_key disk_key;
132 u32 data_size;
134 key.objectid = dir;
135 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
136 key.offset = btrfs_name_hash(name, name_len);
138 path = btrfs_alloc_path();
139 path->leave_spinning = 1;
141 data_size = sizeof(*dir_item) + name_len;
142 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
143 name, name_len);
144 if (IS_ERR(dir_item)) {
145 ret = PTR_ERR(dir_item);
146 if (ret == -EEXIST)
147 goto second_insert;
148 goto out;
151 leaf = path->nodes[0];
152 btrfs_cpu_key_to_disk(&disk_key, location);
153 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
154 btrfs_set_dir_type(leaf, dir_item, type);
155 btrfs_set_dir_data_len(leaf, dir_item, 0);
156 btrfs_set_dir_name_len(leaf, dir_item, name_len);
157 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
158 name_ptr = (unsigned long)(dir_item + 1);
160 write_extent_buffer(leaf, name, name_ptr, name_len);
161 btrfs_mark_buffer_dirty(leaf);
163 second_insert:
164 if (root == root->fs_info->tree_root) {
165 ret = 0;
166 goto out;
168 btrfs_release_path(root, path);
170 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
171 key.offset = index;
172 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
173 name, name_len);
174 if (IS_ERR(dir_item)) {
175 ret2 = PTR_ERR(dir_item);
176 goto out;
178 leaf = path->nodes[0];
179 btrfs_cpu_key_to_disk(&disk_key, location);
180 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
181 btrfs_set_dir_type(leaf, dir_item, type);
182 btrfs_set_dir_data_len(leaf, dir_item, 0);
183 btrfs_set_dir_name_len(leaf, dir_item, name_len);
184 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
185 name_ptr = (unsigned long)(dir_item + 1);
186 write_extent_buffer(leaf, name, name_ptr, name_len);
187 btrfs_mark_buffer_dirty(leaf);
188 out:
189 btrfs_free_path(path);
190 if (ret)
191 return ret;
192 if (ret2)
193 return ret2;
194 return 0;
198 * lookup a directory item based on name. 'dir' is the objectid
199 * we're searching in, and 'mod' tells us if you plan on deleting the
200 * item (use mod < 0) or changing the options (use mod > 0)
202 struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
203 struct btrfs_root *root,
204 struct btrfs_path *path, u64 dir,
205 const char *name, int name_len,
206 int mod)
208 int ret;
209 struct btrfs_key key;
210 int ins_len = mod < 0 ? -1 : 0;
211 int cow = mod != 0;
212 struct btrfs_key found_key;
213 struct extent_buffer *leaf;
215 key.objectid = dir;
216 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
218 key.offset = btrfs_name_hash(name, name_len);
220 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
221 if (ret < 0)
222 return ERR_PTR(ret);
223 if (ret > 0) {
224 if (path->slots[0] == 0)
225 return NULL;
226 path->slots[0]--;
229 leaf = path->nodes[0];
230 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
232 if (found_key.objectid != dir ||
233 btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY ||
234 found_key.offset != key.offset)
235 return NULL;
237 return btrfs_match_dir_item_name(root, path, name, name_len);
241 * lookup a directory item based on index. 'dir' is the objectid
242 * we're searching in, and 'mod' tells us if you plan on deleting the
243 * item (use mod < 0) or changing the options (use mod > 0)
245 * The name is used to make sure the index really points to the name you were
246 * looking for.
248 struct btrfs_dir_item *
249 btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
250 struct btrfs_root *root,
251 struct btrfs_path *path, u64 dir,
252 u64 objectid, const char *name, int name_len,
253 int mod)
255 int ret;
256 struct btrfs_key key;
257 int ins_len = mod < 0 ? -1 : 0;
258 int cow = mod != 0;
260 key.objectid = dir;
261 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
262 key.offset = objectid;
264 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
265 if (ret < 0)
266 return ERR_PTR(ret);
267 if (ret > 0)
268 return ERR_PTR(-ENOENT);
269 return btrfs_match_dir_item_name(root, path, name, name_len);
272 struct btrfs_dir_item *
273 btrfs_search_dir_index_item(struct btrfs_root *root,
274 struct btrfs_path *path, u64 dirid,
275 const char *name, int name_len)
277 struct extent_buffer *leaf;
278 struct btrfs_dir_item *di;
279 struct btrfs_key key;
280 u32 nritems;
281 int ret;
283 key.objectid = dirid;
284 key.type = BTRFS_DIR_INDEX_KEY;
285 key.offset = 0;
287 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
288 if (ret < 0)
289 return ERR_PTR(ret);
291 leaf = path->nodes[0];
292 nritems = btrfs_header_nritems(leaf);
294 while (1) {
295 if (path->slots[0] >= nritems) {
296 ret = btrfs_next_leaf(root, path);
297 if (ret < 0)
298 return ERR_PTR(ret);
299 if (ret > 0)
300 break;
301 leaf = path->nodes[0];
302 nritems = btrfs_header_nritems(leaf);
303 continue;
306 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
307 if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY)
308 break;
310 di = btrfs_match_dir_item_name(root, path, name, name_len);
311 if (di)
312 return di;
314 path->slots[0]++;
316 return NULL;
319 struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
320 struct btrfs_root *root,
321 struct btrfs_path *path, u64 dir,
322 const char *name, u16 name_len,
323 int mod)
325 int ret;
326 struct btrfs_key key;
327 int ins_len = mod < 0 ? -1 : 0;
328 int cow = mod != 0;
329 struct btrfs_key found_key;
330 struct extent_buffer *leaf;
332 key.objectid = dir;
333 btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
334 key.offset = btrfs_name_hash(name, name_len);
335 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
336 if (ret < 0)
337 return ERR_PTR(ret);
338 if (ret > 0) {
339 if (path->slots[0] == 0)
340 return NULL;
341 path->slots[0]--;
344 leaf = path->nodes[0];
345 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
347 if (found_key.objectid != dir ||
348 btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY ||
349 found_key.offset != key.offset)
350 return NULL;
352 return btrfs_match_dir_item_name(root, path, name, name_len);
356 * helper function to look at the directory item pointed to by 'path'
357 * this walks through all the entries in a dir item and finds one
358 * for a specific name.
360 struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
361 struct btrfs_path *path,
362 const char *name, int name_len)
364 struct btrfs_dir_item *dir_item;
365 unsigned long name_ptr;
366 u32 total_len;
367 u32 cur = 0;
368 u32 this_len;
369 struct extent_buffer *leaf;
371 leaf = path->nodes[0];
372 dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
373 total_len = btrfs_item_size_nr(leaf, path->slots[0]);
374 while (cur < total_len) {
375 this_len = sizeof(*dir_item) +
376 btrfs_dir_name_len(leaf, dir_item) +
377 btrfs_dir_data_len(leaf, dir_item);
378 name_ptr = (unsigned long)(dir_item + 1);
380 if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
381 memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
382 return dir_item;
384 cur += this_len;
385 dir_item = (struct btrfs_dir_item *)((char *)dir_item +
386 this_len);
388 return NULL;
392 * given a pointer into a directory item, delete it. This
393 * handles items that have more than one entry in them.
395 int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
396 struct btrfs_root *root,
397 struct btrfs_path *path,
398 struct btrfs_dir_item *di)
401 struct extent_buffer *leaf;
402 u32 sub_item_len;
403 u32 item_len;
404 int ret = 0;
406 leaf = path->nodes[0];
407 sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) +
408 btrfs_dir_data_len(leaf, di);
409 item_len = btrfs_item_size_nr(leaf, path->slots[0]);
410 if (sub_item_len == item_len) {
411 ret = btrfs_del_item(trans, root, path);
412 } else {
413 /* MARKER */
414 unsigned long ptr = (unsigned long)di;
415 unsigned long start;
417 start = btrfs_item_ptr_offset(leaf, path->slots[0]);
418 memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
419 item_len - (ptr + sub_item_len - start));
420 ret = btrfs_truncate_item(trans, root, path,
421 item_len - sub_item_len, 1);
423 return 0;