btrfs: move the printk helpers out of ctree.h
[linux-block.git] / fs / btrfs / dir-item.c
CommitLineData
c1d7c514 1// SPDX-License-Identifier: GPL-2.0
6cbd5570
CM
2/*
3 * Copyright (C) 2007 Oracle. All rights reserved.
6cbd5570
CM
4 */
5
9b569ea0 6#include "messages.h"
62e2749e
CM
7#include "ctree.h"
8#include "disk-io.h"
e089f05c 9#include "transaction.h"
62e2749e 10
d352ac68
CM
11/*
12 * insert a name into a directory, doing overflow properly if there is a hash
13 * collision. data_size indicates how big the item inserted should be. On
14 * success a struct btrfs_dir_item pointer is returned, otherwise it is
15 * an ERR_PTR.
16 *
17 * The name is not copied into the dir item, you have to do that yourself.
18 */
35b7e476
CM
19static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
20 *trans,
21 struct btrfs_root *root,
22 struct btrfs_path *path,
23 struct btrfs_key *cpu_key,
e06afa83
CM
24 u32 data_size,
25 const char *name,
26 int name_len)
7fcde0e3 27{
2ff7e61e 28 struct btrfs_fs_info *fs_info = root->fs_info;
7fcde0e3 29 int ret;
7e38180e 30 char *ptr;
5f39d397 31 struct extent_buffer *leaf;
7fcde0e3
CM
32
33 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
7e38180e 34 if (ret == -EEXIST) {
e06afa83 35 struct btrfs_dir_item *di;
2ff7e61e 36 di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
e06afa83
CM
37 if (di)
38 return ERR_PTR(-EEXIST);
c71dd880 39 btrfs_extend_item(path, data_size);
143bede5 40 } else if (ret < 0)
54aa1f4d 41 return ERR_PTR(ret);
7e38180e 42 WARN_ON(ret > 0);
5f39d397 43 leaf = path->nodes[0];
7e38180e 44 ptr = btrfs_item_ptr(leaf, path->slots[0], char);
3212fa14
JB
45 ASSERT(data_size <= btrfs_item_size(leaf, path->slots[0]));
46 ptr += btrfs_item_size(leaf, path->slots[0]) - data_size;
7e38180e 47 return (struct btrfs_dir_item *)ptr;
7fcde0e3
CM
48}
49
d352ac68
CM
50/*
51 * xattrs work a lot like directories, this inserts an xattr item
52 * into the tree
53 */
5103e947 54int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
f34f57a3
YZ
55 struct btrfs_root *root,
56 struct btrfs_path *path, u64 objectid,
57 const char *name, u16 name_len,
58 const void *data, u16 data_len)
5103e947
JB
59{
60 int ret = 0;
5103e947
JB
61 struct btrfs_dir_item *dir_item;
62 unsigned long name_ptr, data_ptr;
63 struct btrfs_key key, location;
64 struct btrfs_disk_key disk_key;
65 struct extent_buffer *leaf;
66 u32 data_size;
67
b9d04c60
DS
68 if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root->fs_info))
69 return -ENOSPC;
f34f57a3
YZ
70
71 key.objectid = objectid;
962a298f 72 key.type = BTRFS_XATTR_ITEM_KEY;
df68b8a7 73 key.offset = btrfs_name_hash(name, name_len);
5103e947
JB
74
75 data_size = sizeof(*dir_item) + name_len + data_len;
76 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
77 name, name_len);
fa09200b
JB
78 if (IS_ERR(dir_item))
79 return PTR_ERR(dir_item);
5103e947
JB
80 memset(&location, 0, sizeof(location));
81
82 leaf = path->nodes[0];
83 btrfs_cpu_key_to_disk(&disk_key, &location);
84 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
85 btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
86 btrfs_set_dir_name_len(leaf, dir_item, name_len);
e02119d5 87 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
5103e947
JB
88 btrfs_set_dir_data_len(leaf, dir_item, data_len);
89 name_ptr = (unsigned long)(dir_item + 1);
90 data_ptr = (unsigned long)((char *)name_ptr + name_len);
91
92 write_extent_buffer(leaf, name, name_ptr, name_len);
93 write_extent_buffer(leaf, data, data_ptr, data_len);
94 btrfs_mark_buffer_dirty(path->nodes[0]);
95
5103e947
JB
96 return ret;
97}
98
d352ac68
CM
99/*
100 * insert a directory item in the tree, doing all the magic for
101 * both indexes. 'dir' indicates which objectid to insert it into,
102 * 'location' is the key to stuff into the directory item, 'type' is the
103 * type of the inode we're pointing to, and 'index' is the sequence number
104 * to use for the second index (if one is created).
79787eaa 105 * Will return 0 or -ENOMEM
d352ac68 106 */
684572df
LF
107int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, const char *name,
108 int name_len, struct btrfs_inode *dir,
109 struct btrfs_key *location, u8 type, u64 index)
62e2749e
CM
110{
111 int ret = 0;
e06afa83 112 int ret2 = 0;
684572df 113 struct btrfs_root *root = dir->root;
5caf2a00 114 struct btrfs_path *path;
62e2749e 115 struct btrfs_dir_item *dir_item;
5f39d397
CM
116 struct extent_buffer *leaf;
117 unsigned long name_ptr;
62e2749e 118 struct btrfs_key key;
5f39d397 119 struct btrfs_disk_key disk_key;
62e2749e
CM
120 u32 data_size;
121
8e7611cf 122 key.objectid = btrfs_ino(dir);
962a298f 123 key.type = BTRFS_DIR_ITEM_KEY;
df68b8a7 124 key.offset = btrfs_name_hash(name, name_len);
b9473439 125
5caf2a00 126 path = btrfs_alloc_path();
16cdcec7
MX
127 if (!path)
128 return -ENOMEM;
b9473439 129
16cdcec7
MX
130 btrfs_cpu_key_to_disk(&disk_key, location);
131
62e2749e 132 data_size = sizeof(*dir_item) + name_len;
e06afa83
CM
133 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
134 name, name_len);
7e38180e
CM
135 if (IS_ERR(dir_item)) {
136 ret = PTR_ERR(dir_item);
e06afa83
CM
137 if (ret == -EEXIST)
138 goto second_insert;
c2db1073 139 goto out_free;
7e38180e 140 }
62e2749e 141
5f39d397 142 leaf = path->nodes[0];
5f39d397
CM
143 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
144 btrfs_set_dir_type(leaf, dir_item, type);
5103e947 145 btrfs_set_dir_data_len(leaf, dir_item, 0);
5f39d397 146 btrfs_set_dir_name_len(leaf, dir_item, name_len);
e02119d5 147 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
5f39d397 148 name_ptr = (unsigned long)(dir_item + 1);
c5739bba 149
5f39d397
CM
150 write_extent_buffer(leaf, name, name_ptr, name_len);
151 btrfs_mark_buffer_dirty(leaf);
7e38180e 152
e06afa83 153second_insert:
7e38180e
CM
154 /* FIXME, use some real flag for selecting the extra index */
155 if (root == root->fs_info->tree_root) {
156 ret = 0;
c2db1073 157 goto out_free;
7e38180e 158 }
b3b4aa74 159 btrfs_release_path(path);
7e38180e 160
4465c8b4
LF
161 ret2 = btrfs_insert_delayed_dir_index(trans, name, name_len, dir,
162 &disk_key, type, index);
c2db1073 163out_free:
5caf2a00 164 btrfs_free_path(path);
e06afa83
CM
165 if (ret)
166 return ret;
167 if (ret2)
168 return ret2;
169 return 0;
62e2749e
CM
170}
171
a7d1c5dc
MPS
172static struct btrfs_dir_item *btrfs_lookup_match_dir(
173 struct btrfs_trans_handle *trans,
174 struct btrfs_root *root, struct btrfs_path *path,
175 struct btrfs_key *key, const char *name,
176 int name_len, int mod)
177{
178 const int ins_len = (mod < 0 ? -1 : 0);
179 const int cow = (mod != 0);
180 int ret;
181
182 ret = btrfs_search_slot(trans, root, key, path, ins_len, cow);
183 if (ret < 0)
184 return ERR_PTR(ret);
185 if (ret > 0)
186 return ERR_PTR(-ENOENT);
187
188 return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
189}
190
d352ac68 191/*
8dcbc261
FM
192 * Lookup for a directory item by name.
193 *
194 * @trans: The transaction handle to use. Can be NULL if @mod is 0.
195 * @root: The root of the target tree.
196 * @path: Path to use for the search.
197 * @dir: The inode number (objectid) of the directory.
198 * @name: The name associated to the directory entry we are looking for.
199 * @name_len: The length of the name.
200 * @mod: Used to indicate if the tree search is meant for a read only
201 * lookup, for a modification lookup or for a deletion lookup, so
202 * its value should be 0, 1 or -1, respectively.
203 *
204 * Returns: NULL if the dir item does not exists, an error pointer if an error
205 * happened, or a pointer to a dir item if a dir item exists for the given name.
d352ac68 206 */
7e38180e
CM
207struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
208 struct btrfs_root *root,
209 struct btrfs_path *path, u64 dir,
210 const char *name, int name_len,
211 int mod)
62e2749e 212{
62e2749e 213 struct btrfs_key key;
a7d1c5dc 214 struct btrfs_dir_item *di;
62e2749e
CM
215
216 key.objectid = dir;
962a298f 217 key.type = BTRFS_DIR_ITEM_KEY;
df68b8a7 218 key.offset = btrfs_name_hash(name, name_len);
5f39d397 219
a7d1c5dc
MPS
220 di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
221 if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
7e38180e
CM
222 return NULL;
223
a7d1c5dc 224 return di;
62e2749e
CM
225}
226
9c52057c
CM
227int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
228 const char *name, int name_len)
229{
230 int ret;
231 struct btrfs_key key;
232 struct btrfs_dir_item *di;
233 int data_size;
234 struct extent_buffer *leaf;
235 int slot;
236 struct btrfs_path *path;
237
9c52057c
CM
238 path = btrfs_alloc_path();
239 if (!path)
240 return -ENOMEM;
241
242 key.objectid = dir;
962a298f 243 key.type = BTRFS_DIR_ITEM_KEY;
9c52057c
CM
244 key.offset = btrfs_name_hash(name, name_len);
245
a7d1c5dc
MPS
246 di = btrfs_lookup_match_dir(NULL, root, path, &key, name, name_len, 0);
247 if (IS_ERR(di)) {
248 ret = PTR_ERR(di);
249 /* Nothing found, we're safe */
250 if (ret == -ENOENT) {
251 ret = 0;
252 goto out;
253 }
9c52057c 254
a7d1c5dc
MPS
255 if (ret < 0)
256 goto out;
9c52057c
CM
257 }
258
259 /* we found an item, look for our name in the item */
9c52057c
CM
260 if (di) {
261 /* our exact name was found */
262 ret = -EEXIST;
263 goto out;
264 }
265
266 /*
267 * see if there is room in the item to insert this
268 * name
269 */
878f2d2c 270 data_size = sizeof(*di) + name_len;
9c52057c
CM
271 leaf = path->nodes[0];
272 slot = path->slots[0];
3212fa14 273 if (data_size + btrfs_item_size(leaf, slot) +
da17066c 274 sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root->fs_info)) {
9c52057c
CM
275 ret = -EOVERFLOW;
276 } else {
277 /* plenty of insertion room */
278 ret = 0;
279 }
280out:
281 btrfs_free_path(path);
282 return ret;
283}
284
d352ac68 285/*
8dcbc261 286 * Lookup for a directory index item by name and index number.
d352ac68 287 *
8dcbc261
FM
288 * @trans: The transaction handle to use. Can be NULL if @mod is 0.
289 * @root: The root of the target tree.
290 * @path: Path to use for the search.
291 * @dir: The inode number (objectid) of the directory.
292 * @index: The index number.
293 * @name: The name associated to the directory entry we are looking for.
294 * @name_len: The length of the name.
295 * @mod: Used to indicate if the tree search is meant for a read only
296 * lookup, for a modification lookup or for a deletion lookup, so
297 * its value should be 0, 1 or -1, respectively.
298 *
299 * Returns: NULL if the dir index item does not exists, an error pointer if an
300 * error happened, or a pointer to a dir item if the dir index item exists and
301 * matches the criteria (name and index number).
d352ac68 302 */
7e38180e
CM
303struct btrfs_dir_item *
304btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
305 struct btrfs_root *root,
306 struct btrfs_path *path, u64 dir,
8dcbc261 307 u64 index, const char *name, int name_len,
7e38180e
CM
308 int mod)
309{
8dcbc261 310 struct btrfs_dir_item *di;
7e38180e 311 struct btrfs_key key;
7e38180e
CM
312
313 key.objectid = dir;
962a298f 314 key.type = BTRFS_DIR_INDEX_KEY;
8dcbc261 315 key.offset = index;
7e38180e 316
8dcbc261
FM
317 di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
318 if (di == ERR_PTR(-ENOENT))
319 return NULL;
320
321 return di;
7e38180e
CM
322}
323
4df27c4d
YZ
324struct btrfs_dir_item *
325btrfs_search_dir_index_item(struct btrfs_root *root,
326 struct btrfs_path *path, u64 dirid,
327 const char *name, int name_len)
328{
4df27c4d
YZ
329 struct btrfs_dir_item *di;
330 struct btrfs_key key;
4df27c4d
YZ
331 int ret;
332
333 key.objectid = dirid;
334 key.type = BTRFS_DIR_INDEX_KEY;
335 key.offset = 0;
336
9dcbe16f 337 btrfs_for_each_slot(root, &key, &key, path, ret) {
4df27c4d
YZ
338 if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY)
339 break;
340
2ff7e61e
JM
341 di = btrfs_match_dir_item_name(root->fs_info, path,
342 name, name_len);
4df27c4d
YZ
343 if (di)
344 return di;
4df27c4d 345 }
9dcbe16f
GN
346 /* Adjust return code if the key was not found in the next leaf. */
347 if (ret > 0)
348 ret = 0;
349
350 return ERR_PTR(ret);
4df27c4d
YZ
351}
352
5103e947
JB
353struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
354 struct btrfs_root *root,
355 struct btrfs_path *path, u64 dir,
356 const char *name, u16 name_len,
357 int mod)
358{
5103e947 359 struct btrfs_key key;
a7d1c5dc 360 struct btrfs_dir_item *di;
5103e947
JB
361
362 key.objectid = dir;
962a298f 363 key.type = BTRFS_XATTR_ITEM_KEY;
df68b8a7 364 key.offset = btrfs_name_hash(name, name_len);
a7d1c5dc
MPS
365
366 di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
367 if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
5103e947
JB
368 return NULL;
369
a7d1c5dc 370 return di;
5103e947
JB
371}
372
d352ac68
CM
373/*
374 * helper function to look at the directory item pointed to by 'path'
375 * this walks through all the entries in a dir item and finds one
376 * for a specific name.
377 */
2ff7e61e 378struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info,
5f5bc6b1
FM
379 struct btrfs_path *path,
380 const char *name, int name_len)
62e2749e 381{
62e2749e 382 struct btrfs_dir_item *dir_item;
5f39d397 383 unsigned long name_ptr;
7e38180e
CM
384 u32 total_len;
385 u32 cur = 0;
386 u32 this_len;
5f39d397 387 struct extent_buffer *leaf;
a8a2ee0c 388
5f39d397 389 leaf = path->nodes[0];
7e38180e 390 dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
22a94d44 391
3212fa14 392 total_len = btrfs_item_size(leaf, path->slots[0]);
d397712b 393 while (cur < total_len) {
5f39d397 394 this_len = sizeof(*dir_item) +
5103e947
JB
395 btrfs_dir_name_len(leaf, dir_item) +
396 btrfs_dir_data_len(leaf, dir_item);
5f39d397 397 name_ptr = (unsigned long)(dir_item + 1);
7e38180e 398
5f39d397
CM
399 if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
400 memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
7e38180e
CM
401 return dir_item;
402
403 cur += this_len;
404 dir_item = (struct btrfs_dir_item *)((char *)dir_item +
405 this_len);
406 }
407 return NULL;
62e2749e 408}
7e38180e 409
d352ac68
CM
410/*
411 * given a pointer into a directory item, delete it. This
412 * handles items that have more than one entry in them.
413 */
7e38180e
CM
414int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
415 struct btrfs_root *root,
416 struct btrfs_path *path,
417 struct btrfs_dir_item *di)
418{
419
5f39d397 420 struct extent_buffer *leaf;
7e38180e
CM
421 u32 sub_item_len;
422 u32 item_len;
54aa1f4d 423 int ret = 0;
7e38180e 424
5f39d397 425 leaf = path->nodes[0];
5103e947
JB
426 sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) +
427 btrfs_dir_data_len(leaf, di);
3212fa14 428 item_len = btrfs_item_size(leaf, path->slots[0]);
5f39d397 429 if (sub_item_len == item_len) {
7e38180e 430 ret = btrfs_del_item(trans, root, path);
7e38180e 431 } else {
5f39d397
CM
432 /* MARKER */
433 unsigned long ptr = (unsigned long)di;
434 unsigned long start;
435
436 start = btrfs_item_ptr_offset(leaf, path->slots[0]);
437 memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
7e38180e 438 item_len - (ptr + sub_item_len - start));
78ac4f9e 439 btrfs_truncate_item(path, item_len - sub_item_len, 1);
7e38180e 440 }
411fc6bc 441 return ret;
7e38180e 442}