Blame view

fs/btrfs/dir-item.c 13 KB
6cbd55707   Chris Mason   Btrfs: add GPLv2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Copyright (C) 2007 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
62e2749e0   Chris Mason   Btrfs: Use a chun...
18
19
20
  #include "ctree.h"
  #include "disk-io.h"
  #include "hash.h"
e089f05c1   Chris Mason   Btrfs: transactio...
21
  #include "transaction.h"
62e2749e0   Chris Mason   Btrfs: Use a chun...
22

d352ac681   Chris Mason   Btrfs: add and im...
23
24
25
26
27
28
29
30
  /*
   * insert a name into a directory, doing overflow properly if there is a hash
   * collision.  data_size indicates how big the item inserted should be.  On
   * success a struct btrfs_dir_item pointer is returned, otherwise it is
   * an ERR_PTR.
   *
   * The name is not copied into the dir item, you have to do that yourself.
   */
35b7e4761   Chris Mason   Btrfs: fix page c...
31
32
33
34
35
  static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
  						   *trans,
  						   struct btrfs_root *root,
  						   struct btrfs_path *path,
  						   struct btrfs_key *cpu_key,
e06afa839   Chris Mason   Btrfs: rename
36
37
38
  						   u32 data_size,
  						   const char *name,
  						   int name_len)
7fcde0e32   Chris Mason   Btrfs: finish off...
39
  {
7fcde0e32   Chris Mason   Btrfs: finish off...
40
  	int ret;
7e38180e2   Chris Mason   Btrfs: directory ...
41
42
  	char *ptr;
  	struct btrfs_item *item;
5f39d397d   Chris Mason   Btrfs: Create ext...
43
  	struct extent_buffer *leaf;
7fcde0e32   Chris Mason   Btrfs: finish off...
44
45
  
  	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
7e38180e2   Chris Mason   Btrfs: directory ...
46
  	if (ret == -EEXIST) {
e06afa839   Chris Mason   Btrfs: rename
47
48
49
50
  		struct btrfs_dir_item *di;
  		di = btrfs_match_dir_item_name(root, path, name, name_len);
  		if (di)
  			return ERR_PTR(-EEXIST);
7e38180e2   Chris Mason   Btrfs: directory ...
51
52
  		ret = btrfs_extend_item(trans, root, path, data_size);
  		WARN_ON(ret > 0);
7fcde0e32   Chris Mason   Btrfs: finish off...
53
  	}
54aa1f4df   Chris Mason   Btrfs: Audit call...
54
55
  	if (ret < 0)
  		return ERR_PTR(ret);
7e38180e2   Chris Mason   Btrfs: directory ...
56
  	WARN_ON(ret > 0);
5f39d397d   Chris Mason   Btrfs: Create ext...
57
58
  	leaf = path->nodes[0];
  	item = btrfs_item_nr(leaf, path->slots[0]);
7e38180e2   Chris Mason   Btrfs: directory ...
59
  	ptr = btrfs_item_ptr(leaf, path->slots[0], char);
5f39d397d   Chris Mason   Btrfs: Create ext...
60
61
  	BUG_ON(data_size > btrfs_item_size(leaf, item));
  	ptr += btrfs_item_size(leaf, item) - data_size;
7e38180e2   Chris Mason   Btrfs: directory ...
62
  	return (struct btrfs_dir_item *)ptr;
7fcde0e32   Chris Mason   Btrfs: finish off...
63
  }
d352ac681   Chris Mason   Btrfs: add and im...
64
65
66
67
  /*
   * xattrs work a lot like directories, this inserts an xattr item
   * into the tree
   */
5103e947b   Josef Bacik   xattr support for...
68
  int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
69
70
71
72
  			    struct btrfs_root *root,
  			    struct btrfs_path *path, u64 objectid,
  			    const char *name, u16 name_len,
  			    const void *data, u16 data_len)
5103e947b   Josef Bacik   xattr support for...
73
74
  {
  	int ret = 0;
5103e947b   Josef Bacik   xattr support for...
75
76
77
78
79
80
  	struct btrfs_dir_item *dir_item;
  	unsigned long name_ptr, data_ptr;
  	struct btrfs_key key, location;
  	struct btrfs_disk_key disk_key;
  	struct extent_buffer *leaf;
  	u32 data_size;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
81
82
83
  	BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));
  
  	key.objectid = objectid;
5103e947b   Josef Bacik   xattr support for...
84
  	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
df68b8a7a   David Miller   Btrfs: unaligned ...
85
  	key.offset = btrfs_name_hash(name, name_len);
5103e947b   Josef Bacik   xattr support for...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  
  	data_size = sizeof(*dir_item) + name_len + data_len;
  	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
  					name, name_len);
  	/*
  	 * FIXME: at some point we should handle xattr's that are larger than
  	 * what we can fit in our leaf.  We set location to NULL b/c we arent
  	 * pointing at anything else, that will change if we store the xattr
  	 * data in a separate inode.
  	 */
  	BUG_ON(IS_ERR(dir_item));
  	memset(&location, 0, sizeof(location));
  
  	leaf = path->nodes[0];
  	btrfs_cpu_key_to_disk(&disk_key, &location);
  	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
  	btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
  	btrfs_set_dir_name_len(leaf, dir_item, name_len);
e02119d5a   Chris Mason   Btrfs: Add a writ...
104
  	btrfs_set_dir_transid(leaf, dir_item, trans->transid);
5103e947b   Josef Bacik   xattr support for...
105
106
107
108
109
110
111
  	btrfs_set_dir_data_len(leaf, dir_item, data_len);
  	name_ptr = (unsigned long)(dir_item + 1);
  	data_ptr = (unsigned long)((char *)name_ptr + name_len);
  
  	write_extent_buffer(leaf, name, name_ptr, name_len);
  	write_extent_buffer(leaf, data, data_ptr, data_len);
  	btrfs_mark_buffer_dirty(path->nodes[0]);
5103e947b   Josef Bacik   xattr support for...
112
113
  	return ret;
  }
d352ac681   Chris Mason   Btrfs: add and im...
114
115
116
117
118
119
120
  /*
   * insert a directory item in the tree, doing all the magic for
   * both indexes. 'dir' indicates which objectid to insert it into,
   * 'location' is the key to stuff into the directory item, 'type' is the
   * type of the inode we're pointing to, and 'index' is the sequence number
   * to use for the second index (if one is created).
   */
e089f05c1   Chris Mason   Btrfs: transactio...
121
  int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
d6e4a428e   Chris Mason   Btrfs: start of s...
122
  			  *root, const char *name, int name_len, u64 dir,
aec7477b3   Josef Bacik   Btrfs: Implement ...
123
  			  struct btrfs_key *location, u8 type, u64 index)
62e2749e0   Chris Mason   Btrfs: Use a chun...
124
125
  {
  	int ret = 0;
e06afa839   Chris Mason   Btrfs: rename
126
  	int ret2 = 0;
5caf2a002   Chris Mason   Btrfs: dynamic al...
127
  	struct btrfs_path *path;
62e2749e0   Chris Mason   Btrfs: Use a chun...
128
  	struct btrfs_dir_item *dir_item;
5f39d397d   Chris Mason   Btrfs: Create ext...
129
130
  	struct extent_buffer *leaf;
  	unsigned long name_ptr;
62e2749e0   Chris Mason   Btrfs: Use a chun...
131
  	struct btrfs_key key;
5f39d397d   Chris Mason   Btrfs: Create ext...
132
  	struct btrfs_disk_key disk_key;
62e2749e0   Chris Mason   Btrfs: Use a chun...
133
134
135
  	u32 data_size;
  
  	key.objectid = dir;
1d4f6404d   Chris Mason   Btrfs: directory ...
136
  	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
df68b8a7a   David Miller   Btrfs: unaligned ...
137
  	key.offset = btrfs_name_hash(name, name_len);
b9473439d   Chris Mason   Btrfs: leave btre...
138

5caf2a002   Chris Mason   Btrfs: dynamic al...
139
  	path = btrfs_alloc_path();
b9473439d   Chris Mason   Btrfs: leave btre...
140
  	path->leave_spinning = 1;
62e2749e0   Chris Mason   Btrfs: Use a chun...
141
  	data_size = sizeof(*dir_item) + name_len;
e06afa839   Chris Mason   Btrfs: rename
142
143
  	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
  					name, name_len);
7e38180e2   Chris Mason   Btrfs: directory ...
144
145
  	if (IS_ERR(dir_item)) {
  		ret = PTR_ERR(dir_item);
e06afa839   Chris Mason   Btrfs: rename
146
147
  		if (ret == -EEXIST)
  			goto second_insert;
c2db1073f   Tsutomu Itoh   Btrfs: check retu...
148
  		goto out_free;
7e38180e2   Chris Mason   Btrfs: directory ...
149
  	}
62e2749e0   Chris Mason   Btrfs: Use a chun...
150

5f39d397d   Chris Mason   Btrfs: Create ext...
151
152
153
154
  	leaf = path->nodes[0];
  	btrfs_cpu_key_to_disk(&disk_key, location);
  	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
  	btrfs_set_dir_type(leaf, dir_item, type);
5103e947b   Josef Bacik   xattr support for...
155
  	btrfs_set_dir_data_len(leaf, dir_item, 0);
5f39d397d   Chris Mason   Btrfs: Create ext...
156
  	btrfs_set_dir_name_len(leaf, dir_item, name_len);
e02119d5a   Chris Mason   Btrfs: Add a writ...
157
  	btrfs_set_dir_transid(leaf, dir_item, trans->transid);
5f39d397d   Chris Mason   Btrfs: Create ext...
158
  	name_ptr = (unsigned long)(dir_item + 1);
c5739bba5   Chris Mason   Btrfs: snapshot p...
159

5f39d397d   Chris Mason   Btrfs: Create ext...
160
161
  	write_extent_buffer(leaf, name, name_ptr, name_len);
  	btrfs_mark_buffer_dirty(leaf);
7e38180e2   Chris Mason   Btrfs: directory ...
162

e06afa839   Chris Mason   Btrfs: rename
163
  second_insert:
7e38180e2   Chris Mason   Btrfs: directory ...
164
165
166
  	/* FIXME, use some real flag for selecting the extra index */
  	if (root == root->fs_info->tree_root) {
  		ret = 0;
c2db1073f   Tsutomu Itoh   Btrfs: check retu...
167
  		goto out_free;
7e38180e2   Chris Mason   Btrfs: directory ...
168
  	}
5caf2a002   Chris Mason   Btrfs: dynamic al...
169
  	btrfs_release_path(root, path);
7e38180e2   Chris Mason   Btrfs: directory ...
170
171
  
  	btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
aec7477b3   Josef Bacik   Btrfs: Implement ...
172
  	key.offset = index;
e06afa839   Chris Mason   Btrfs: rename
173
174
  	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
  					name, name_len);
7e38180e2   Chris Mason   Btrfs: directory ...
175
  	if (IS_ERR(dir_item)) {
e06afa839   Chris Mason   Btrfs: rename
176
  		ret2 = PTR_ERR(dir_item);
c2db1073f   Tsutomu Itoh   Btrfs: check retu...
177
  		goto out_free;
7e38180e2   Chris Mason   Btrfs: directory ...
178
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
179
180
181
182
  	leaf = path->nodes[0];
  	btrfs_cpu_key_to_disk(&disk_key, location);
  	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
  	btrfs_set_dir_type(leaf, dir_item, type);
5103e947b   Josef Bacik   xattr support for...
183
  	btrfs_set_dir_data_len(leaf, dir_item, 0);
5f39d397d   Chris Mason   Btrfs: Create ext...
184
  	btrfs_set_dir_name_len(leaf, dir_item, name_len);
e02119d5a   Chris Mason   Btrfs: Add a writ...
185
  	btrfs_set_dir_transid(leaf, dir_item, trans->transid);
5f39d397d   Chris Mason   Btrfs: Create ext...
186
187
188
  	name_ptr = (unsigned long)(dir_item + 1);
  	write_extent_buffer(leaf, name, name_ptr, name_len);
  	btrfs_mark_buffer_dirty(leaf);
c2db1073f   Tsutomu Itoh   Btrfs: check retu...
189
190
  
  out_free:
5caf2a002   Chris Mason   Btrfs: dynamic al...
191
  	btrfs_free_path(path);
e06afa839   Chris Mason   Btrfs: rename
192
193
194
195
196
  	if (ret)
  		return ret;
  	if (ret2)
  		return ret2;
  	return 0;
62e2749e0   Chris Mason   Btrfs: Use a chun...
197
  }
d352ac681   Chris Mason   Btrfs: add and im...
198
199
200
201
202
  /*
   * lookup a directory item based on name.  'dir' is the objectid
   * we're searching in, and 'mod' tells us if you plan on deleting the
   * item (use mod < 0) or changing the options (use mod > 0)
   */
7e38180e2   Chris Mason   Btrfs: directory ...
203
204
205
206
207
  struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
  					     struct btrfs_root *root,
  					     struct btrfs_path *path, u64 dir,
  					     const char *name, int name_len,
  					     int mod)
62e2749e0   Chris Mason   Btrfs: Use a chun...
208
  {
1d4f6404d   Chris Mason   Btrfs: directory ...
209
  	int ret;
62e2749e0   Chris Mason   Btrfs: Use a chun...
210
  	struct btrfs_key key;
1d4f6404d   Chris Mason   Btrfs: directory ...
211
212
  	int ins_len = mod < 0 ? -1 : 0;
  	int cow = mod != 0;
5f39d397d   Chris Mason   Btrfs: Create ext...
213
214
  	struct btrfs_key found_key;
  	struct extent_buffer *leaf;
62e2749e0   Chris Mason   Btrfs: Use a chun...
215
216
  
  	key.objectid = dir;
1d4f6404d   Chris Mason   Btrfs: directory ...
217
  	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
5f39d397d   Chris Mason   Btrfs: Create ext...
218

df68b8a7a   David Miller   Btrfs: unaligned ...
219
  	key.offset = btrfs_name_hash(name, name_len);
5f39d397d   Chris Mason   Btrfs: Create ext...
220

7e38180e2   Chris Mason   Btrfs: directory ...
221
222
223
224
225
226
227
  	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
  	if (ret < 0)
  		return ERR_PTR(ret);
  	if (ret > 0) {
  		if (path->slots[0] == 0)
  			return NULL;
  		path->slots[0]--;
7fcde0e32   Chris Mason   Btrfs: finish off...
228
  	}
7e38180e2   Chris Mason   Btrfs: directory ...
229

5f39d397d   Chris Mason   Btrfs: Create ext...
230
231
232
233
234
235
  	leaf = path->nodes[0];
  	btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
  
  	if (found_key.objectid != dir ||
  	    btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY ||
  	    found_key.offset != key.offset)
7e38180e2   Chris Mason   Btrfs: directory ...
236
237
238
  		return NULL;
  
  	return btrfs_match_dir_item_name(root, path, name, name_len);
62e2749e0   Chris Mason   Btrfs: Use a chun...
239
  }
d352ac681   Chris Mason   Btrfs: add and im...
240
241
242
243
244
245
246
247
  /*
   * lookup a directory item based on index.  'dir' is the objectid
   * we're searching in, and 'mod' tells us if you plan on deleting the
   * item (use mod < 0) or changing the options (use mod > 0)
   *
   * The name is used to make sure the index really points to the name you were
   * looking for.
   */
7e38180e2   Chris Mason   Btrfs: directory ...
248
249
250
251
252
253
254
255
256
257
258
259
260
  struct btrfs_dir_item *
  btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
  			    struct btrfs_root *root,
  			    struct btrfs_path *path, u64 dir,
  			    u64 objectid, const char *name, int name_len,
  			    int mod)
  {
  	int ret;
  	struct btrfs_key key;
  	int ins_len = mod < 0 ? -1 : 0;
  	int cow = mod != 0;
  
  	key.objectid = dir;
7e38180e2   Chris Mason   Btrfs: directory ...
261
262
263
264
265
266
267
268
269
270
  	btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
  	key.offset = objectid;
  
  	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
  	if (ret < 0)
  		return ERR_PTR(ret);
  	if (ret > 0)
  		return ERR_PTR(-ENOENT);
  	return btrfs_match_dir_item_name(root, path, name, name_len);
  }
4df27c4d5   Yan, Zheng   Btrfs: change how...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  struct btrfs_dir_item *
  btrfs_search_dir_index_item(struct btrfs_root *root,
  			    struct btrfs_path *path, u64 dirid,
  			    const char *name, int name_len)
  {
  	struct extent_buffer *leaf;
  	struct btrfs_dir_item *di;
  	struct btrfs_key key;
  	u32 nritems;
  	int ret;
  
  	key.objectid = dirid;
  	key.type = BTRFS_DIR_INDEX_KEY;
  	key.offset = 0;
  
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0)
  		return ERR_PTR(ret);
  
  	leaf = path->nodes[0];
  	nritems = btrfs_header_nritems(leaf);
  
  	while (1) {
  		if (path->slots[0] >= nritems) {
  			ret = btrfs_next_leaf(root, path);
  			if (ret < 0)
  				return ERR_PTR(ret);
  			if (ret > 0)
  				break;
  			leaf = path->nodes[0];
  			nritems = btrfs_header_nritems(leaf);
  			continue;
  		}
  
  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
  		if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY)
  			break;
  
  		di = btrfs_match_dir_item_name(root, path, name, name_len);
  		if (di)
  			return di;
  
  		path->slots[0]++;
  	}
  	return NULL;
  }
5103e947b   Josef Bacik   xattr support for...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
  					  struct btrfs_root *root,
  					  struct btrfs_path *path, u64 dir,
  					  const char *name, u16 name_len,
  					  int mod)
  {
  	int ret;
  	struct btrfs_key key;
  	int ins_len = mod < 0 ? -1 : 0;
  	int cow = mod != 0;
  	struct btrfs_key found_key;
  	struct extent_buffer *leaf;
  
  	key.objectid = dir;
  	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
df68b8a7a   David Miller   Btrfs: unaligned ...
332
  	key.offset = btrfs_name_hash(name, name_len);
5103e947b   Josef Bacik   xattr support for...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
  	if (ret < 0)
  		return ERR_PTR(ret);
  	if (ret > 0) {
  		if (path->slots[0] == 0)
  			return NULL;
  		path->slots[0]--;
  	}
  
  	leaf = path->nodes[0];
  	btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
  
  	if (found_key.objectid != dir ||
  	    btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY ||
  	    found_key.offset != key.offset)
  		return NULL;
  
  	return btrfs_match_dir_item_name(root, path, name, name_len);
  }
d352ac681   Chris Mason   Btrfs: add and im...
352
353
354
355
356
  /*
   * helper function to look at the directory item pointed to by 'path'
   * this walks through all the entries in a dir item and finds one
   * for a specific name.
   */
7e38180e2   Chris Mason   Btrfs: directory ...
357
  struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
7f5c15160   Chris Mason   Add generation nu...
358
359
  			      struct btrfs_path *path,
  			      const char *name, int name_len)
62e2749e0   Chris Mason   Btrfs: Use a chun...
360
  {
62e2749e0   Chris Mason   Btrfs: Use a chun...
361
  	struct btrfs_dir_item *dir_item;
5f39d397d   Chris Mason   Btrfs: Create ext...
362
  	unsigned long name_ptr;
7e38180e2   Chris Mason   Btrfs: directory ...
363
364
365
  	u32 total_len;
  	u32 cur = 0;
  	u32 this_len;
5f39d397d   Chris Mason   Btrfs: Create ext...
366
  	struct extent_buffer *leaf;
a8a2ee0c6   Chris Mason   Btrfs: add a name...
367

5f39d397d   Chris Mason   Btrfs: Create ext...
368
  	leaf = path->nodes[0];
7e38180e2   Chris Mason   Btrfs: directory ...
369
  	dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
22a94d44b   Josef Bacik   Btrfs: add checks...
370
371
  	if (verify_dir_item(root, leaf, dir_item))
  		return NULL;
5f39d397d   Chris Mason   Btrfs: Create ext...
372
  	total_len = btrfs_item_size_nr(leaf, path->slots[0]);
d397712bc   Chris Mason   Btrfs: Fix checkp...
373
  	while (cur < total_len) {
5f39d397d   Chris Mason   Btrfs: Create ext...
374
  		this_len = sizeof(*dir_item) +
5103e947b   Josef Bacik   xattr support for...
375
376
  			btrfs_dir_name_len(leaf, dir_item) +
  			btrfs_dir_data_len(leaf, dir_item);
5f39d397d   Chris Mason   Btrfs: Create ext...
377
  		name_ptr = (unsigned long)(dir_item + 1);
7e38180e2   Chris Mason   Btrfs: directory ...
378

5f39d397d   Chris Mason   Btrfs: Create ext...
379
380
  		if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
  		    memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
7e38180e2   Chris Mason   Btrfs: directory ...
381
382
383
384
385
386
387
  			return dir_item;
  
  		cur += this_len;
  		dir_item = (struct btrfs_dir_item *)((char *)dir_item +
  						     this_len);
  	}
  	return NULL;
62e2749e0   Chris Mason   Btrfs: Use a chun...
388
  }
7e38180e2   Chris Mason   Btrfs: directory ...
389

d352ac681   Chris Mason   Btrfs: add and im...
390
391
392
393
  /*
   * given a pointer into a directory item, delete it.  This
   * handles items that have more than one entry in them.
   */
7e38180e2   Chris Mason   Btrfs: directory ...
394
395
396
397
398
  int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
  			      struct btrfs_root *root,
  			      struct btrfs_path *path,
  			      struct btrfs_dir_item *di)
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
399
  	struct extent_buffer *leaf;
7e38180e2   Chris Mason   Btrfs: directory ...
400
401
  	u32 sub_item_len;
  	u32 item_len;
54aa1f4df   Chris Mason   Btrfs: Audit call...
402
  	int ret = 0;
7e38180e2   Chris Mason   Btrfs: directory ...
403

5f39d397d   Chris Mason   Btrfs: Create ext...
404
  	leaf = path->nodes[0];
5103e947b   Josef Bacik   xattr support for...
405
406
  	sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) +
  		btrfs_dir_data_len(leaf, di);
5f39d397d   Chris Mason   Btrfs: Create ext...
407
408
  	item_len = btrfs_item_size_nr(leaf, path->slots[0]);
  	if (sub_item_len == item_len) {
7e38180e2   Chris Mason   Btrfs: directory ...
409
  		ret = btrfs_del_item(trans, root, path);
7e38180e2   Chris Mason   Btrfs: directory ...
410
  	} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
411
412
413
414
415
416
  		/* MARKER */
  		unsigned long ptr = (unsigned long)di;
  		unsigned long start;
  
  		start = btrfs_item_ptr_offset(leaf, path->slots[0]);
  		memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
7e38180e2   Chris Mason   Btrfs: directory ...
417
418
  			item_len - (ptr + sub_item_len - start));
  		ret = btrfs_truncate_item(trans, root, path,
179e29e48   Chris Mason   Btrfs: Fix a numb...
419
  					  item_len - sub_item_len, 1);
7e38180e2   Chris Mason   Btrfs: directory ...
420
  	}
411fc6bce   Andi Kleen   Btrfs: Fix variab...
421
  	return ret;
7e38180e2   Chris Mason   Btrfs: directory ...
422
  }
22a94d44b   Josef Bacik   Btrfs: add checks...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  
  int verify_dir_item(struct btrfs_root *root,
  		    struct extent_buffer *leaf,
  		    struct btrfs_dir_item *dir_item)
  {
  	u16 namelen = BTRFS_NAME_LEN;
  	u8 type = btrfs_dir_type(leaf, dir_item);
  
  	if (type >= BTRFS_FT_MAX) {
  		printk(KERN_CRIT "btrfs: invalid dir item type: %d
  ",
  		       (int)type);
  		return 1;
  	}
  
  	if (type == BTRFS_FT_XATTR)
  		namelen = XATTR_NAME_MAX;
  
  	if (btrfs_dir_name_len(leaf, dir_item) > namelen) {
  		printk(KERN_CRIT "btrfS: invalid dir item name len: %u
  ",
  		       (unsigned)btrfs_dir_data_len(leaf, dir_item));
  		return 1;
  	}
  
  	/* BTRFS_MAX_XATTR_SIZE is the same for all dir items */
  	if (btrfs_dir_data_len(leaf, dir_item) > BTRFS_MAX_XATTR_SIZE(root)) {
  		printk(KERN_CRIT "btrfs: invalid dir item data len: %u
  ",
  		       (unsigned)btrfs_dir_data_len(leaf, dir_item));
  		return 1;
  	}
  
  	return 0;
  }