blob: 29e967b2c6672ff4d068af6485c60e89a29c3804 [file] [log] [blame]
Chris Mason6cbd5572007-06-12 09:07:21 -04001/*
2 * Copyright (C) 2007 Oracle. All rights reserved.
3 *
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.
7 *
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.
12 *
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.
17 */
18
Chris Mason62e27492007-03-15 12:56:47 -040019#include "ctree.h"
20#include "disk-io.h"
Chris Masone089f052007-03-16 16:20:31 -040021#include "transaction.h"
Chris Mason62e27492007-03-15 12:56:47 -040022
Chris Masond352ac62008-09-29 15:18:18 -040023/*
24 * insert a name into a directory, doing overflow properly if there is a hash
25 * collision. data_size indicates how big the item inserted should be. On
26 * success a struct btrfs_dir_item pointer is returned, otherwise it is
27 * an ERR_PTR.
28 *
29 * The name is not copied into the dir item, you have to do that yourself.
30 */
Chris Mason35b7e472007-05-02 15:53:43 -040031static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
32 *trans,
33 struct btrfs_root *root,
34 struct btrfs_path *path,
35 struct btrfs_key *cpu_key,
Chris Masone06afa82007-05-23 15:44:28 -040036 u32 data_size,
37 const char *name,
38 int name_len)
Chris Mason7fcde0e2007-04-05 12:13:21 -040039{
Jeff Mahoney2ff7e612016-06-22 18:54:24 -040040 struct btrfs_fs_info *fs_info = root->fs_info;
Chris Mason7fcde0e2007-04-05 12:13:21 -040041 int ret;
Chris Mason7e381802007-04-19 15:36:27 -040042 char *ptr;
43 struct btrfs_item *item;
Chris Mason5f39d392007-10-15 16:14:19 -040044 struct extent_buffer *leaf;
Chris Mason7fcde0e2007-04-05 12:13:21 -040045
46 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
Chris Mason7e381802007-04-19 15:36:27 -040047 if (ret == -EEXIST) {
Chris Masone06afa82007-05-23 15:44:28 -040048 struct btrfs_dir_item *di;
Jeff Mahoney2ff7e612016-06-22 18:54:24 -040049 di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
Chris Masone06afa82007-05-23 15:44:28 -040050 if (di)
51 return ERR_PTR(-EEXIST);
Jeff Mahoney2ff7e612016-06-22 18:54:24 -040052 btrfs_extend_item(fs_info, path, data_size);
Jeff Mahoney143bede2012-03-01 14:56:26 +010053 } else if (ret < 0)
Chris Mason54aa1f42007-06-22 14:16:25 -040054 return ERR_PTR(ret);
Chris Mason7e381802007-04-19 15:36:27 -040055 WARN_ON(ret > 0);
Chris Mason5f39d392007-10-15 16:14:19 -040056 leaf = path->nodes[0];
Ross Kirkdd3cc162013-09-16 15:58:09 +010057 item = btrfs_item_nr(path->slots[0]);
Chris Mason7e381802007-04-19 15:36:27 -040058 ptr = btrfs_item_ptr(leaf, path->slots[0], char);
Chris Mason5f39d392007-10-15 16:14:19 -040059 BUG_ON(data_size > btrfs_item_size(leaf, item));
60 ptr += btrfs_item_size(leaf, item) - data_size;
Chris Mason7e381802007-04-19 15:36:27 -040061 return (struct btrfs_dir_item *)ptr;
Chris Mason7fcde0e2007-04-05 12:13:21 -040062}
63
Chris Masond352ac62008-09-29 15:18:18 -040064/*
65 * xattrs work a lot like directories, this inserts an xattr item
66 * into the tree
67 */
Josef Bacik5103e942007-11-16 11:45:54 -050068int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
Yan, Zhengf34f57a2009-11-12 09:35:27 +000069 struct btrfs_root *root,
70 struct btrfs_path *path, u64 objectid,
71 const char *name, u16 name_len,
72 const void *data, u16 data_len)
Josef Bacik5103e942007-11-16 11:45:54 -050073{
74 int ret = 0;
Josef Bacik5103e942007-11-16 11:45:54 -050075 struct btrfs_dir_item *dir_item;
76 unsigned long name_ptr, data_ptr;
77 struct btrfs_key key, location;
78 struct btrfs_disk_key disk_key;
79 struct extent_buffer *leaf;
80 u32 data_size;
81
David Sterbab9d04c62017-02-17 19:42:43 +010082 if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root->fs_info))
83 return -ENOSPC;
Yan, Zhengf34f57a2009-11-12 09:35:27 +000084
85 key.objectid = objectid;
David Sterba962a2982014-06-04 18:41:45 +020086 key.type = BTRFS_XATTR_ITEM_KEY;
David Millerdf68b8a2008-02-15 10:40:52 -050087 key.offset = btrfs_name_hash(name, name_len);
Josef Bacik5103e942007-11-16 11:45:54 -050088
89 data_size = sizeof(*dir_item) + name_len + data_len;
90 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
91 name, name_len);
Josef Bacikfa092002011-05-27 12:06:11 -040092 if (IS_ERR(dir_item))
93 return PTR_ERR(dir_item);
Josef Bacik5103e942007-11-16 11:45:54 -050094 memset(&location, 0, sizeof(location));
95
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);
Chris Masone02119d2008-09-05 16:13:11 -0400101 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
Josef Bacik5103e942007-11-16 11:45:54 -0500102 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);
105
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]);
109
Josef Bacik5103e942007-11-16 11:45:54 -0500110 return ret;
111}
112
Chris Masond352ac62008-09-29 15:18:18 -0400113/*
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).
Jeff Mahoney79787ea2012-03-12 16:03:00 +0100119 * Will return 0 or -ENOMEM
Chris Masond352ac62008-09-29 15:18:18 -0400120 */
Chris Masone089f052007-03-16 16:20:31 -0400121int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
Miao Xie16cdcec2011-04-22 18:12:22 +0800122 *root, const char *name, int name_len,
Nikolay Borisov8e7611c2017-02-20 13:50:31 +0200123 struct btrfs_inode *dir, struct btrfs_key *location,
Miao Xie16cdcec2011-04-22 18:12:22 +0800124 u8 type, u64 index)
Chris Mason62e27492007-03-15 12:56:47 -0400125{
126 int ret = 0;
Chris Masone06afa82007-05-23 15:44:28 -0400127 int ret2 = 0;
Chris Mason5caf2a02007-04-02 11:20:42 -0400128 struct btrfs_path *path;
Chris Mason62e27492007-03-15 12:56:47 -0400129 struct btrfs_dir_item *dir_item;
Chris Mason5f39d392007-10-15 16:14:19 -0400130 struct extent_buffer *leaf;
131 unsigned long name_ptr;
Chris Mason62e27492007-03-15 12:56:47 -0400132 struct btrfs_key key;
Chris Mason5f39d392007-10-15 16:14:19 -0400133 struct btrfs_disk_key disk_key;
Chris Mason62e27492007-03-15 12:56:47 -0400134 u32 data_size;
135
Nikolay Borisov8e7611c2017-02-20 13:50:31 +0200136 key.objectid = btrfs_ino(dir);
David Sterba962a2982014-06-04 18:41:45 +0200137 key.type = BTRFS_DIR_ITEM_KEY;
David Millerdf68b8a2008-02-15 10:40:52 -0500138 key.offset = btrfs_name_hash(name, name_len);
Chris Masonb9473432009-03-13 11:00:37 -0400139
Chris Mason5caf2a02007-04-02 11:20:42 -0400140 path = btrfs_alloc_path();
Miao Xie16cdcec2011-04-22 18:12:22 +0800141 if (!path)
142 return -ENOMEM;
Chris Masonb9473432009-03-13 11:00:37 -0400143 path->leave_spinning = 1;
144
Miao Xie16cdcec2011-04-22 18:12:22 +0800145 btrfs_cpu_key_to_disk(&disk_key, location);
146
Chris Mason62e27492007-03-15 12:56:47 -0400147 data_size = sizeof(*dir_item) + name_len;
Chris Masone06afa82007-05-23 15:44:28 -0400148 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
149 name, name_len);
Chris Mason7e381802007-04-19 15:36:27 -0400150 if (IS_ERR(dir_item)) {
151 ret = PTR_ERR(dir_item);
Chris Masone06afa82007-05-23 15:44:28 -0400152 if (ret == -EEXIST)
153 goto second_insert;
Tsutomu Itohc2db1072011-03-01 06:48:31 +0000154 goto out_free;
Chris Mason7e381802007-04-19 15:36:27 -0400155 }
Chris Mason62e27492007-03-15 12:56:47 -0400156
Chris Mason5f39d392007-10-15 16:14:19 -0400157 leaf = path->nodes[0];
Chris Mason5f39d392007-10-15 16:14:19 -0400158 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
159 btrfs_set_dir_type(leaf, dir_item, type);
Josef Bacik5103e942007-11-16 11:45:54 -0500160 btrfs_set_dir_data_len(leaf, dir_item, 0);
Chris Mason5f39d392007-10-15 16:14:19 -0400161 btrfs_set_dir_name_len(leaf, dir_item, name_len);
Chris Masone02119d2008-09-05 16:13:11 -0400162 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
Chris Mason5f39d392007-10-15 16:14:19 -0400163 name_ptr = (unsigned long)(dir_item + 1);
Chris Masonc5739bb2007-04-10 09:27:04 -0400164
Chris Mason5f39d392007-10-15 16:14:19 -0400165 write_extent_buffer(leaf, name, name_ptr, name_len);
166 btrfs_mark_buffer_dirty(leaf);
Chris Mason7e381802007-04-19 15:36:27 -0400167
Chris Masone06afa82007-05-23 15:44:28 -0400168second_insert:
Chris Mason7e381802007-04-19 15:36:27 -0400169 /* FIXME, use some real flag for selecting the extra index */
170 if (root == root->fs_info->tree_root) {
171 ret = 0;
Tsutomu Itohc2db1072011-03-01 06:48:31 +0000172 goto out_free;
Chris Mason7e381802007-04-19 15:36:27 -0400173 }
David Sterbab3b4aa72011-04-21 01:20:15 +0200174 btrfs_release_path(path);
Chris Mason7e381802007-04-19 15:36:27 -0400175
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400176 ret2 = btrfs_insert_delayed_dir_index(trans, root->fs_info, name,
Nikolay Borisov8e7611c2017-02-20 13:50:31 +0200177 name_len, dir, &disk_key, type, index);
Tsutomu Itohc2db1072011-03-01 06:48:31 +0000178out_free:
Chris Mason5caf2a02007-04-02 11:20:42 -0400179 btrfs_free_path(path);
Chris Masone06afa82007-05-23 15:44:28 -0400180 if (ret)
181 return ret;
182 if (ret2)
183 return ret2;
184 return 0;
Chris Mason62e27492007-03-15 12:56:47 -0400185}
186
Chris Masond352ac62008-09-29 15:18:18 -0400187/*
188 * lookup a directory item based on name. 'dir' is the objectid
189 * we're searching in, and 'mod' tells us if you plan on deleting the
190 * item (use mod < 0) or changing the options (use mod > 0)
191 */
Chris Mason7e381802007-04-19 15:36:27 -0400192struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
193 struct btrfs_root *root,
194 struct btrfs_path *path, u64 dir,
195 const char *name, int name_len,
196 int mod)
Chris Mason62e27492007-03-15 12:56:47 -0400197{
Chris Mason1d4f6402007-03-15 15:18:43 -0400198 int ret;
Chris Mason62e27492007-03-15 12:56:47 -0400199 struct btrfs_key key;
Chris Mason1d4f6402007-03-15 15:18:43 -0400200 int ins_len = mod < 0 ? -1 : 0;
201 int cow = mod != 0;
Chris Mason62e27492007-03-15 12:56:47 -0400202
203 key.objectid = dir;
David Sterba962a2982014-06-04 18:41:45 +0200204 key.type = BTRFS_DIR_ITEM_KEY;
Chris Mason5f39d392007-10-15 16:14:19 -0400205
David Millerdf68b8a2008-02-15 10:40:52 -0500206 key.offset = btrfs_name_hash(name, name_len);
Chris Mason5f39d392007-10-15 16:14:19 -0400207
Chris Mason7e381802007-04-19 15:36:27 -0400208 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
209 if (ret < 0)
210 return ERR_PTR(ret);
Li Zefan85d85a72011-07-14 03:17:52 +0000211 if (ret > 0)
Chris Mason7e381802007-04-19 15:36:27 -0400212 return NULL;
213
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400214 return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
Chris Mason62e27492007-03-15 12:56:47 -0400215}
216
Chris Mason9c520572012-12-17 14:26:57 -0500217int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
218 const char *name, int name_len)
219{
220 int ret;
221 struct btrfs_key key;
222 struct btrfs_dir_item *di;
223 int data_size;
224 struct extent_buffer *leaf;
225 int slot;
226 struct btrfs_path *path;
227
228
229 path = btrfs_alloc_path();
230 if (!path)
231 return -ENOMEM;
232
233 key.objectid = dir;
David Sterba962a2982014-06-04 18:41:45 +0200234 key.type = BTRFS_DIR_ITEM_KEY;
Chris Mason9c520572012-12-17 14:26:57 -0500235 key.offset = btrfs_name_hash(name, name_len);
236
237 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
238
239 /* return back any errors */
240 if (ret < 0)
241 goto out;
242
243 /* nothing found, we're safe */
244 if (ret > 0) {
245 ret = 0;
246 goto out;
247 }
248
249 /* we found an item, look for our name in the item */
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400250 di = btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
Chris Mason9c520572012-12-17 14:26:57 -0500251 if (di) {
252 /* our exact name was found */
253 ret = -EEXIST;
254 goto out;
255 }
256
257 /*
258 * see if there is room in the item to insert this
259 * name
260 */
Filipe David Borba Manana878f2d22013-11-27 16:06:16 +0000261 data_size = sizeof(*di) + name_len;
Chris Mason9c520572012-12-17 14:26:57 -0500262 leaf = path->nodes[0];
263 slot = path->slots[0];
264 if (data_size + btrfs_item_size_nr(leaf, slot) +
Jeff Mahoneyda170662016-06-15 09:22:56 -0400265 sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root->fs_info)) {
Chris Mason9c520572012-12-17 14:26:57 -0500266 ret = -EOVERFLOW;
267 } else {
268 /* plenty of insertion room */
269 ret = 0;
270 }
271out:
272 btrfs_free_path(path);
273 return ret;
274}
275
Chris Masond352ac62008-09-29 15:18:18 -0400276/*
277 * lookup a directory item based on index. 'dir' is the objectid
278 * we're searching in, and 'mod' tells us if you plan on deleting the
279 * item (use mod < 0) or changing the options (use mod > 0)
280 *
281 * The name is used to make sure the index really points to the name you were
282 * looking for.
283 */
Chris Mason7e381802007-04-19 15:36:27 -0400284struct btrfs_dir_item *
285btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
286 struct btrfs_root *root,
287 struct btrfs_path *path, u64 dir,
288 u64 objectid, const char *name, int name_len,
289 int mod)
290{
291 int ret;
292 struct btrfs_key key;
293 int ins_len = mod < 0 ? -1 : 0;
294 int cow = mod != 0;
295
296 key.objectid = dir;
David Sterba962a2982014-06-04 18:41:45 +0200297 key.type = BTRFS_DIR_INDEX_KEY;
Chris Mason7e381802007-04-19 15:36:27 -0400298 key.offset = objectid;
299
300 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
301 if (ret < 0)
302 return ERR_PTR(ret);
303 if (ret > 0)
304 return ERR_PTR(-ENOENT);
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400305 return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
Chris Mason7e381802007-04-19 15:36:27 -0400306}
307
Yan, Zheng4df27c4d2009-09-21 15:56:00 -0400308struct btrfs_dir_item *
309btrfs_search_dir_index_item(struct btrfs_root *root,
310 struct btrfs_path *path, u64 dirid,
311 const char *name, int name_len)
312{
313 struct extent_buffer *leaf;
314 struct btrfs_dir_item *di;
315 struct btrfs_key key;
316 u32 nritems;
317 int ret;
318
319 key.objectid = dirid;
320 key.type = BTRFS_DIR_INDEX_KEY;
321 key.offset = 0;
322
323 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
324 if (ret < 0)
325 return ERR_PTR(ret);
326
327 leaf = path->nodes[0];
328 nritems = btrfs_header_nritems(leaf);
329
330 while (1) {
331 if (path->slots[0] >= nritems) {
332 ret = btrfs_next_leaf(root, path);
333 if (ret < 0)
334 return ERR_PTR(ret);
335 if (ret > 0)
336 break;
337 leaf = path->nodes[0];
338 nritems = btrfs_header_nritems(leaf);
339 continue;
340 }
341
342 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
343 if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY)
344 break;
345
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400346 di = btrfs_match_dir_item_name(root->fs_info, path,
347 name, name_len);
Yan, Zheng4df27c4d2009-09-21 15:56:00 -0400348 if (di)
349 return di;
350
351 path->slots[0]++;
352 }
353 return NULL;
354}
355
Josef Bacik5103e942007-11-16 11:45:54 -0500356struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
357 struct btrfs_root *root,
358 struct btrfs_path *path, u64 dir,
359 const char *name, u16 name_len,
360 int mod)
361{
362 int ret;
363 struct btrfs_key key;
364 int ins_len = mod < 0 ? -1 : 0;
365 int cow = mod != 0;
Josef Bacik5103e942007-11-16 11:45:54 -0500366
367 key.objectid = dir;
David Sterba962a2982014-06-04 18:41:45 +0200368 key.type = BTRFS_XATTR_ITEM_KEY;
David Millerdf68b8a2008-02-15 10:40:52 -0500369 key.offset = btrfs_name_hash(name, name_len);
Josef Bacik5103e942007-11-16 11:45:54 -0500370 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
371 if (ret < 0)
372 return ERR_PTR(ret);
Li Zefan85d85a72011-07-14 03:17:52 +0000373 if (ret > 0)
Josef Bacik5103e942007-11-16 11:45:54 -0500374 return NULL;
375
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400376 return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
Josef Bacik5103e942007-11-16 11:45:54 -0500377}
378
Chris Masond352ac62008-09-29 15:18:18 -0400379/*
380 * helper function to look at the directory item pointed to by 'path'
381 * this walks through all the entries in a dir item and finds one
382 * for a specific name.
383 */
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400384struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info,
Filipe Manana5f5bc6b2014-11-09 08:38:39 +0000385 struct btrfs_path *path,
386 const char *name, int name_len)
Chris Mason62e27492007-03-15 12:56:47 -0400387{
Chris Mason62e27492007-03-15 12:56:47 -0400388 struct btrfs_dir_item *dir_item;
Chris Mason5f39d392007-10-15 16:14:19 -0400389 unsigned long name_ptr;
Chris Mason7e381802007-04-19 15:36:27 -0400390 u32 total_len;
391 u32 cur = 0;
392 u32 this_len;
Chris Mason5f39d392007-10-15 16:14:19 -0400393 struct extent_buffer *leaf;
Chris Masona8a2ee02007-03-16 08:46:49 -0400394
Chris Mason5f39d392007-10-15 16:14:19 -0400395 leaf = path->nodes[0];
Chris Mason7e381802007-04-19 15:36:27 -0400396 dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
Josef Bacik22a94d42011-03-16 16:47:17 -0400397
Chris Mason5f39d392007-10-15 16:14:19 -0400398 total_len = btrfs_item_size_nr(leaf, path->slots[0]);
Chris Masond3977122009-01-05 21:25:51 -0500399 while (cur < total_len) {
Chris Mason5f39d392007-10-15 16:14:19 -0400400 this_len = sizeof(*dir_item) +
Josef Bacik5103e942007-11-16 11:45:54 -0500401 btrfs_dir_name_len(leaf, dir_item) +
402 btrfs_dir_data_len(leaf, dir_item);
Chris Mason5f39d392007-10-15 16:14:19 -0400403 name_ptr = (unsigned long)(dir_item + 1);
Chris Mason7e381802007-04-19 15:36:27 -0400404
Chris Mason5f39d392007-10-15 16:14:19 -0400405 if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
406 memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
Chris Mason7e381802007-04-19 15:36:27 -0400407 return dir_item;
408
409 cur += this_len;
410 dir_item = (struct btrfs_dir_item *)((char *)dir_item +
411 this_len);
412 }
413 return NULL;
Chris Mason62e27492007-03-15 12:56:47 -0400414}
Chris Mason7e381802007-04-19 15:36:27 -0400415
Chris Masond352ac62008-09-29 15:18:18 -0400416/*
417 * given a pointer into a directory item, delete it. This
418 * handles items that have more than one entry in them.
419 */
Chris Mason7e381802007-04-19 15:36:27 -0400420int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
421 struct btrfs_root *root,
422 struct btrfs_path *path,
423 struct btrfs_dir_item *di)
424{
425
Chris Mason5f39d392007-10-15 16:14:19 -0400426 struct extent_buffer *leaf;
Chris Mason7e381802007-04-19 15:36:27 -0400427 u32 sub_item_len;
428 u32 item_len;
Chris Mason54aa1f42007-06-22 14:16:25 -0400429 int ret = 0;
Chris Mason7e381802007-04-19 15:36:27 -0400430
Chris Mason5f39d392007-10-15 16:14:19 -0400431 leaf = path->nodes[0];
Josef Bacik5103e942007-11-16 11:45:54 -0500432 sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) +
433 btrfs_dir_data_len(leaf, di);
Chris Mason5f39d392007-10-15 16:14:19 -0400434 item_len = btrfs_item_size_nr(leaf, path->slots[0]);
435 if (sub_item_len == item_len) {
Chris Mason7e381802007-04-19 15:36:27 -0400436 ret = btrfs_del_item(trans, root, path);
Chris Mason7e381802007-04-19 15:36:27 -0400437 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400438 /* MARKER */
439 unsigned long ptr = (unsigned long)di;
440 unsigned long start;
441
442 start = btrfs_item_ptr_offset(leaf, path->slots[0]);
443 memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
Chris Mason7e381802007-04-19 15:36:27 -0400444 item_len - (ptr + sub_item_len - start));
Jeff Mahoney2ff7e612016-06-22 18:54:24 -0400445 btrfs_truncate_item(root->fs_info, path,
446 item_len - sub_item_len, 1);
Chris Mason7e381802007-04-19 15:36:27 -0400447 }
Andi Kleen411fc6b2010-10-29 15:14:31 -0400448 return ret;
Chris Mason7e381802007-04-19 15:36:27 -0400449}