Blame view

fs/btrfs/ctree.c 111 KB
6cbd55707   Chris Mason   Btrfs: add GPLv2
1
  /*
d352ac681   Chris Mason   Btrfs: add and im...
2
   * Copyright (C) 2007,2008 Oracle.  All rights reserved.
6cbd55707   Chris Mason   Btrfs: add GPLv2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * 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.
   */
a6b6e75e0   Chris Mason   Btrfs: Defrag onl...
18
  #include <linux/sched.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
eb60ceac0   Chris Mason   Btrfs: Add backin...
20
21
  #include "ctree.h"
  #include "disk-io.h"
7f5c15160   Chris Mason   Add generation nu...
22
  #include "transaction.h"
5f39d397d   Chris Mason   Btrfs: Create ext...
23
  #include "print-tree.h"
925baeddc   Chris Mason   Btrfs: Start btre...
24
  #include "locking.h"
9a8dd1502   Chris Mason   Btrfs: Block size...
25

e089f05c1   Chris Mason   Btrfs: transactio...
26
27
28
  static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
  		      *root, struct btrfs_path *path, int level);
  static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
d4dbff953   Chris Mason   Btrfs: support fo...
29
  		      *root, struct btrfs_key *ins_key,
cc0c55384   Chris Mason   Btrfs: Fix split_...
30
  		      struct btrfs_path *path, int data_size, int extend);
5f39d397d   Chris Mason   Btrfs: Create ext...
31
32
  static int push_node_left(struct btrfs_trans_handle *trans,
  			  struct btrfs_root *root, struct extent_buffer *dst,
971a1f664   Chris Mason   Btrfs: Don't empt...
33
  			  struct extent_buffer *src, int empty);
5f39d397d   Chris Mason   Btrfs: Create ext...
34
35
36
37
  static int balance_node_right(struct btrfs_trans_handle *trans,
  			      struct btrfs_root *root,
  			      struct extent_buffer *dst_buf,
  			      struct extent_buffer *src_buf);
e089f05c1   Chris Mason   Btrfs: transactio...
38
39
  static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
  		   struct btrfs_path *path, int level, int slot);
d97e63b69   Chris Mason   Btrfs: early exte...
40

df24a2b9c   Chris Mason   Btrfs: early inli...
41
  struct btrfs_path *btrfs_alloc_path(void)
2c90e5d65   Chris Mason   Btrfs: still corr...
42
  {
df24a2b9c   Chris Mason   Btrfs: early inli...
43
  	struct btrfs_path *path;
e00f73086   Jeff Mahoney   Btrfs: remove btr...
44
  	path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
df24a2b9c   Chris Mason   Btrfs: early inli...
45
  	return path;
2c90e5d65   Chris Mason   Btrfs: still corr...
46
  }
b4ce94de9   Chris Mason   Btrfs: Change btr...
47
48
49
50
51
52
53
54
  /*
   * set all locked nodes in the path to blocking locks.  This should
   * be done before scheduling
   */
  noinline void btrfs_set_path_blocking(struct btrfs_path *p)
  {
  	int i;
  	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
bd681513f   Chris Mason   Btrfs: switch the...
55
56
57
58
59
60
61
  		if (!p->nodes[i] || !p->locks[i])
  			continue;
  		btrfs_set_lock_blocking_rw(p->nodes[i], p->locks[i]);
  		if (p->locks[i] == BTRFS_READ_LOCK)
  			p->locks[i] = BTRFS_READ_LOCK_BLOCKING;
  		else if (p->locks[i] == BTRFS_WRITE_LOCK)
  			p->locks[i] = BTRFS_WRITE_LOCK_BLOCKING;
b4ce94de9   Chris Mason   Btrfs: Change btr...
62
63
64
65
66
  	}
  }
  
  /*
   * reset all the locked nodes in the patch to spinning locks.
4008c04a0   Chris Mason   Btrfs: make a loc...
67
68
69
70
71
   *
   * held is used to keep lockdep happy, when lockdep is enabled
   * we set held to a blocking lock before we go around and
   * retake all the spinlocks in the path.  You can safely use NULL
   * for held
b4ce94de9   Chris Mason   Btrfs: Change btr...
72
   */
4008c04a0   Chris Mason   Btrfs: make a loc...
73
  noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
bd681513f   Chris Mason   Btrfs: switch the...
74
  					struct extent_buffer *held, int held_rw)
b4ce94de9   Chris Mason   Btrfs: Change btr...
75
76
  {
  	int i;
4008c04a0   Chris Mason   Btrfs: make a loc...
77
78
79
80
81
82
83
84
  
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  	/* lockdep really cares that we take all of these spinlocks
  	 * in the right order.  If any of the locks in the path are not
  	 * currently blocking, it is going to complain.  So, make really
  	 * really sure by forcing the path to blocking before we clear
  	 * the path blocking.
  	 */
bd681513f   Chris Mason   Btrfs: switch the...
85
86
87
88
89
90
91
  	if (held) {
  		btrfs_set_lock_blocking_rw(held, held_rw);
  		if (held_rw == BTRFS_WRITE_LOCK)
  			held_rw = BTRFS_WRITE_LOCK_BLOCKING;
  		else if (held_rw == BTRFS_READ_LOCK)
  			held_rw = BTRFS_READ_LOCK_BLOCKING;
  	}
4008c04a0   Chris Mason   Btrfs: make a loc...
92
93
94
95
  	btrfs_set_path_blocking(p);
  #endif
  
  	for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
bd681513f   Chris Mason   Btrfs: switch the...
96
97
98
99
100
101
102
  		if (p->nodes[i] && p->locks[i]) {
  			btrfs_clear_lock_blocking_rw(p->nodes[i], p->locks[i]);
  			if (p->locks[i] == BTRFS_WRITE_LOCK_BLOCKING)
  				p->locks[i] = BTRFS_WRITE_LOCK;
  			else if (p->locks[i] == BTRFS_READ_LOCK_BLOCKING)
  				p->locks[i] = BTRFS_READ_LOCK;
  		}
b4ce94de9   Chris Mason   Btrfs: Change btr...
103
  	}
4008c04a0   Chris Mason   Btrfs: make a loc...
104
105
106
  
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  	if (held)
bd681513f   Chris Mason   Btrfs: switch the...
107
  		btrfs_clear_lock_blocking_rw(held, held_rw);
4008c04a0   Chris Mason   Btrfs: make a loc...
108
  #endif
b4ce94de9   Chris Mason   Btrfs: Change btr...
109
  }
d352ac681   Chris Mason   Btrfs: add and im...
110
  /* this also releases the path */
df24a2b9c   Chris Mason   Btrfs: early inli...
111
  void btrfs_free_path(struct btrfs_path *p)
be0e5c097   Chris Mason   Btrfs: Initial ch...
112
  {
ff175d57f   Jesper Juhl   btrfs: Don't pass...
113
114
  	if (!p)
  		return;
b3b4aa74b   David Sterba   btrfs: drop unuse...
115
  	btrfs_release_path(p);
df24a2b9c   Chris Mason   Btrfs: early inli...
116
  	kmem_cache_free(btrfs_path_cachep, p);
be0e5c097   Chris Mason   Btrfs: Initial ch...
117
  }
d352ac681   Chris Mason   Btrfs: add and im...
118
119
120
121
122
123
  /*
   * path release drops references on the extent buffers in the path
   * and it drops any locks held by this path
   *
   * It is safe to call this on paths that no locks or extent buffers held.
   */
b3b4aa74b   David Sterba   btrfs: drop unuse...
124
  noinline void btrfs_release_path(struct btrfs_path *p)
eb60ceac0   Chris Mason   Btrfs: Add backin...
125
126
  {
  	int i;
a21350115   Chris Mason   Btrfs: Replace th...
127

234b63a09   Chris Mason   rename funcs and ...
128
  	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
3f157a2fd   Chris Mason   Btrfs: Online btr...
129
  		p->slots[i] = 0;
eb60ceac0   Chris Mason   Btrfs: Add backin...
130
  		if (!p->nodes[i])
925baeddc   Chris Mason   Btrfs: Start btre...
131
132
  			continue;
  		if (p->locks[i]) {
bd681513f   Chris Mason   Btrfs: switch the...
133
  			btrfs_tree_unlock_rw(p->nodes[i], p->locks[i]);
925baeddc   Chris Mason   Btrfs: Start btre...
134
135
  			p->locks[i] = 0;
  		}
5f39d397d   Chris Mason   Btrfs: Create ext...
136
  		free_extent_buffer(p->nodes[i]);
3f157a2fd   Chris Mason   Btrfs: Online btr...
137
  		p->nodes[i] = NULL;
eb60ceac0   Chris Mason   Btrfs: Add backin...
138
139
  	}
  }
d352ac681   Chris Mason   Btrfs: add and im...
140
141
142
143
144
145
146
147
148
149
  /*
   * safely gets a reference on the root node of a tree.  A lock
   * is not taken, so a concurrent writer may put a different node
   * at the root of the tree.  See btrfs_lock_root_node for the
   * looping required.
   *
   * The extent buffer returned by this has a reference taken, so
   * it won't disappear.  It may stop being the root of the tree
   * at any time because there are no locks held.
   */
925baeddc   Chris Mason   Btrfs: Start btre...
150
151
152
  struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
  {
  	struct extent_buffer *eb;
240f62c87   Chris Mason   Btrfs: use RCU in...
153
154
155
  
  	rcu_read_lock();
  	eb = rcu_dereference(root->node);
925baeddc   Chris Mason   Btrfs: Start btre...
156
  	extent_buffer_get(eb);
240f62c87   Chris Mason   Btrfs: use RCU in...
157
  	rcu_read_unlock();
925baeddc   Chris Mason   Btrfs: Start btre...
158
159
  	return eb;
  }
d352ac681   Chris Mason   Btrfs: add and im...
160
161
162
163
  /* loop around taking references on and locking the root node of the
   * tree until you end up with a lock on the root.  A locked buffer
   * is returned, with a reference held.
   */
925baeddc   Chris Mason   Btrfs: Start btre...
164
165
166
  struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
  {
  	struct extent_buffer *eb;
d397712bc   Chris Mason   Btrfs: Fix checkp...
167
  	while (1) {
925baeddc   Chris Mason   Btrfs: Start btre...
168
169
  		eb = btrfs_root_node(root);
  		btrfs_tree_lock(eb);
240f62c87   Chris Mason   Btrfs: use RCU in...
170
  		if (eb == root->node)
925baeddc   Chris Mason   Btrfs: Start btre...
171
  			break;
925baeddc   Chris Mason   Btrfs: Start btre...
172
173
174
175
176
  		btrfs_tree_unlock(eb);
  		free_extent_buffer(eb);
  	}
  	return eb;
  }
bd681513f   Chris Mason   Btrfs: switch the...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  /* loop around taking references on and locking the root node of the
   * tree until you end up with a lock on the root.  A locked buffer
   * is returned, with a reference held.
   */
  struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
  {
  	struct extent_buffer *eb;
  
  	while (1) {
  		eb = btrfs_root_node(root);
  		btrfs_tree_read_lock(eb);
  		if (eb == root->node)
  			break;
  		btrfs_tree_read_unlock(eb);
  		free_extent_buffer(eb);
  	}
  	return eb;
  }
d352ac681   Chris Mason   Btrfs: add and im...
195
196
197
198
  /* cowonly root (everything not a reference counted cow subvolume), just get
   * put onto a simple dirty list.  transaction.c walks this to make sure they
   * get properly updated on disk.
   */
0b86a832a   Chris Mason   Btrfs: Add suppor...
199
200
201
202
203
204
205
  static void add_root_to_dirty_list(struct btrfs_root *root)
  {
  	if (root->track_dirty && list_empty(&root->dirty_list)) {
  		list_add(&root->dirty_list,
  			 &root->fs_info->dirty_cowonly_roots);
  	}
  }
d352ac681   Chris Mason   Btrfs: add and im...
206
207
208
209
210
  /*
   * used by snapshot creation to make a copy of a root for a tree with
   * a given objectid.  The buffer with the new root node is returned in
   * cow_ret, and this func returns zero on success or a negative error code.
   */
be20aa9db   Chris Mason   Btrfs: Add mount ...
211
212
213
214
215
216
  int btrfs_copy_root(struct btrfs_trans_handle *trans,
  		      struct btrfs_root *root,
  		      struct extent_buffer *buf,
  		      struct extent_buffer **cow_ret, u64 new_root_objectid)
  {
  	struct extent_buffer *cow;
be20aa9db   Chris Mason   Btrfs: Add mount ...
217
218
  	int ret = 0;
  	int level;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
219
  	struct btrfs_disk_key disk_key;
be20aa9db   Chris Mason   Btrfs: Add mount ...
220
221
222
223
224
225
  
  	WARN_ON(root->ref_cows && trans->transid !=
  		root->fs_info->running_transaction->transid);
  	WARN_ON(root->ref_cows && trans->transid != root->last_trans);
  
  	level = btrfs_header_level(buf);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
226
227
228
229
  	if (level == 0)
  		btrfs_item_key(buf, &disk_key, 0);
  	else
  		btrfs_node_key(buf, &disk_key, 0);
31840ae1a   Zheng Yan   Btrfs: Full back ...
230

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
231
232
233
234
  	cow = btrfs_alloc_free_block(trans, root, buf->len, 0,
  				     new_root_objectid, &disk_key, level,
  				     buf->start, 0);
  	if (IS_ERR(cow))
be20aa9db   Chris Mason   Btrfs: Add mount ...
235
236
237
238
239
  		return PTR_ERR(cow);
  
  	copy_extent_buffer(cow, buf, 0, 0, cow->len);
  	btrfs_set_header_bytenr(cow, cow->start);
  	btrfs_set_header_generation(cow, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
240
241
242
243
244
245
246
  	btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV);
  	btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN |
  				     BTRFS_HEADER_FLAG_RELOC);
  	if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID)
  		btrfs_set_header_flag(cow, BTRFS_HEADER_FLAG_RELOC);
  	else
  		btrfs_set_header_owner(cow, new_root_objectid);
be20aa9db   Chris Mason   Btrfs: Add mount ...
247

2b82032c3   Yan Zheng   Btrfs: Seed devic...
248
249
250
  	write_extent_buffer(cow, root->fs_info->fsid,
  			    (unsigned long)btrfs_header_fsid(cow),
  			    BTRFS_FSID_SIZE);
be20aa9db   Chris Mason   Btrfs: Add mount ...
251
  	WARN_ON(btrfs_header_generation(buf) > trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
252
253
254
255
  	if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID)
  		ret = btrfs_inc_ref(trans, root, cow, 1);
  	else
  		ret = btrfs_inc_ref(trans, root, cow, 0);
4aec2b523   Chris Mason   kmalloc a few lar...
256

be20aa9db   Chris Mason   Btrfs: Add mount ...
257
258
259
260
261
262
263
  	if (ret)
  		return ret;
  
  	btrfs_mark_buffer_dirty(cow);
  	*cow_ret = cow;
  	return 0;
  }
d352ac681   Chris Mason   Btrfs: add and im...
264
  /*
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
   * check if the tree block can be shared by multiple trees
   */
  int btrfs_block_can_be_shared(struct btrfs_root *root,
  			      struct extent_buffer *buf)
  {
  	/*
  	 * Tree blocks not in refernece counted trees and tree roots
  	 * are never shared. If a block was allocated after the last
  	 * snapshot and the block was not allocated by tree relocation,
  	 * we know the block is not shared.
  	 */
  	if (root->ref_cows &&
  	    buf != root->node && buf != root->commit_root &&
  	    (btrfs_header_generation(buf) <=
  	     btrfs_root_last_snapshot(&root->root_item) ||
  	     btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)))
  		return 1;
  #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
  	if (root->ref_cows &&
  	    btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV)
  		return 1;
  #endif
  	return 0;
  }
  
  static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
  				       struct btrfs_root *root,
  				       struct extent_buffer *buf,
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
293
294
  				       struct extent_buffer *cow,
  				       int *last_ref)
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  {
  	u64 refs;
  	u64 owner;
  	u64 flags;
  	u64 new_flags = 0;
  	int ret;
  
  	/*
  	 * Backrefs update rules:
  	 *
  	 * Always use full backrefs for extent pointers in tree block
  	 * allocated by tree relocation.
  	 *
  	 * If a shared tree block is no longer referenced by its owner
  	 * tree (btrfs_header_owner(buf) == root->root_key.objectid),
  	 * use full backrefs for extent pointers in tree block.
  	 *
  	 * If a tree block is been relocating
  	 * (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID),
  	 * use full backrefs for extent pointers in tree block.
  	 * The reason for this is some operations (such as drop tree)
  	 * are only allowed for blocks use full backrefs.
  	 */
  
  	if (btrfs_block_can_be_shared(root, buf)) {
  		ret = btrfs_lookup_extent_info(trans, root, buf->start,
  					       buf->len, &refs, &flags);
  		BUG_ON(ret);
  		BUG_ON(refs == 0);
  	} else {
  		refs = 1;
  		if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
  		    btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV)
  			flags = BTRFS_BLOCK_FLAG_FULL_BACKREF;
  		else
  			flags = 0;
  	}
  
  	owner = btrfs_header_owner(buf);
  	BUG_ON(owner == BTRFS_TREE_RELOC_OBJECTID &&
  	       !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
  
  	if (refs > 1) {
  		if ((owner == root->root_key.objectid ||
  		     root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
  		    !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
  			ret = btrfs_inc_ref(trans, root, buf, 1);
  			BUG_ON(ret);
  
  			if (root->root_key.objectid ==
  			    BTRFS_TREE_RELOC_OBJECTID) {
  				ret = btrfs_dec_ref(trans, root, buf, 0);
  				BUG_ON(ret);
  				ret = btrfs_inc_ref(trans, root, cow, 1);
  				BUG_ON(ret);
  			}
  			new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
  		} else {
  
  			if (root->root_key.objectid ==
  			    BTRFS_TREE_RELOC_OBJECTID)
  				ret = btrfs_inc_ref(trans, root, cow, 1);
  			else
  				ret = btrfs_inc_ref(trans, root, cow, 0);
  			BUG_ON(ret);
  		}
  		if (new_flags != 0) {
  			ret = btrfs_set_disk_extent_flags(trans, root,
  							  buf->start,
  							  buf->len,
  							  new_flags, 0);
  			BUG_ON(ret);
  		}
  	} else {
  		if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
  			if (root->root_key.objectid ==
  			    BTRFS_TREE_RELOC_OBJECTID)
  				ret = btrfs_inc_ref(trans, root, cow, 1);
  			else
  				ret = btrfs_inc_ref(trans, root, cow, 0);
  			BUG_ON(ret);
  			ret = btrfs_dec_ref(trans, root, buf, 1);
  			BUG_ON(ret);
  		}
  		clean_tree_block(trans, root, buf);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
380
  		*last_ref = 1;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
381
382
383
384
385
  	}
  	return 0;
  }
  
  /*
d397712bc   Chris Mason   Btrfs: Fix checkp...
386
387
388
389
   * does the dirty work in cow of a single block.  The parent block (if
   * supplied) is updated to point to the new cow copy.  The new buffer is marked
   * dirty and returned locked.  If you modify the block it needs to be marked
   * dirty again.
d352ac681   Chris Mason   Btrfs: add and im...
390
391
392
   *
   * search_start -- an allocation hint for the new block
   *
d397712bc   Chris Mason   Btrfs: Fix checkp...
393
394
395
   * empty_size -- a hint that you plan on doing more cow.  This is the size in
   * bytes the allocator should try to find free next to the block it returns.
   * This is just a hint and may be ignored by the allocator.
d352ac681   Chris Mason   Btrfs: add and im...
396
   */
d397712bc   Chris Mason   Btrfs: Fix checkp...
397
  static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
5f39d397d   Chris Mason   Btrfs: Create ext...
398
399
400
401
  			     struct btrfs_root *root,
  			     struct extent_buffer *buf,
  			     struct extent_buffer *parent, int parent_slot,
  			     struct extent_buffer **cow_ret,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
402
  			     u64 search_start, u64 empty_size)
02217ed29   Chris Mason   Btrfs: early refe...
403
  {
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
404
  	struct btrfs_disk_key disk_key;
5f39d397d   Chris Mason   Btrfs: Create ext...
405
  	struct extent_buffer *cow;
7bb86316c   Chris Mason   Btrfs: Add back p...
406
  	int level;
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
407
  	int last_ref = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
408
  	int unlock_orig = 0;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
409
  	u64 parent_start;
7bb86316c   Chris Mason   Btrfs: Add back p...
410

925baeddc   Chris Mason   Btrfs: Start btre...
411
412
  	if (*cow_ret == buf)
  		unlock_orig = 1;
b9447ef80   Chris Mason   Btrfs: fix spinlo...
413
  	btrfs_assert_tree_locked(buf);
925baeddc   Chris Mason   Btrfs: Start btre...
414

7bb86316c   Chris Mason   Btrfs: Add back p...
415
416
  	WARN_ON(root->ref_cows && trans->transid !=
  		root->fs_info->running_transaction->transid);
6702ed490   Chris Mason   Btrfs: Add run ti...
417
  	WARN_ON(root->ref_cows && trans->transid != root->last_trans);
5f39d397d   Chris Mason   Btrfs: Create ext...
418

7bb86316c   Chris Mason   Btrfs: Add back p...
419
  	level = btrfs_header_level(buf);
31840ae1a   Zheng Yan   Btrfs: Full back ...
420

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  	if (level == 0)
  		btrfs_item_key(buf, &disk_key, 0);
  	else
  		btrfs_node_key(buf, &disk_key, 0);
  
  	if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
  		if (parent)
  			parent_start = parent->start;
  		else
  			parent_start = 0;
  	} else
  		parent_start = 0;
  
  	cow = btrfs_alloc_free_block(trans, root, buf->len, parent_start,
  				     root->root_key.objectid, &disk_key,
  				     level, search_start, empty_size);
54aa1f4df   Chris Mason   Btrfs: Audit call...
437
438
  	if (IS_ERR(cow))
  		return PTR_ERR(cow);
6702ed490   Chris Mason   Btrfs: Add run ti...
439

b4ce94de9   Chris Mason   Btrfs: Change btr...
440
  	/* cow is set to blocking by btrfs_init_new_buffer */
5f39d397d   Chris Mason   Btrfs: Create ext...
441
  	copy_extent_buffer(cow, buf, 0, 0, cow->len);
db94535db   Chris Mason   Btrfs: Allow tree...
442
  	btrfs_set_header_bytenr(cow, cow->start);
5f39d397d   Chris Mason   Btrfs: Create ext...
443
  	btrfs_set_header_generation(cow, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
444
445
446
447
448
449
450
  	btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV);
  	btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN |
  				     BTRFS_HEADER_FLAG_RELOC);
  	if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
  		btrfs_set_header_flag(cow, BTRFS_HEADER_FLAG_RELOC);
  	else
  		btrfs_set_header_owner(cow, root->root_key.objectid);
6702ed490   Chris Mason   Btrfs: Add run ti...
451

2b82032c3   Yan Zheng   Btrfs: Seed devic...
452
453
454
  	write_extent_buffer(cow, root->fs_info->fsid,
  			    (unsigned long)btrfs_header_fsid(cow),
  			    BTRFS_FSID_SIZE);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
455
  	update_ref_for_cow(trans, root, buf, cow, &last_ref);
1a40e23b9   Zheng Yan   Btrfs: update spa...
456

3fd0a5585   Yan, Zheng   Btrfs: Metadata E...
457
458
  	if (root->ref_cows)
  		btrfs_reloc_cow_block(trans, root, buf, cow);
02217ed29   Chris Mason   Btrfs: early refe...
459
  	if (buf == root->node) {
925baeddc   Chris Mason   Btrfs: Start btre...
460
  		WARN_ON(parent && parent != buf);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
461
462
463
464
465
  		if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
  		    btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV)
  			parent_start = buf->start;
  		else
  			parent_start = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
466

5f39d397d   Chris Mason   Btrfs: Create ext...
467
  		extent_buffer_get(cow);
240f62c87   Chris Mason   Btrfs: use RCU in...
468
  		rcu_assign_pointer(root->node, cow);
925baeddc   Chris Mason   Btrfs: Start btre...
469

f0486c68e   Yan, Zheng   Btrfs: Introduce ...
470
471
  		btrfs_free_tree_block(trans, root, buf, parent_start,
  				      last_ref);
5f39d397d   Chris Mason   Btrfs: Create ext...
472
  		free_extent_buffer(buf);
0b86a832a   Chris Mason   Btrfs: Add suppor...
473
  		add_root_to_dirty_list(root);
02217ed29   Chris Mason   Btrfs: early refe...
474
  	} else {
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
475
476
477
478
479
480
  		if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
  			parent_start = parent->start;
  		else
  			parent_start = 0;
  
  		WARN_ON(trans->transid != btrfs_header_generation(parent));
5f39d397d   Chris Mason   Btrfs: Create ext...
481
  		btrfs_set_node_blockptr(parent, parent_slot,
db94535db   Chris Mason   Btrfs: Allow tree...
482
  					cow->start);
74493f7a5   Chris Mason   Btrfs: Implement ...
483
484
  		btrfs_set_node_ptr_generation(parent, parent_slot,
  					      trans->transid);
d60255795   Chris Mason   Btrfs: corruption...
485
  		btrfs_mark_buffer_dirty(parent);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
486
487
  		btrfs_free_tree_block(trans, root, buf, parent_start,
  				      last_ref);
02217ed29   Chris Mason   Btrfs: early refe...
488
  	}
925baeddc   Chris Mason   Btrfs: Start btre...
489
490
  	if (unlock_orig)
  		btrfs_tree_unlock(buf);
5f39d397d   Chris Mason   Btrfs: Create ext...
491
  	free_extent_buffer(buf);
ccd467d60   Chris Mason   Btrfs: crash reco...
492
  	btrfs_mark_buffer_dirty(cow);
2c90e5d65   Chris Mason   Btrfs: still corr...
493
  	*cow_ret = cow;
02217ed29   Chris Mason   Btrfs: early refe...
494
495
  	return 0;
  }
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
496
497
498
499
  static inline int should_cow_block(struct btrfs_trans_handle *trans,
  				   struct btrfs_root *root,
  				   struct extent_buffer *buf)
  {
f1ebcc74d   Liu Bo   Btrfs: fix tree c...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  	/* ensure we can see the force_cow */
  	smp_rmb();
  
  	/*
  	 * We do not need to cow a block if
  	 * 1) this block is not created or changed in this transaction;
  	 * 2) this block does not belong to TREE_RELOC tree;
  	 * 3) the root is not forced COW.
  	 *
  	 * What is forced COW:
  	 *    when we create snapshot during commiting the transaction,
  	 *    after we've finished coping src root, we must COW the shared
  	 *    block to ensure the metadata consistency.
  	 */
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
514
515
516
  	if (btrfs_header_generation(buf) == trans->transid &&
  	    !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) &&
  	    !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID &&
f1ebcc74d   Liu Bo   Btrfs: fix tree c...
517
518
  	      btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)) &&
  	    !root->force_cow)
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
519
520
521
  		return 0;
  	return 1;
  }
d352ac681   Chris Mason   Btrfs: add and im...
522
523
524
525
526
  /*
   * cows a single block, see __btrfs_cow_block for the real work.
   * This version of it has extra checks so that a block isn't cow'd more than
   * once per transaction, as long as it hasn't been written yet
   */
d397712bc   Chris Mason   Btrfs: Fix checkp...
527
  noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
5f39d397d   Chris Mason   Btrfs: Create ext...
528
529
  		    struct btrfs_root *root, struct extent_buffer *buf,
  		    struct extent_buffer *parent, int parent_slot,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
530
  		    struct extent_buffer **cow_ret)
6702ed490   Chris Mason   Btrfs: Add run ti...
531
532
  {
  	u64 search_start;
f510cfecf   Chris Mason   Btrfs: Fix extent...
533
  	int ret;
dc17ff8f1   Chris Mason   Btrfs: Add data=o...
534

6702ed490   Chris Mason   Btrfs: Add run ti...
535
  	if (trans->transaction != root->fs_info->running_transaction) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
536
537
538
539
  		printk(KERN_CRIT "trans %llu running %llu
  ",
  		       (unsigned long long)trans->transid,
  		       (unsigned long long)
6702ed490   Chris Mason   Btrfs: Add run ti...
540
541
542
543
  		       root->fs_info->running_transaction->transid);
  		WARN_ON(1);
  	}
  	if (trans->transid != root->fs_info->generation) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
544
545
546
547
  		printk(KERN_CRIT "trans %llu running %llu
  ",
  		       (unsigned long long)trans->transid,
  		       (unsigned long long)root->fs_info->generation);
6702ed490   Chris Mason   Btrfs: Add run ti...
548
549
  		WARN_ON(1);
  	}
dc17ff8f1   Chris Mason   Btrfs: Add data=o...
550

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
551
  	if (!should_cow_block(trans, root, buf)) {
6702ed490   Chris Mason   Btrfs: Add run ti...
552
553
554
  		*cow_ret = buf;
  		return 0;
  	}
c487685d7   Chris Mason   Btrfs: hash_lock ...
555

0b86a832a   Chris Mason   Btrfs: Add suppor...
556
  	search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
b4ce94de9   Chris Mason   Btrfs: Change btr...
557
558
559
560
  
  	if (parent)
  		btrfs_set_lock_blocking(parent);
  	btrfs_set_lock_blocking(buf);
f510cfecf   Chris Mason   Btrfs: Fix extent...
561
  	ret = __btrfs_cow_block(trans, root, buf, parent,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
562
  				 parent_slot, cow_ret, search_start, 0);
1abe9b8a1   liubo   Btrfs: add initia...
563
564
  
  	trace_btrfs_cow_block(root, buf, *cow_ret);
f510cfecf   Chris Mason   Btrfs: Fix extent...
565
  	return ret;
6702ed490   Chris Mason   Btrfs: Add run ti...
566
  }
d352ac681   Chris Mason   Btrfs: add and im...
567
568
569
570
  /*
   * helper function for defrag to decide if two blocks pointed to by a
   * node are actually close by
   */
6b80053d0   Chris Mason   Btrfs: Add back t...
571
  static int close_blocks(u64 blocknr, u64 other, u32 blocksize)
6702ed490   Chris Mason   Btrfs: Add run ti...
572
  {
6b80053d0   Chris Mason   Btrfs: Add back t...
573
  	if (blocknr < other && other - (blocknr + blocksize) < 32768)
6702ed490   Chris Mason   Btrfs: Add run ti...
574
  		return 1;
6b80053d0   Chris Mason   Btrfs: Add back t...
575
  	if (blocknr > other && blocknr - (other + blocksize) < 32768)
6702ed490   Chris Mason   Btrfs: Add run ti...
576
577
578
  		return 1;
  	return 0;
  }
081e95736   Chris Mason   Btrfs: Make defra...
579
580
581
582
583
584
585
586
  /*
   * compare two keys in a memcmp fashion
   */
  static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
  {
  	struct btrfs_key k1;
  
  	btrfs_disk_key_to_cpu(&k1, disk);
20736abaa   Diego Calleja   Btrfs: Remove cod...
587
  	return btrfs_comp_cpu_keys(&k1, k2);
081e95736   Chris Mason   Btrfs: Make defra...
588
  }
f3465ca44   Josef Bacik   Btrfs: batch exte...
589
590
591
  /*
   * same as comp_keys only with two btrfs_key's
   */
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
592
  int btrfs_comp_cpu_keys(struct btrfs_key *k1, struct btrfs_key *k2)
f3465ca44   Josef Bacik   Btrfs: batch exte...
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  {
  	if (k1->objectid > k2->objectid)
  		return 1;
  	if (k1->objectid < k2->objectid)
  		return -1;
  	if (k1->type > k2->type)
  		return 1;
  	if (k1->type < k2->type)
  		return -1;
  	if (k1->offset > k2->offset)
  		return 1;
  	if (k1->offset < k2->offset)
  		return -1;
  	return 0;
  }
081e95736   Chris Mason   Btrfs: Make defra...
608

d352ac681   Chris Mason   Btrfs: add and im...
609
610
611
612
613
  /*
   * this is used by the defrag code to go through all the
   * leaves pointed to by a node and reallocate them so that
   * disk order is close to key order
   */
6702ed490   Chris Mason   Btrfs: Add run ti...
614
  int btrfs_realloc_node(struct btrfs_trans_handle *trans,
5f39d397d   Chris Mason   Btrfs: Create ext...
615
  		       struct btrfs_root *root, struct extent_buffer *parent,
a6b6e75e0   Chris Mason   Btrfs: Defrag onl...
616
617
  		       int start_slot, int cache_only, u64 *last_ret,
  		       struct btrfs_key *progress)
6702ed490   Chris Mason   Btrfs: Add run ti...
618
  {
6b80053d0   Chris Mason   Btrfs: Add back t...
619
  	struct extent_buffer *cur;
6702ed490   Chris Mason   Btrfs: Add run ti...
620
  	u64 blocknr;
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
621
  	u64 gen;
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
622
623
  	u64 search_start = *last_ret;
  	u64 last_block = 0;
6702ed490   Chris Mason   Btrfs: Add run ti...
624
625
  	u64 other;
  	u32 parent_nritems;
6702ed490   Chris Mason   Btrfs: Add run ti...
626
627
628
  	int end_slot;
  	int i;
  	int err = 0;
f2183bde1   Chris Mason   Btrfs: Add BH_Def...
629
  	int parent_level;
6b80053d0   Chris Mason   Btrfs: Add back t...
630
631
  	int uptodate;
  	u32 blocksize;
081e95736   Chris Mason   Btrfs: Make defra...
632
633
  	int progress_passed = 0;
  	struct btrfs_disk_key disk_key;
6702ed490   Chris Mason   Btrfs: Add run ti...
634

5708b9591   Chris Mason   Btrfs: Tune the a...
635
636
637
  	parent_level = btrfs_header_level(parent);
  	if (cache_only && parent_level != 1)
  		return 0;
d397712bc   Chris Mason   Btrfs: Fix checkp...
638
  	if (trans->transaction != root->fs_info->running_transaction)
6702ed490   Chris Mason   Btrfs: Add run ti...
639
  		WARN_ON(1);
d397712bc   Chris Mason   Btrfs: Fix checkp...
640
  	if (trans->transid != root->fs_info->generation)
6702ed490   Chris Mason   Btrfs: Add run ti...
641
  		WARN_ON(1);
86479a04e   Chris Mason   Add support for d...
642

6b80053d0   Chris Mason   Btrfs: Add back t...
643
  	parent_nritems = btrfs_header_nritems(parent);
6b80053d0   Chris Mason   Btrfs: Add back t...
644
  	blocksize = btrfs_level_size(root, parent_level - 1);
6702ed490   Chris Mason   Btrfs: Add run ti...
645
646
647
648
  	end_slot = parent_nritems;
  
  	if (parent_nritems == 1)
  		return 0;
b4ce94de9   Chris Mason   Btrfs: Change btr...
649
  	btrfs_set_lock_blocking(parent);
6702ed490   Chris Mason   Btrfs: Add run ti...
650
651
  	for (i = start_slot; i < end_slot; i++) {
  		int close = 1;
a6b6e75e0   Chris Mason   Btrfs: Defrag onl...
652

081e95736   Chris Mason   Btrfs: Make defra...
653
654
655
656
657
  		btrfs_node_key(parent, &disk_key, i);
  		if (!progress_passed && comp_keys(&disk_key, progress) < 0)
  			continue;
  
  		progress_passed = 1;
6b80053d0   Chris Mason   Btrfs: Add back t...
658
  		blocknr = btrfs_node_blockptr(parent, i);
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
659
  		gen = btrfs_node_ptr_generation(parent, i);
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
660
661
  		if (last_block == 0)
  			last_block = blocknr;
5708b9591   Chris Mason   Btrfs: Tune the a...
662

6702ed490   Chris Mason   Btrfs: Add run ti...
663
  		if (i > 0) {
6b80053d0   Chris Mason   Btrfs: Add back t...
664
665
  			other = btrfs_node_blockptr(parent, i - 1);
  			close = close_blocks(blocknr, other, blocksize);
6702ed490   Chris Mason   Btrfs: Add run ti...
666
  		}
0ef3e66b6   Chris Mason   Btrfs: Allocator ...
667
  		if (!close && i < end_slot - 2) {
6b80053d0   Chris Mason   Btrfs: Add back t...
668
669
  			other = btrfs_node_blockptr(parent, i + 1);
  			close = close_blocks(blocknr, other, blocksize);
6702ed490   Chris Mason   Btrfs: Add run ti...
670
  		}
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
671
672
  		if (close) {
  			last_block = blocknr;
6702ed490   Chris Mason   Btrfs: Add run ti...
673
  			continue;
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
674
  		}
6702ed490   Chris Mason   Btrfs: Add run ti...
675

6b80053d0   Chris Mason   Btrfs: Add back t...
676
677
  		cur = btrfs_find_tree_block(root, blocknr, blocksize);
  		if (cur)
1259ab75c   Chris Mason   Btrfs: Handle wri...
678
  			uptodate = btrfs_buffer_uptodate(cur, gen);
6b80053d0   Chris Mason   Btrfs: Add back t...
679
680
  		else
  			uptodate = 0;
5708b9591   Chris Mason   Btrfs: Tune the a...
681
  		if (!cur || !uptodate) {
6702ed490   Chris Mason   Btrfs: Add run ti...
682
  			if (cache_only) {
6b80053d0   Chris Mason   Btrfs: Add back t...
683
  				free_extent_buffer(cur);
6702ed490   Chris Mason   Btrfs: Add run ti...
684
685
  				continue;
  			}
6b80053d0   Chris Mason   Btrfs: Add back t...
686
687
  			if (!cur) {
  				cur = read_tree_block(root, blocknr,
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
688
  							 blocksize, gen);
97d9a8a42   Tsutomu Itoh   Btrfs: check retu...
689
690
  				if (!cur)
  					return -EIO;
6b80053d0   Chris Mason   Btrfs: Add back t...
691
  			} else if (!uptodate) {
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
692
  				btrfs_read_buffer(cur, gen);
f2183bde1   Chris Mason   Btrfs: Add BH_Def...
693
  			}
6702ed490   Chris Mason   Btrfs: Add run ti...
694
  		}
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
695
  		if (search_start == 0)
6b80053d0   Chris Mason   Btrfs: Add back t...
696
  			search_start = last_block;
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
697

e7a84565b   Chris Mason   Btrfs: Add btree ...
698
  		btrfs_tree_lock(cur);
b4ce94de9   Chris Mason   Btrfs: Change btr...
699
  		btrfs_set_lock_blocking(cur);
6b80053d0   Chris Mason   Btrfs: Add back t...
700
  		err = __btrfs_cow_block(trans, root, cur, parent, i,
e7a84565b   Chris Mason   Btrfs: Add btree ...
701
  					&cur, search_start,
6b80053d0   Chris Mason   Btrfs: Add back t...
702
  					min(16 * blocksize,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
703
  					    (end_slot - i) * blocksize));
252c38f06   Yan   Btrfs: ctree.c cl...
704
  		if (err) {
e7a84565b   Chris Mason   Btrfs: Add btree ...
705
  			btrfs_tree_unlock(cur);
6b80053d0   Chris Mason   Btrfs: Add back t...
706
  			free_extent_buffer(cur);
6702ed490   Chris Mason   Btrfs: Add run ti...
707
  			break;
252c38f06   Yan   Btrfs: ctree.c cl...
708
  		}
e7a84565b   Chris Mason   Btrfs: Add btree ...
709
710
  		search_start = cur->start;
  		last_block = cur->start;
f2183bde1   Chris Mason   Btrfs: Add BH_Def...
711
  		*last_ret = search_start;
e7a84565b   Chris Mason   Btrfs: Add btree ...
712
713
  		btrfs_tree_unlock(cur);
  		free_extent_buffer(cur);
6702ed490   Chris Mason   Btrfs: Add run ti...
714
715
716
  	}
  	return err;
  }
74123bd72   Chris Mason   Btrfs: Commenting...
717
718
719
720
721
  /*
   * The leaf data grows from end-to-front in the node.
   * this returns the address of the start of the last item,
   * which is the stop of the leaf data stack
   */
123abc88c   Chris Mason   Btrfs: variable b...
722
  static inline unsigned int leaf_data_end(struct btrfs_root *root,
5f39d397d   Chris Mason   Btrfs: Create ext...
723
  					 struct extent_buffer *leaf)
be0e5c097   Chris Mason   Btrfs: Initial ch...
724
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
725
  	u32 nr = btrfs_header_nritems(leaf);
be0e5c097   Chris Mason   Btrfs: Initial ch...
726
  	if (nr == 0)
123abc88c   Chris Mason   Btrfs: variable b...
727
  		return BTRFS_LEAF_DATA_SIZE(root);
5f39d397d   Chris Mason   Btrfs: Create ext...
728
  	return btrfs_item_offset_nr(leaf, nr - 1);
be0e5c097   Chris Mason   Btrfs: Initial ch...
729
  }
aa5d6bed2   Chris Mason   Btrfs: return cod...
730

74123bd72   Chris Mason   Btrfs: Commenting...
731
  /*
5f39d397d   Chris Mason   Btrfs: Create ext...
732
733
734
   * search for key in the extent_buffer.  The items start at offset p,
   * and they are item_size apart.  There are 'max' items in p.
   *
74123bd72   Chris Mason   Btrfs: Commenting...
735
736
737
738
739
740
   * the slot in the array is returned via slot, and it points to
   * the place where you would insert key if it is not found in
   * the array.
   *
   * slot may point to max if the key is bigger than all of the keys
   */
e02119d5a   Chris Mason   Btrfs: Add a writ...
741
742
743
744
  static noinline int generic_bin_search(struct extent_buffer *eb,
  				       unsigned long p,
  				       int item_size, struct btrfs_key *key,
  				       int max, int *slot)
be0e5c097   Chris Mason   Btrfs: Initial ch...
745
746
747
748
749
  {
  	int low = 0;
  	int high = max;
  	int mid;
  	int ret;
479965d66   Chris Mason   Btrfs: Optimizati...
750
  	struct btrfs_disk_key *tmp = NULL;
5f39d397d   Chris Mason   Btrfs: Create ext...
751
752
  	struct btrfs_disk_key unaligned;
  	unsigned long offset;
5f39d397d   Chris Mason   Btrfs: Create ext...
753
754
755
  	char *kaddr = NULL;
  	unsigned long map_start = 0;
  	unsigned long map_len = 0;
479965d66   Chris Mason   Btrfs: Optimizati...
756
  	int err;
be0e5c097   Chris Mason   Btrfs: Initial ch...
757

d397712bc   Chris Mason   Btrfs: Fix checkp...
758
  	while (low < high) {
be0e5c097   Chris Mason   Btrfs: Initial ch...
759
  		mid = (low + high) / 2;
5f39d397d   Chris Mason   Btrfs: Create ext...
760
  		offset = p + mid * item_size;
a65917156   Chris Mason   Btrfs: stop using...
761
  		if (!kaddr || offset < map_start ||
5f39d397d   Chris Mason   Btrfs: Create ext...
762
763
  		    (offset + sizeof(struct btrfs_disk_key)) >
  		    map_start + map_len) {
934d375ba   Chris Mason   Btrfs: Use map_pr...
764
765
  
  			err = map_private_extent_buffer(eb, offset,
479965d66   Chris Mason   Btrfs: Optimizati...
766
  						sizeof(struct btrfs_disk_key),
a65917156   Chris Mason   Btrfs: stop using...
767
  						&kaddr, &map_start, &map_len);
479965d66   Chris Mason   Btrfs: Optimizati...
768
769
770
771
772
773
774
775
776
  
  			if (!err) {
  				tmp = (struct btrfs_disk_key *)(kaddr + offset -
  							map_start);
  			} else {
  				read_extent_buffer(eb, &unaligned,
  						   offset, sizeof(unaligned));
  				tmp = &unaligned;
  			}
5f39d397d   Chris Mason   Btrfs: Create ext...
777

5f39d397d   Chris Mason   Btrfs: Create ext...
778
779
780
781
  		} else {
  			tmp = (struct btrfs_disk_key *)(kaddr + offset -
  							map_start);
  		}
be0e5c097   Chris Mason   Btrfs: Initial ch...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  		ret = comp_keys(tmp, key);
  
  		if (ret < 0)
  			low = mid + 1;
  		else if (ret > 0)
  			high = mid;
  		else {
  			*slot = mid;
  			return 0;
  		}
  	}
  	*slot = low;
  	return 1;
  }
97571fd0c   Chris Mason   Btrfs: cleanup & ...
796
797
798
799
  /*
   * simple bin_search frontend that does the right thing for
   * leaves vs nodes
   */
5f39d397d   Chris Mason   Btrfs: Create ext...
800
801
  static int bin_search(struct extent_buffer *eb, struct btrfs_key *key,
  		      int level, int *slot)
be0e5c097   Chris Mason   Btrfs: Initial ch...
802
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
803
804
805
  	if (level == 0) {
  		return generic_bin_search(eb,
  					  offsetof(struct btrfs_leaf, items),
0783fcfc4   Chris Mason   Btrfs: struct ite...
806
  					  sizeof(struct btrfs_item),
5f39d397d   Chris Mason   Btrfs: Create ext...
807
  					  key, btrfs_header_nritems(eb),
7518a238e   Chris Mason   Btrfs: get/set fo...
808
  					  slot);
be0e5c097   Chris Mason   Btrfs: Initial ch...
809
  	} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
810
811
  		return generic_bin_search(eb,
  					  offsetof(struct btrfs_node, ptrs),
123abc88c   Chris Mason   Btrfs: variable b...
812
  					  sizeof(struct btrfs_key_ptr),
5f39d397d   Chris Mason   Btrfs: Create ext...
813
  					  key, btrfs_header_nritems(eb),
7518a238e   Chris Mason   Btrfs: get/set fo...
814
  					  slot);
be0e5c097   Chris Mason   Btrfs: Initial ch...
815
816
817
  	}
  	return -1;
  }
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
818
819
820
821
822
  int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
  		     int level, int *slot)
  {
  	return bin_search(eb, key, level, slot);
  }
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
  static void root_add_used(struct btrfs_root *root, u32 size)
  {
  	spin_lock(&root->accounting_lock);
  	btrfs_set_root_used(&root->root_item,
  			    btrfs_root_used(&root->root_item) + size);
  	spin_unlock(&root->accounting_lock);
  }
  
  static void root_sub_used(struct btrfs_root *root, u32 size)
  {
  	spin_lock(&root->accounting_lock);
  	btrfs_set_root_used(&root->root_item,
  			    btrfs_root_used(&root->root_item) - size);
  	spin_unlock(&root->accounting_lock);
  }
d352ac681   Chris Mason   Btrfs: add and im...
838
839
840
841
  /* given a node and slot number, this reads the blocks it points to.  The
   * extent buffer is returned with a reference taken (but unlocked).
   * NULL is returned on error.
   */
e02119d5a   Chris Mason   Btrfs: Add a writ...
842
  static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
5f39d397d   Chris Mason   Btrfs: Create ext...
843
  				   struct extent_buffer *parent, int slot)
bb8039515   Chris Mason   Btrfs: merge on t...
844
  {
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
845
  	int level = btrfs_header_level(parent);
bb8039515   Chris Mason   Btrfs: merge on t...
846
847
  	if (slot < 0)
  		return NULL;
5f39d397d   Chris Mason   Btrfs: Create ext...
848
  	if (slot >= btrfs_header_nritems(parent))
bb8039515   Chris Mason   Btrfs: merge on t...
849
  		return NULL;
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
850
851
  
  	BUG_ON(level == 0);
db94535db   Chris Mason   Btrfs: Allow tree...
852
  	return read_tree_block(root, btrfs_node_blockptr(parent, slot),
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
853
854
  		       btrfs_level_size(root, level - 1),
  		       btrfs_node_ptr_generation(parent, slot));
bb8039515   Chris Mason   Btrfs: merge on t...
855
  }
d352ac681   Chris Mason   Btrfs: add and im...
856
857
858
859
860
  /*
   * node level balancing, used to make sure nodes are in proper order for
   * item deletion.  We balance from the top down, so we have to make sure
   * that a deletion won't leave an node completely empty later on.
   */
e02119d5a   Chris Mason   Btrfs: Add a writ...
861
  static noinline int balance_level(struct btrfs_trans_handle *trans,
98ed51747   Chris Mason   Btrfs: Force inli...
862
863
  			 struct btrfs_root *root,
  			 struct btrfs_path *path, int level)
bb8039515   Chris Mason   Btrfs: merge on t...
864
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
865
866
867
868
  	struct extent_buffer *right = NULL;
  	struct extent_buffer *mid;
  	struct extent_buffer *left = NULL;
  	struct extent_buffer *parent = NULL;
bb8039515   Chris Mason   Btrfs: merge on t...
869
870
871
  	int ret = 0;
  	int wret;
  	int pslot;
bb8039515   Chris Mason   Btrfs: merge on t...
872
  	int orig_slot = path->slots[level];
79f95c82d   Chris Mason   Btrfs: Fixup the ...
873
  	u64 orig_ptr;
bb8039515   Chris Mason   Btrfs: merge on t...
874
875
876
  
  	if (level == 0)
  		return 0;
5f39d397d   Chris Mason   Btrfs: Create ext...
877
  	mid = path->nodes[level];
b4ce94de9   Chris Mason   Btrfs: Change btr...
878

bd681513f   Chris Mason   Btrfs: switch the...
879
880
  	WARN_ON(path->locks[level] != BTRFS_WRITE_LOCK &&
  		path->locks[level] != BTRFS_WRITE_LOCK_BLOCKING);
7bb86316c   Chris Mason   Btrfs: Add back p...
881
  	WARN_ON(btrfs_header_generation(mid) != trans->transid);
1d4f8a0c1   Chris Mason   Btrfs: node->bloc...
882
  	orig_ptr = btrfs_node_blockptr(mid, orig_slot);
79f95c82d   Chris Mason   Btrfs: Fixup the ...
883

a05a9bb18   Li Zefan   Btrfs: fix array ...
884
  	if (level < BTRFS_MAX_LEVEL - 1) {
5f39d397d   Chris Mason   Btrfs: Create ext...
885
  		parent = path->nodes[level + 1];
a05a9bb18   Li Zefan   Btrfs: fix array ...
886
887
  		pslot = path->slots[level + 1];
  	}
bb8039515   Chris Mason   Btrfs: merge on t...
888

406894788   Chris Mason   Btrfs: minor comm...
889
890
891
892
  	/*
  	 * deal with the case where there is only one pointer in the root
  	 * by promoting the node below to a root
  	 */
5f39d397d   Chris Mason   Btrfs: Create ext...
893
894
  	if (!parent) {
  		struct extent_buffer *child;
bb8039515   Chris Mason   Btrfs: merge on t...
895

5f39d397d   Chris Mason   Btrfs: Create ext...
896
  		if (btrfs_header_nritems(mid) != 1)
bb8039515   Chris Mason   Btrfs: merge on t...
897
898
899
  			return 0;
  
  		/* promote the child to a root */
5f39d397d   Chris Mason   Btrfs: Create ext...
900
  		child = read_node_slot(root, mid, 0);
7951f3cef   Jeff Mahoney   Btrfs: balance_le...
901
  		BUG_ON(!child);
925baeddc   Chris Mason   Btrfs: Start btre...
902
  		btrfs_tree_lock(child);
b4ce94de9   Chris Mason   Btrfs: Change btr...
903
  		btrfs_set_lock_blocking(child);
9fa8cfe70   Chris Mason   Btrfs: don't prea...
904
  		ret = btrfs_cow_block(trans, root, child, mid, 0, &child);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
905
906
907
908
909
  		if (ret) {
  			btrfs_tree_unlock(child);
  			free_extent_buffer(child);
  			goto enospc;
  		}
2f375ab9c   Yan   Call btrfs_cow_bl...
910

240f62c87   Chris Mason   Btrfs: use RCU in...
911
  		rcu_assign_pointer(root->node, child);
925baeddc   Chris Mason   Btrfs: Start btre...
912

0b86a832a   Chris Mason   Btrfs: Add suppor...
913
  		add_root_to_dirty_list(root);
925baeddc   Chris Mason   Btrfs: Start btre...
914
  		btrfs_tree_unlock(child);
b4ce94de9   Chris Mason   Btrfs: Change btr...
915

925baeddc   Chris Mason   Btrfs: Start btre...
916
  		path->locks[level] = 0;
bb8039515   Chris Mason   Btrfs: merge on t...
917
  		path->nodes[level] = NULL;
5f39d397d   Chris Mason   Btrfs: Create ext...
918
  		clean_tree_block(trans, root, mid);
925baeddc   Chris Mason   Btrfs: Start btre...
919
  		btrfs_tree_unlock(mid);
bb8039515   Chris Mason   Btrfs: merge on t...
920
  		/* once for the path */
5f39d397d   Chris Mason   Btrfs: Create ext...
921
  		free_extent_buffer(mid);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
922
923
924
  
  		root_sub_used(root, mid->len);
  		btrfs_free_tree_block(trans, root, mid, 0, 1);
bb8039515   Chris Mason   Btrfs: merge on t...
925
  		/* once for the root ptr */
5f39d397d   Chris Mason   Btrfs: Create ext...
926
  		free_extent_buffer(mid);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
927
  		return 0;
bb8039515   Chris Mason   Btrfs: merge on t...
928
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
929
  	if (btrfs_header_nritems(mid) >
123abc88c   Chris Mason   Btrfs: variable b...
930
  	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
bb8039515   Chris Mason   Btrfs: merge on t...
931
  		return 0;
559af8211   Andi Kleen   Btrfs: cleanup wa...
932
  	btrfs_header_nritems(mid);
54aa1f4df   Chris Mason   Btrfs: Audit call...
933

5f39d397d   Chris Mason   Btrfs: Create ext...
934
935
  	left = read_node_slot(root, parent, pslot - 1);
  	if (left) {
925baeddc   Chris Mason   Btrfs: Start btre...
936
  		btrfs_tree_lock(left);
b4ce94de9   Chris Mason   Btrfs: Change btr...
937
  		btrfs_set_lock_blocking(left);
5f39d397d   Chris Mason   Btrfs: Create ext...
938
  		wret = btrfs_cow_block(trans, root, left,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
939
  				       parent, pslot - 1, &left);
54aa1f4df   Chris Mason   Btrfs: Audit call...
940
941
942
943
  		if (wret) {
  			ret = wret;
  			goto enospc;
  		}
2cc58cf24   Chris Mason   Btrfs: Do more ex...
944
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
945
946
  	right = read_node_slot(root, parent, pslot + 1);
  	if (right) {
925baeddc   Chris Mason   Btrfs: Start btre...
947
  		btrfs_tree_lock(right);
b4ce94de9   Chris Mason   Btrfs: Change btr...
948
  		btrfs_set_lock_blocking(right);
5f39d397d   Chris Mason   Btrfs: Create ext...
949
  		wret = btrfs_cow_block(trans, root, right,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
950
  				       parent, pslot + 1, &right);
2cc58cf24   Chris Mason   Btrfs: Do more ex...
951
952
953
954
955
956
957
  		if (wret) {
  			ret = wret;
  			goto enospc;
  		}
  	}
  
  	/* first, try to make some room in the middle buffer */
5f39d397d   Chris Mason   Btrfs: Create ext...
958
959
  	if (left) {
  		orig_slot += btrfs_header_nritems(left);
bce4eae98   Chris Mason   Btrfs: Fix balanc...
960
  		wret = push_node_left(trans, root, left, mid, 1);
79f95c82d   Chris Mason   Btrfs: Fixup the ...
961
962
  		if (wret < 0)
  			ret = wret;
559af8211   Andi Kleen   Btrfs: cleanup wa...
963
  		btrfs_header_nritems(mid);
bb8039515   Chris Mason   Btrfs: merge on t...
964
  	}
79f95c82d   Chris Mason   Btrfs: Fixup the ...
965
966
967
968
  
  	/*
  	 * then try to empty the right most buffer into the middle
  	 */
5f39d397d   Chris Mason   Btrfs: Create ext...
969
  	if (right) {
971a1f664   Chris Mason   Btrfs: Don't empt...
970
  		wret = push_node_left(trans, root, mid, right, 1);
54aa1f4df   Chris Mason   Btrfs: Audit call...
971
  		if (wret < 0 && wret != -ENOSPC)
79f95c82d   Chris Mason   Btrfs: Fixup the ...
972
  			ret = wret;
5f39d397d   Chris Mason   Btrfs: Create ext...
973
  		if (btrfs_header_nritems(right) == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
974
  			clean_tree_block(trans, root, right);
925baeddc   Chris Mason   Btrfs: Start btre...
975
  			btrfs_tree_unlock(right);
e089f05c1   Chris Mason   Btrfs: transactio...
976
977
  			wret = del_ptr(trans, root, path, level + 1, pslot +
  				       1);
bb8039515   Chris Mason   Btrfs: merge on t...
978
979
  			if (wret)
  				ret = wret;
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
980
981
982
983
  			root_sub_used(root, right->len);
  			btrfs_free_tree_block(trans, root, right, 0, 1);
  			free_extent_buffer(right);
  			right = NULL;
bb8039515   Chris Mason   Btrfs: merge on t...
984
  		} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
985
986
987
988
  			struct btrfs_disk_key right_key;
  			btrfs_node_key(right, &right_key, 0);
  			btrfs_set_node_key(parent, &right_key, pslot + 1);
  			btrfs_mark_buffer_dirty(parent);
bb8039515   Chris Mason   Btrfs: merge on t...
989
990
  		}
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
991
  	if (btrfs_header_nritems(mid) == 1) {
79f95c82d   Chris Mason   Btrfs: Fixup the ...
992
993
994
995
996
997
998
999
1000
  		/*
  		 * we're not allowed to leave a node with one item in the
  		 * tree during a delete.  A deletion from lower in the tree
  		 * could try to delete the only pointer in this node.
  		 * So, pull some keys from the left.
  		 * There has to be a left pointer at this point because
  		 * otherwise we would have pulled some pointers from the
  		 * right
  		 */
5f39d397d   Chris Mason   Btrfs: Create ext...
1001
1002
  		BUG_ON(!left);
  		wret = balance_node_right(trans, root, mid, left);
54aa1f4df   Chris Mason   Btrfs: Audit call...
1003
  		if (wret < 0) {
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1004
  			ret = wret;
54aa1f4df   Chris Mason   Btrfs: Audit call...
1005
1006
  			goto enospc;
  		}
bce4eae98   Chris Mason   Btrfs: Fix balanc...
1007
1008
1009
1010
1011
  		if (wret == 1) {
  			wret = push_node_left(trans, root, left, mid, 1);
  			if (wret < 0)
  				ret = wret;
  		}
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1012
1013
  		BUG_ON(wret == 1);
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
1014
  	if (btrfs_header_nritems(mid) == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
1015
  		clean_tree_block(trans, root, mid);
925baeddc   Chris Mason   Btrfs: Start btre...
1016
  		btrfs_tree_unlock(mid);
e089f05c1   Chris Mason   Btrfs: transactio...
1017
  		wret = del_ptr(trans, root, path, level + 1, pslot);
bb8039515   Chris Mason   Btrfs: merge on t...
1018
1019
  		if (wret)
  			ret = wret;
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
1020
1021
1022
1023
  		root_sub_used(root, mid->len);
  		btrfs_free_tree_block(trans, root, mid, 0, 1);
  		free_extent_buffer(mid);
  		mid = NULL;
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1024
1025
  	} else {
  		/* update the parent key to reflect our changes */
5f39d397d   Chris Mason   Btrfs: Create ext...
1026
1027
1028
1029
  		struct btrfs_disk_key mid_key;
  		btrfs_node_key(mid, &mid_key, 0);
  		btrfs_set_node_key(parent, &mid_key, pslot);
  		btrfs_mark_buffer_dirty(parent);
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1030
  	}
bb8039515   Chris Mason   Btrfs: merge on t...
1031

79f95c82d   Chris Mason   Btrfs: Fixup the ...
1032
  	/* update the path */
5f39d397d   Chris Mason   Btrfs: Create ext...
1033
1034
1035
  	if (left) {
  		if (btrfs_header_nritems(left) > orig_slot) {
  			extent_buffer_get(left);
925baeddc   Chris Mason   Btrfs: Start btre...
1036
  			/* left was locked after cow */
5f39d397d   Chris Mason   Btrfs: Create ext...
1037
  			path->nodes[level] = left;
bb8039515   Chris Mason   Btrfs: merge on t...
1038
1039
  			path->slots[level + 1] -= 1;
  			path->slots[level] = orig_slot;
925baeddc   Chris Mason   Btrfs: Start btre...
1040
1041
  			if (mid) {
  				btrfs_tree_unlock(mid);
5f39d397d   Chris Mason   Btrfs: Create ext...
1042
  				free_extent_buffer(mid);
925baeddc   Chris Mason   Btrfs: Start btre...
1043
  			}
bb8039515   Chris Mason   Btrfs: merge on t...
1044
  		} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
1045
  			orig_slot -= btrfs_header_nritems(left);
bb8039515   Chris Mason   Btrfs: merge on t...
1046
1047
1048
  			path->slots[level] = orig_slot;
  		}
  	}
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1049
  	/* double check we haven't messed things up */
e20d96d64   Chris Mason   Mountable btrfs, ...
1050
  	if (orig_ptr !=
5f39d397d   Chris Mason   Btrfs: Create ext...
1051
  	    btrfs_node_blockptr(path->nodes[level], path->slots[level]))
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1052
  		BUG();
54aa1f4df   Chris Mason   Btrfs: Audit call...
1053
  enospc:
925baeddc   Chris Mason   Btrfs: Start btre...
1054
1055
  	if (right) {
  		btrfs_tree_unlock(right);
5f39d397d   Chris Mason   Btrfs: Create ext...
1056
  		free_extent_buffer(right);
925baeddc   Chris Mason   Btrfs: Start btre...
1057
1058
1059
1060
  	}
  	if (left) {
  		if (path->nodes[level] != left)
  			btrfs_tree_unlock(left);
5f39d397d   Chris Mason   Btrfs: Create ext...
1061
  		free_extent_buffer(left);
925baeddc   Chris Mason   Btrfs: Start btre...
1062
  	}
bb8039515   Chris Mason   Btrfs: merge on t...
1063
1064
  	return ret;
  }
d352ac681   Chris Mason   Btrfs: add and im...
1065
1066
1067
1068
  /* Node balancing for insertion.  Here we only split or push nodes around
   * when they are completely full.  This is also done top down, so we
   * have to be pessimistic.
   */
d397712bc   Chris Mason   Btrfs: Fix checkp...
1069
  static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
98ed51747   Chris Mason   Btrfs: Force inli...
1070
1071
  					  struct btrfs_root *root,
  					  struct btrfs_path *path, int level)
e66f709b1   Chris Mason   Btrfs: write barr...
1072
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
1073
1074
1075
1076
  	struct extent_buffer *right = NULL;
  	struct extent_buffer *mid;
  	struct extent_buffer *left = NULL;
  	struct extent_buffer *parent = NULL;
e66f709b1   Chris Mason   Btrfs: write barr...
1077
1078
1079
1080
  	int ret = 0;
  	int wret;
  	int pslot;
  	int orig_slot = path->slots[level];
e66f709b1   Chris Mason   Btrfs: write barr...
1081
1082
1083
  
  	if (level == 0)
  		return 1;
5f39d397d   Chris Mason   Btrfs: Create ext...
1084
  	mid = path->nodes[level];
7bb86316c   Chris Mason   Btrfs: Add back p...
1085
  	WARN_ON(btrfs_header_generation(mid) != trans->transid);
e66f709b1   Chris Mason   Btrfs: write barr...
1086

a05a9bb18   Li Zefan   Btrfs: fix array ...
1087
  	if (level < BTRFS_MAX_LEVEL - 1) {
5f39d397d   Chris Mason   Btrfs: Create ext...
1088
  		parent = path->nodes[level + 1];
a05a9bb18   Li Zefan   Btrfs: fix array ...
1089
1090
  		pslot = path->slots[level + 1];
  	}
e66f709b1   Chris Mason   Btrfs: write barr...
1091

5f39d397d   Chris Mason   Btrfs: Create ext...
1092
  	if (!parent)
e66f709b1   Chris Mason   Btrfs: write barr...
1093
  		return 1;
e66f709b1   Chris Mason   Btrfs: write barr...
1094

5f39d397d   Chris Mason   Btrfs: Create ext...
1095
  	left = read_node_slot(root, parent, pslot - 1);
e66f709b1   Chris Mason   Btrfs: write barr...
1096
1097
  
  	/* first, try to make some room in the middle buffer */
5f39d397d   Chris Mason   Btrfs: Create ext...
1098
  	if (left) {
e66f709b1   Chris Mason   Btrfs: write barr...
1099
  		u32 left_nr;
925baeddc   Chris Mason   Btrfs: Start btre...
1100
1101
  
  		btrfs_tree_lock(left);
b4ce94de9   Chris Mason   Btrfs: Change btr...
1102
  		btrfs_set_lock_blocking(left);
5f39d397d   Chris Mason   Btrfs: Create ext...
1103
  		left_nr = btrfs_header_nritems(left);
33ade1f82   Chris Mason   Btrfs: node balan...
1104
1105
1106
  		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
  			wret = 1;
  		} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
1107
  			ret = btrfs_cow_block(trans, root, left, parent,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
1108
  					      pslot - 1, &left);
54aa1f4df   Chris Mason   Btrfs: Audit call...
1109
1110
1111
  			if (ret)
  				wret = 1;
  			else {
54aa1f4df   Chris Mason   Btrfs: Audit call...
1112
  				wret = push_node_left(trans, root,
971a1f664   Chris Mason   Btrfs: Don't empt...
1113
  						      left, mid, 0);
54aa1f4df   Chris Mason   Btrfs: Audit call...
1114
  			}
33ade1f82   Chris Mason   Btrfs: node balan...
1115
  		}
e66f709b1   Chris Mason   Btrfs: write barr...
1116
1117
1118
  		if (wret < 0)
  			ret = wret;
  		if (wret == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
1119
  			struct btrfs_disk_key disk_key;
e66f709b1   Chris Mason   Btrfs: write barr...
1120
  			orig_slot += left_nr;
5f39d397d   Chris Mason   Btrfs: Create ext...
1121
1122
1123
1124
1125
  			btrfs_node_key(mid, &disk_key, 0);
  			btrfs_set_node_key(parent, &disk_key, pslot);
  			btrfs_mark_buffer_dirty(parent);
  			if (btrfs_header_nritems(left) > orig_slot) {
  				path->nodes[level] = left;
e66f709b1   Chris Mason   Btrfs: write barr...
1126
1127
  				path->slots[level + 1] -= 1;
  				path->slots[level] = orig_slot;
925baeddc   Chris Mason   Btrfs: Start btre...
1128
  				btrfs_tree_unlock(mid);
5f39d397d   Chris Mason   Btrfs: Create ext...
1129
  				free_extent_buffer(mid);
e66f709b1   Chris Mason   Btrfs: write barr...
1130
1131
  			} else {
  				orig_slot -=
5f39d397d   Chris Mason   Btrfs: Create ext...
1132
  					btrfs_header_nritems(left);
e66f709b1   Chris Mason   Btrfs: write barr...
1133
  				path->slots[level] = orig_slot;
925baeddc   Chris Mason   Btrfs: Start btre...
1134
  				btrfs_tree_unlock(left);
5f39d397d   Chris Mason   Btrfs: Create ext...
1135
  				free_extent_buffer(left);
e66f709b1   Chris Mason   Btrfs: write barr...
1136
  			}
e66f709b1   Chris Mason   Btrfs: write barr...
1137
1138
  			return 0;
  		}
925baeddc   Chris Mason   Btrfs: Start btre...
1139
  		btrfs_tree_unlock(left);
5f39d397d   Chris Mason   Btrfs: Create ext...
1140
  		free_extent_buffer(left);
e66f709b1   Chris Mason   Btrfs: write barr...
1141
  	}
925baeddc   Chris Mason   Btrfs: Start btre...
1142
  	right = read_node_slot(root, parent, pslot + 1);
e66f709b1   Chris Mason   Btrfs: write barr...
1143
1144
1145
1146
  
  	/*
  	 * then try to empty the right most buffer into the middle
  	 */
5f39d397d   Chris Mason   Btrfs: Create ext...
1147
  	if (right) {
33ade1f82   Chris Mason   Btrfs: node balan...
1148
  		u32 right_nr;
b4ce94de9   Chris Mason   Btrfs: Change btr...
1149

925baeddc   Chris Mason   Btrfs: Start btre...
1150
  		btrfs_tree_lock(right);
b4ce94de9   Chris Mason   Btrfs: Change btr...
1151
  		btrfs_set_lock_blocking(right);
5f39d397d   Chris Mason   Btrfs: Create ext...
1152
  		right_nr = btrfs_header_nritems(right);
33ade1f82   Chris Mason   Btrfs: node balan...
1153
1154
1155
  		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
  			wret = 1;
  		} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
1156
1157
  			ret = btrfs_cow_block(trans, root, right,
  					      parent, pslot + 1,
9fa8cfe70   Chris Mason   Btrfs: don't prea...
1158
  					      &right);
54aa1f4df   Chris Mason   Btrfs: Audit call...
1159
1160
1161
  			if (ret)
  				wret = 1;
  			else {
54aa1f4df   Chris Mason   Btrfs: Audit call...
1162
  				wret = balance_node_right(trans, root,
5f39d397d   Chris Mason   Btrfs: Create ext...
1163
  							  right, mid);
54aa1f4df   Chris Mason   Btrfs: Audit call...
1164
  			}
33ade1f82   Chris Mason   Btrfs: node balan...
1165
  		}
e66f709b1   Chris Mason   Btrfs: write barr...
1166
1167
1168
  		if (wret < 0)
  			ret = wret;
  		if (wret == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
1169
1170
1171
1172
1173
1174
1175
1176
  			struct btrfs_disk_key disk_key;
  
  			btrfs_node_key(right, &disk_key, 0);
  			btrfs_set_node_key(parent, &disk_key, pslot + 1);
  			btrfs_mark_buffer_dirty(parent);
  
  			if (btrfs_header_nritems(mid) <= orig_slot) {
  				path->nodes[level] = right;
e66f709b1   Chris Mason   Btrfs: write barr...
1177
1178
  				path->slots[level + 1] += 1;
  				path->slots[level] = orig_slot -
5f39d397d   Chris Mason   Btrfs: Create ext...
1179
  					btrfs_header_nritems(mid);
925baeddc   Chris Mason   Btrfs: Start btre...
1180
  				btrfs_tree_unlock(mid);
5f39d397d   Chris Mason   Btrfs: Create ext...
1181
  				free_extent_buffer(mid);
e66f709b1   Chris Mason   Btrfs: write barr...
1182
  			} else {
925baeddc   Chris Mason   Btrfs: Start btre...
1183
  				btrfs_tree_unlock(right);
5f39d397d   Chris Mason   Btrfs: Create ext...
1184
  				free_extent_buffer(right);
e66f709b1   Chris Mason   Btrfs: write barr...
1185
  			}
e66f709b1   Chris Mason   Btrfs: write barr...
1186
1187
  			return 0;
  		}
925baeddc   Chris Mason   Btrfs: Start btre...
1188
  		btrfs_tree_unlock(right);
5f39d397d   Chris Mason   Btrfs: Create ext...
1189
  		free_extent_buffer(right);
e66f709b1   Chris Mason   Btrfs: write barr...
1190
  	}
e66f709b1   Chris Mason   Btrfs: write barr...
1191
1192
  	return 1;
  }
74123bd72   Chris Mason   Btrfs: Commenting...
1193
  /*
d352ac681   Chris Mason   Btrfs: add and im...
1194
1195
   * readahead one full node of leaves, finding things that are close
   * to the block in 'slot', and triggering ra on them.
3c69faecb   Chris Mason   Btrfs: Fold some ...
1196
   */
c8c42864f   Chris Mason   Btrfs: break up b...
1197
1198
1199
  static void reada_for_search(struct btrfs_root *root,
  			     struct btrfs_path *path,
  			     int level, int slot, u64 objectid)
3c69faecb   Chris Mason   Btrfs: Fold some ...
1200
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
1201
  	struct extent_buffer *node;
01f466580   Chris Mason   Btrfs: Less aggre...
1202
  	struct btrfs_disk_key disk_key;
3c69faecb   Chris Mason   Btrfs: Fold some ...
1203
  	u32 nritems;
3c69faecb   Chris Mason   Btrfs: Fold some ...
1204
  	u64 search;
a71753194   Chris Mason   Btrfs: do less ag...
1205
  	u64 target;
6b80053d0   Chris Mason   Btrfs: Add back t...
1206
  	u64 nread = 0;
cb25c2ea6   Josef Bacik   Btrfs: map the no...
1207
  	u64 gen;
3c69faecb   Chris Mason   Btrfs: Fold some ...
1208
  	int direction = path->reada;
5f39d397d   Chris Mason   Btrfs: Create ext...
1209
  	struct extent_buffer *eb;
6b80053d0   Chris Mason   Btrfs: Add back t...
1210
1211
1212
  	u32 nr;
  	u32 blocksize;
  	u32 nscan = 0;
db94535db   Chris Mason   Btrfs: Allow tree...
1213

a6b6e75e0   Chris Mason   Btrfs: Defrag onl...
1214
  	if (level != 1)
6702ed490   Chris Mason   Btrfs: Add run ti...
1215
1216
1217
  		return;
  
  	if (!path->nodes[level])
3c69faecb   Chris Mason   Btrfs: Fold some ...
1218
  		return;
5f39d397d   Chris Mason   Btrfs: Create ext...
1219
  	node = path->nodes[level];
925baeddc   Chris Mason   Btrfs: Start btre...
1220

3c69faecb   Chris Mason   Btrfs: Fold some ...
1221
  	search = btrfs_node_blockptr(node, slot);
6b80053d0   Chris Mason   Btrfs: Add back t...
1222
1223
  	blocksize = btrfs_level_size(root, level - 1);
  	eb = btrfs_find_tree_block(root, search, blocksize);
5f39d397d   Chris Mason   Btrfs: Create ext...
1224
1225
  	if (eb) {
  		free_extent_buffer(eb);
3c69faecb   Chris Mason   Btrfs: Fold some ...
1226
1227
  		return;
  	}
a71753194   Chris Mason   Btrfs: do less ag...
1228
  	target = search;
6b80053d0   Chris Mason   Btrfs: Add back t...
1229

5f39d397d   Chris Mason   Btrfs: Create ext...
1230
  	nritems = btrfs_header_nritems(node);
6b80053d0   Chris Mason   Btrfs: Add back t...
1231
  	nr = slot;
25b8b936e   Josef Bacik   Btrfs: don't map ...
1232

d397712bc   Chris Mason   Btrfs: Fix checkp...
1233
  	while (1) {
6b80053d0   Chris Mason   Btrfs: Add back t...
1234
1235
1236
1237
1238
1239
1240
1241
  		if (direction < 0) {
  			if (nr == 0)
  				break;
  			nr--;
  		} else if (direction > 0) {
  			nr++;
  			if (nr >= nritems)
  				break;
3c69faecb   Chris Mason   Btrfs: Fold some ...
1242
  		}
01f466580   Chris Mason   Btrfs: Less aggre...
1243
1244
1245
1246
1247
  		if (path->reada < 0 && objectid) {
  			btrfs_node_key(node, &disk_key, nr);
  			if (btrfs_disk_key_objectid(&disk_key) != objectid)
  				break;
  		}
6b80053d0   Chris Mason   Btrfs: Add back t...
1248
  		search = btrfs_node_blockptr(node, nr);
a71753194   Chris Mason   Btrfs: do less ag...
1249
1250
  		if ((search <= target && target - search <= 65536) ||
  		    (search > target && search - target <= 65536)) {
cb25c2ea6   Josef Bacik   Btrfs: map the no...
1251
  			gen = btrfs_node_ptr_generation(node, nr);
cb25c2ea6   Josef Bacik   Btrfs: map the no...
1252
  			readahead_tree_block(root, search, blocksize, gen);
6b80053d0   Chris Mason   Btrfs: Add back t...
1253
1254
1255
  			nread += blocksize;
  		}
  		nscan++;
a71753194   Chris Mason   Btrfs: do less ag...
1256
  		if ((nread > 65536 || nscan > 32))
6b80053d0   Chris Mason   Btrfs: Add back t...
1257
  			break;
3c69faecb   Chris Mason   Btrfs: Fold some ...
1258
1259
  	}
  }
925baeddc   Chris Mason   Btrfs: Start btre...
1260

d352ac681   Chris Mason   Btrfs: add and im...
1261
  /*
b4ce94de9   Chris Mason   Btrfs: Change btr...
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
   * returns -EAGAIN if it had to drop the path, or zero if everything was in
   * cache
   */
  static noinline int reada_for_balance(struct btrfs_root *root,
  				      struct btrfs_path *path, int level)
  {
  	int slot;
  	int nritems;
  	struct extent_buffer *parent;
  	struct extent_buffer *eb;
  	u64 gen;
  	u64 block1 = 0;
  	u64 block2 = 0;
  	int ret = 0;
  	int blocksize;
8c594ea81   Chris Mason   Btrfs: use the ri...
1277
  	parent = path->nodes[level + 1];
b4ce94de9   Chris Mason   Btrfs: Change btr...
1278
1279
1280
1281
  	if (!parent)
  		return 0;
  
  	nritems = btrfs_header_nritems(parent);
8c594ea81   Chris Mason   Btrfs: use the ri...
1282
  	slot = path->slots[level + 1];
b4ce94de9   Chris Mason   Btrfs: Change btr...
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
  	blocksize = btrfs_level_size(root, level);
  
  	if (slot > 0) {
  		block1 = btrfs_node_blockptr(parent, slot - 1);
  		gen = btrfs_node_ptr_generation(parent, slot - 1);
  		eb = btrfs_find_tree_block(root, block1, blocksize);
  		if (eb && btrfs_buffer_uptodate(eb, gen))
  			block1 = 0;
  		free_extent_buffer(eb);
  	}
8c594ea81   Chris Mason   Btrfs: use the ri...
1293
  	if (slot + 1 < nritems) {
b4ce94de9   Chris Mason   Btrfs: Change btr...
1294
1295
1296
1297
1298
1299
1300
1301
1302
  		block2 = btrfs_node_blockptr(parent, slot + 1);
  		gen = btrfs_node_ptr_generation(parent, slot + 1);
  		eb = btrfs_find_tree_block(root, block2, blocksize);
  		if (eb && btrfs_buffer_uptodate(eb, gen))
  			block2 = 0;
  		free_extent_buffer(eb);
  	}
  	if (block1 || block2) {
  		ret = -EAGAIN;
8c594ea81   Chris Mason   Btrfs: use the ri...
1303
1304
  
  		/* release the whole path */
b3b4aa74b   David Sterba   btrfs: drop unuse...
1305
  		btrfs_release_path(path);
8c594ea81   Chris Mason   Btrfs: use the ri...
1306
1307
  
  		/* read the blocks */
b4ce94de9   Chris Mason   Btrfs: Change btr...
1308
1309
1310
1311
1312
1313
1314
1315
1316
  		if (block1)
  			readahead_tree_block(root, block1, blocksize, 0);
  		if (block2)
  			readahead_tree_block(root, block2, blocksize, 0);
  
  		if (block1) {
  			eb = read_tree_block(root, block1, blocksize, 0);
  			free_extent_buffer(eb);
  		}
8c594ea81   Chris Mason   Btrfs: use the ri...
1317
  		if (block2) {
b4ce94de9   Chris Mason   Btrfs: Change btr...
1318
1319
1320
1321
1322
1323
1324
1325
1326
  			eb = read_tree_block(root, block2, blocksize, 0);
  			free_extent_buffer(eb);
  		}
  	}
  	return ret;
  }
  
  
  /*
d397712bc   Chris Mason   Btrfs: Fix checkp...
1327
1328
1329
1330
   * when we walk down the tree, it is usually safe to unlock the higher layers
   * in the tree.  The exceptions are when our path goes through slot 0, because
   * operations on the tree might require changing key pointers higher up in the
   * tree.
d352ac681   Chris Mason   Btrfs: add and im...
1331
   *
d397712bc   Chris Mason   Btrfs: Fix checkp...
1332
1333
1334
   * callers might also have set path->keep_locks, which tells this code to keep
   * the lock if the path points to the last slot in the block.  This is part of
   * walking through the tree, and selecting the next slot in the higher block.
d352ac681   Chris Mason   Btrfs: add and im...
1335
   *
d397712bc   Chris Mason   Btrfs: Fix checkp...
1336
1337
   * lowest_unlock sets the lowest level in the tree we're allowed to unlock.  so
   * if lowest_unlock is 1, level 0 won't be unlocked
d352ac681   Chris Mason   Btrfs: add and im...
1338
   */
e02119d5a   Chris Mason   Btrfs: Add a writ...
1339
1340
  static noinline void unlock_up(struct btrfs_path *path, int level,
  			       int lowest_unlock)
925baeddc   Chris Mason   Btrfs: Start btre...
1341
1342
1343
  {
  	int i;
  	int skip_level = level;
051e1b9f7   Chris Mason   Drop locks in btr...
1344
  	int no_skips = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
1345
1346
1347
1348
1349
1350
1351
  	struct extent_buffer *t;
  
  	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
  		if (!path->nodes[i])
  			break;
  		if (!path->locks[i])
  			break;
051e1b9f7   Chris Mason   Drop locks in btr...
1352
  		if (!no_skips && path->slots[i] == 0) {
925baeddc   Chris Mason   Btrfs: Start btre...
1353
1354
1355
  			skip_level = i + 1;
  			continue;
  		}
051e1b9f7   Chris Mason   Drop locks in btr...
1356
  		if (!no_skips && path->keep_locks) {
925baeddc   Chris Mason   Btrfs: Start btre...
1357
1358
1359
  			u32 nritems;
  			t = path->nodes[i];
  			nritems = btrfs_header_nritems(t);
051e1b9f7   Chris Mason   Drop locks in btr...
1360
  			if (nritems < 1 || path->slots[i] >= nritems - 1) {
925baeddc   Chris Mason   Btrfs: Start btre...
1361
1362
1363
1364
  				skip_level = i + 1;
  				continue;
  			}
  		}
051e1b9f7   Chris Mason   Drop locks in btr...
1365
1366
  		if (skip_level < i && i >= lowest_unlock)
  			no_skips = 1;
925baeddc   Chris Mason   Btrfs: Start btre...
1367
1368
  		t = path->nodes[i];
  		if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
bd681513f   Chris Mason   Btrfs: switch the...
1369
  			btrfs_tree_unlock_rw(t, path->locks[i]);
925baeddc   Chris Mason   Btrfs: Start btre...
1370
1371
1372
1373
  			path->locks[i] = 0;
  		}
  	}
  }
3c69faecb   Chris Mason   Btrfs: Fold some ...
1374
  /*
b4ce94de9   Chris Mason   Btrfs: Change btr...
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
   * This releases any locks held in the path starting at level and
   * going all the way up to the root.
   *
   * btrfs_search_slot will keep the lock held on higher nodes in a few
   * corner cases, such as COW of the block at slot zero in the node.  This
   * ignores those rules, and it should only be called when there are no
   * more updates to be done higher up in the tree.
   */
  noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
  {
  	int i;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1386
  	if (path->keep_locks)
b4ce94de9   Chris Mason   Btrfs: Change btr...
1387
1388
1389
1390
  		return;
  
  	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
  		if (!path->nodes[i])
12f4daccf   Chris Mason   Btrfs: fix btrfs_...
1391
  			continue;
b4ce94de9   Chris Mason   Btrfs: Change btr...
1392
  		if (!path->locks[i])
12f4daccf   Chris Mason   Btrfs: fix btrfs_...
1393
  			continue;
bd681513f   Chris Mason   Btrfs: switch the...
1394
  		btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]);
b4ce94de9   Chris Mason   Btrfs: Change btr...
1395
1396
1397
1398
1399
  		path->locks[i] = 0;
  	}
  }
  
  /*
c8c42864f   Chris Mason   Btrfs: break up b...
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
   * helper function for btrfs_search_slot.  The goal is to find a block
   * in cache without setting the path to blocking.  If we find the block
   * we return zero and the path is unchanged.
   *
   * If we can't find the block, we set the path blocking and do some
   * reada.  -EAGAIN is returned and the search must be repeated.
   */
  static int
  read_block_for_search(struct btrfs_trans_handle *trans,
  		       struct btrfs_root *root, struct btrfs_path *p,
  		       struct extent_buffer **eb_ret, int level, int slot,
  		       struct btrfs_key *key)
  {
  	u64 blocknr;
  	u64 gen;
  	u32 blocksize;
  	struct extent_buffer *b = *eb_ret;
  	struct extent_buffer *tmp;
76a05b35a   Chris Mason   Btrfs: Don't loop...
1418
  	int ret;
c8c42864f   Chris Mason   Btrfs: break up b...
1419
1420
1421
1422
1423
1424
  
  	blocknr = btrfs_node_blockptr(b, slot);
  	gen = btrfs_node_ptr_generation(b, slot);
  	blocksize = btrfs_level_size(root, level - 1);
  
  	tmp = btrfs_find_tree_block(root, blocknr, blocksize);
cb44921a0   Chris Mason   Btrfs: don't loop...
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
  	if (tmp) {
  		if (btrfs_buffer_uptodate(tmp, 0)) {
  			if (btrfs_buffer_uptodate(tmp, gen)) {
  				/*
  				 * we found an up to date block without
  				 * sleeping, return
  				 * right away
  				 */
  				*eb_ret = tmp;
  				return 0;
  			}
  			/* the pages were up to date, but we failed
  			 * the generation number check.  Do a full
  			 * read for the generation number that is correct.
  			 * We must do this without dropping locks so
  			 * we can trust our generation number
  			 */
  			free_extent_buffer(tmp);
bd681513f   Chris Mason   Btrfs: switch the...
1443
  			btrfs_set_path_blocking(p);
cb44921a0   Chris Mason   Btrfs: don't loop...
1444
1445
1446
1447
1448
1449
  			tmp = read_tree_block(root, blocknr, blocksize, gen);
  			if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
  				*eb_ret = tmp;
  				return 0;
  			}
  			free_extent_buffer(tmp);
b3b4aa74b   David Sterba   btrfs: drop unuse...
1450
  			btrfs_release_path(p);
cb44921a0   Chris Mason   Btrfs: don't loop...
1451
1452
  			return -EIO;
  		}
c8c42864f   Chris Mason   Btrfs: break up b...
1453
1454
1455
1456
1457
  	}
  
  	/*
  	 * reduce lock contention at high levels
  	 * of the btree by dropping locks before
76a05b35a   Chris Mason   Btrfs: Don't loop...
1458
1459
1460
  	 * we read.  Don't release the lock on the current
  	 * level because we need to walk this node to figure
  	 * out which blocks to read.
c8c42864f   Chris Mason   Btrfs: break up b...
1461
  	 */
8c594ea81   Chris Mason   Btrfs: use the ri...
1462
1463
  	btrfs_unlock_up_safe(p, level + 1);
  	btrfs_set_path_blocking(p);
cb44921a0   Chris Mason   Btrfs: don't loop...
1464
  	free_extent_buffer(tmp);
c8c42864f   Chris Mason   Btrfs: break up b...
1465
1466
  	if (p->reada)
  		reada_for_search(root, p, level, slot, key->objectid);
b3b4aa74b   David Sterba   btrfs: drop unuse...
1467
  	btrfs_release_path(p);
76a05b35a   Chris Mason   Btrfs: Don't loop...
1468
1469
  
  	ret = -EAGAIN;
5bdd3536c   Yan, Zheng   Btrfs: Fix block ...
1470
  	tmp = read_tree_block(root, blocknr, blocksize, 0);
76a05b35a   Chris Mason   Btrfs: Don't loop...
1471
1472
1473
1474
1475
1476
1477
1478
1479
  	if (tmp) {
  		/*
  		 * If the read above didn't mark this buffer up to date,
  		 * it will never end up being up to date.  Set ret to EIO now
  		 * and give up so that our caller doesn't loop forever
  		 * on our EAGAINs.
  		 */
  		if (!btrfs_buffer_uptodate(tmp, 0))
  			ret = -EIO;
c8c42864f   Chris Mason   Btrfs: break up b...
1480
  		free_extent_buffer(tmp);
76a05b35a   Chris Mason   Btrfs: Don't loop...
1481
1482
  	}
  	return ret;
c8c42864f   Chris Mason   Btrfs: break up b...
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
  }
  
  /*
   * helper function for btrfs_search_slot.  This does all of the checks
   * for node-level blocks and does any balancing required based on
   * the ins_len.
   *
   * If no extra work was required, zero is returned.  If we had to
   * drop the path, -EAGAIN is returned and btrfs_search_slot must
   * start over
   */
  static int
  setup_nodes_for_search(struct btrfs_trans_handle *trans,
  		       struct btrfs_root *root, struct btrfs_path *p,
bd681513f   Chris Mason   Btrfs: switch the...
1497
1498
  		       struct extent_buffer *b, int level, int ins_len,
  		       int *write_lock_level)
c8c42864f   Chris Mason   Btrfs: break up b...
1499
1500
1501
1502
1503
  {
  	int ret;
  	if ((p->search_for_split || ins_len > 0) && btrfs_header_nritems(b) >=
  	    BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
  		int sret;
bd681513f   Chris Mason   Btrfs: switch the...
1504
1505
1506
1507
1508
  		if (*write_lock_level < level + 1) {
  			*write_lock_level = level + 1;
  			btrfs_release_path(p);
  			goto again;
  		}
c8c42864f   Chris Mason   Btrfs: break up b...
1509
1510
1511
1512
1513
1514
  		sret = reada_for_balance(root, p, level);
  		if (sret)
  			goto again;
  
  		btrfs_set_path_blocking(p);
  		sret = split_node(trans, root, p, level);
bd681513f   Chris Mason   Btrfs: switch the...
1515
  		btrfs_clear_path_blocking(p, NULL, 0);
c8c42864f   Chris Mason   Btrfs: break up b...
1516
1517
1518
1519
1520
1521
1522
1523
  
  		BUG_ON(sret > 0);
  		if (sret) {
  			ret = sret;
  			goto done;
  		}
  		b = p->nodes[level];
  	} else if (ins_len < 0 && btrfs_header_nritems(b) <
cfbb93084   Chris Mason   Btrfs: balance bt...
1524
  		   BTRFS_NODEPTRS_PER_BLOCK(root) / 2) {
c8c42864f   Chris Mason   Btrfs: break up b...
1525
  		int sret;
bd681513f   Chris Mason   Btrfs: switch the...
1526
1527
1528
1529
1530
  		if (*write_lock_level < level + 1) {
  			*write_lock_level = level + 1;
  			btrfs_release_path(p);
  			goto again;
  		}
c8c42864f   Chris Mason   Btrfs: break up b...
1531
1532
1533
1534
1535
1536
  		sret = reada_for_balance(root, p, level);
  		if (sret)
  			goto again;
  
  		btrfs_set_path_blocking(p);
  		sret = balance_level(trans, root, p, level);
bd681513f   Chris Mason   Btrfs: switch the...
1537
  		btrfs_clear_path_blocking(p, NULL, 0);
c8c42864f   Chris Mason   Btrfs: break up b...
1538
1539
1540
1541
1542
1543
1544
  
  		if (sret) {
  			ret = sret;
  			goto done;
  		}
  		b = p->nodes[level];
  		if (!b) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
1545
  			btrfs_release_path(p);
c8c42864f   Chris Mason   Btrfs: break up b...
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
  			goto again;
  		}
  		BUG_ON(btrfs_header_nritems(b) == 1);
  	}
  	return 0;
  
  again:
  	ret = -EAGAIN;
  done:
  	return ret;
  }
  
  /*
74123bd72   Chris Mason   Btrfs: Commenting...
1559
1560
1561
1562
1563
   * look for key in the tree.  path is filled in with nodes along the way
   * if key is found, we return zero and you can find the item in the leaf
   * level of the path (level 0)
   *
   * If the key isn't found, the path points to the slot where it should
aa5d6bed2   Chris Mason   Btrfs: return cod...
1564
1565
   * be inserted, and 1 is returned.  If there are other errors during the
   * search a negative error number is returned.
97571fd0c   Chris Mason   Btrfs: cleanup & ...
1566
1567
1568
1569
   *
   * if ins_len > 0, nodes and leaves will be split as we walk down the
   * tree.  if ins_len < 0, nodes will be merged as we walk down the tree (if
   * possible)
74123bd72   Chris Mason   Btrfs: Commenting...
1570
   */
e089f05c1   Chris Mason   Btrfs: transactio...
1571
1572
1573
  int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
  		      *root, struct btrfs_key *key, struct btrfs_path *p, int
  		      ins_len, int cow)
be0e5c097   Chris Mason   Btrfs: Initial ch...
1574
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
1575
  	struct extent_buffer *b;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1576
1577
  	int slot;
  	int ret;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1578
  	int err;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1579
  	int level;
925baeddc   Chris Mason   Btrfs: Start btre...
1580
  	int lowest_unlock = 1;
bd681513f   Chris Mason   Btrfs: switch the...
1581
1582
1583
  	int root_lock;
  	/* everything at write_lock_level or lower must be write locked */
  	int write_lock_level = 0;
9f3a74273   Chris Mason   Btrfs: Do snapsho...
1584
  	u8 lowest_level = 0;
6702ed490   Chris Mason   Btrfs: Add run ti...
1585
  	lowest_level = p->lowest_level;
323ac95bc   Chris Mason   Btrfs: don't read...
1586
  	WARN_ON(lowest_level && ins_len > 0);
22b0ebda6   Chris Mason   Btrfs: hunting sl...
1587
  	WARN_ON(p->nodes[0] != NULL);
251792013   Josef Bacik   Btrfs: nuke fs wi...
1588

bd681513f   Chris Mason   Btrfs: switch the...
1589
  	if (ins_len < 0) {
925baeddc   Chris Mason   Btrfs: Start btre...
1590
  		lowest_unlock = 2;
65b51a009   Chris Mason   btrfs_search_slot...
1591

bd681513f   Chris Mason   Btrfs: switch the...
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
  		/* when we are removing items, we might have to go up to level
  		 * two as we update tree pointers  Make sure we keep write
  		 * for those levels as well
  		 */
  		write_lock_level = 2;
  	} else if (ins_len > 0) {
  		/*
  		 * for inserting items, make sure we have a write lock on
  		 * level 1 so we can update keys
  		 */
  		write_lock_level = 1;
  	}
  
  	if (!cow)
  		write_lock_level = -1;
  
  	if (cow && (p->keep_locks || p->lowest_level))
  		write_lock_level = BTRFS_MAX_LEVEL;
bb8039515   Chris Mason   Btrfs: merge on t...
1610
  again:
bd681513f   Chris Mason   Btrfs: switch the...
1611
1612
1613
1614
1615
  	/*
  	 * we try very hard to do read locks on the root
  	 */
  	root_lock = BTRFS_READ_LOCK;
  	level = 0;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1616
  	if (p->search_commit_root) {
bd681513f   Chris Mason   Btrfs: switch the...
1617
1618
1619
1620
  		/*
  		 * the commit roots are read only
  		 * so we always do read locks
  		 */
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1621
1622
  		b = root->commit_root;
  		extent_buffer_get(b);
bd681513f   Chris Mason   Btrfs: switch the...
1623
  		level = btrfs_header_level(b);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1624
  		if (!p->skip_locking)
bd681513f   Chris Mason   Btrfs: switch the...
1625
  			btrfs_tree_read_lock(b);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1626
  	} else {
bd681513f   Chris Mason   Btrfs: switch the...
1627
  		if (p->skip_locking) {
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1628
  			b = btrfs_root_node(root);
bd681513f   Chris Mason   Btrfs: switch the...
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
  			level = btrfs_header_level(b);
  		} else {
  			/* we don't know the level of the root node
  			 * until we actually have it read locked
  			 */
  			b = btrfs_read_lock_root_node(root);
  			level = btrfs_header_level(b);
  			if (level <= write_lock_level) {
  				/* whoops, must trade for write lock */
  				btrfs_tree_read_unlock(b);
  				free_extent_buffer(b);
  				b = btrfs_lock_root_node(root);
  				root_lock = BTRFS_WRITE_LOCK;
  
  				/* the level might have changed, check again */
  				level = btrfs_header_level(b);
  			}
  		}
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1647
  	}
bd681513f   Chris Mason   Btrfs: switch the...
1648
1649
1650
  	p->nodes[level] = b;
  	if (!p->skip_locking)
  		p->locks[level] = root_lock;
925baeddc   Chris Mason   Btrfs: Start btre...
1651

eb60ceac0   Chris Mason   Btrfs: Add backin...
1652
  	while (b) {
5f39d397d   Chris Mason   Btrfs: Create ext...
1653
  		level = btrfs_header_level(b);
65b51a009   Chris Mason   btrfs_search_slot...
1654
1655
1656
1657
1658
  
  		/*
  		 * setup the path here so we can release it under lock
  		 * contention with the cow code
  		 */
02217ed29   Chris Mason   Btrfs: early refe...
1659
  		if (cow) {
c8c42864f   Chris Mason   Btrfs: break up b...
1660
1661
1662
1663
1664
  			/*
  			 * if we don't really need to cow this block
  			 * then we don't want to set the path blocking,
  			 * so we test it here
  			 */
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1665
  			if (!should_cow_block(trans, root, b))
65b51a009   Chris Mason   btrfs_search_slot...
1666
  				goto cow_done;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
1667

b4ce94de9   Chris Mason   Btrfs: Change btr...
1668
  			btrfs_set_path_blocking(p);
bd681513f   Chris Mason   Btrfs: switch the...
1669
1670
1671
1672
1673
1674
1675
1676
1677
  			/*
  			 * must have write locks on this node and the
  			 * parent
  			 */
  			if (level + 1 > write_lock_level) {
  				write_lock_level = level + 1;
  				btrfs_release_path(p);
  				goto again;
  			}
33c66f430   Yan Zheng   Btrfs: fix lockin...
1678
1679
1680
1681
  			err = btrfs_cow_block(trans, root, b,
  					      p->nodes[level + 1],
  					      p->slots[level + 1], &b);
  			if (err) {
33c66f430   Yan Zheng   Btrfs: fix lockin...
1682
  				ret = err;
65b51a009   Chris Mason   btrfs_search_slot...
1683
  				goto done;
54aa1f4df   Chris Mason   Btrfs: Audit call...
1684
  			}
02217ed29   Chris Mason   Btrfs: early refe...
1685
  		}
65b51a009   Chris Mason   btrfs_search_slot...
1686
  cow_done:
02217ed29   Chris Mason   Btrfs: early refe...
1687
  		BUG_ON(!cow && ins_len);
65b51a009   Chris Mason   btrfs_search_slot...
1688

eb60ceac0   Chris Mason   Btrfs: Add backin...
1689
  		p->nodes[level] = b;
bd681513f   Chris Mason   Btrfs: switch the...
1690
  		btrfs_clear_path_blocking(p, NULL, 0);
b4ce94de9   Chris Mason   Btrfs: Change btr...
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
  
  		/*
  		 * we have a lock on b and as long as we aren't changing
  		 * the tree, there is no way to for the items in b to change.
  		 * It is safe to drop the lock on our parent before we
  		 * go through the expensive btree search on b.
  		 *
  		 * If cow is true, then we might be changing slot zero,
  		 * which may require changing the parent.  So, we can't
  		 * drop the lock until after we know which slot we're
  		 * operating on.
  		 */
  		if (!cow)
  			btrfs_unlock_up_safe(p, level + 1);
5f39d397d   Chris Mason   Btrfs: Create ext...
1705
  		ret = bin_search(b, key, level, &slot);
b4ce94de9   Chris Mason   Btrfs: Change btr...
1706

5f39d397d   Chris Mason   Btrfs: Create ext...
1707
  		if (level != 0) {
33c66f430   Yan Zheng   Btrfs: fix lockin...
1708
1709
1710
  			int dec = 0;
  			if (ret && slot > 0) {
  				dec = 1;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1711
  				slot -= 1;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1712
  			}
be0e5c097   Chris Mason   Btrfs: Initial ch...
1713
  			p->slots[level] = slot;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1714
  			err = setup_nodes_for_search(trans, root, p, b, level,
bd681513f   Chris Mason   Btrfs: switch the...
1715
  					     ins_len, &write_lock_level);
33c66f430   Yan Zheng   Btrfs: fix lockin...
1716
  			if (err == -EAGAIN)
c8c42864f   Chris Mason   Btrfs: break up b...
1717
  				goto again;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1718
1719
  			if (err) {
  				ret = err;
c8c42864f   Chris Mason   Btrfs: break up b...
1720
  				goto done;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1721
  			}
c8c42864f   Chris Mason   Btrfs: break up b...
1722
1723
  			b = p->nodes[level];
  			slot = p->slots[level];
b4ce94de9   Chris Mason   Btrfs: Change btr...
1724

bd681513f   Chris Mason   Btrfs: switch the...
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
  			/*
  			 * slot 0 is special, if we change the key
  			 * we have to update the parent pointer
  			 * which means we must have a write lock
  			 * on the parent
  			 */
  			if (slot == 0 && cow &&
  			    write_lock_level < level + 1) {
  				write_lock_level = level + 1;
  				btrfs_release_path(p);
  				goto again;
  			}
f9efa9c78   Chris Mason   Btrfs: Reduce con...
1737
  			unlock_up(p, level, lowest_unlock);
925baeddc   Chris Mason   Btrfs: Start btre...
1738
  			if (level == lowest_level) {
33c66f430   Yan Zheng   Btrfs: fix lockin...
1739
1740
  				if (dec)
  					p->slots[level]++;
5b21f2ed3   Zheng Yan   Btrfs: extent_map...
1741
  				goto done;
925baeddc   Chris Mason   Btrfs: Start btre...
1742
  			}
ca7a79ad8   Chris Mason   Btrfs: Pass down ...
1743

33c66f430   Yan Zheng   Btrfs: fix lockin...
1744
  			err = read_block_for_search(trans, root, p,
c8c42864f   Chris Mason   Btrfs: break up b...
1745
  						    &b, level, slot, key);
33c66f430   Yan Zheng   Btrfs: fix lockin...
1746
  			if (err == -EAGAIN)
c8c42864f   Chris Mason   Btrfs: break up b...
1747
  				goto again;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1748
1749
  			if (err) {
  				ret = err;
76a05b35a   Chris Mason   Btrfs: Don't loop...
1750
  				goto done;
33c66f430   Yan Zheng   Btrfs: fix lockin...
1751
  			}
76a05b35a   Chris Mason   Btrfs: Don't loop...
1752

b4ce94de9   Chris Mason   Btrfs: Change btr...
1753
  			if (!p->skip_locking) {
bd681513f   Chris Mason   Btrfs: switch the...
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
  				level = btrfs_header_level(b);
  				if (level <= write_lock_level) {
  					err = btrfs_try_tree_write_lock(b);
  					if (!err) {
  						btrfs_set_path_blocking(p);
  						btrfs_tree_lock(b);
  						btrfs_clear_path_blocking(p, b,
  								  BTRFS_WRITE_LOCK);
  					}
  					p->locks[level] = BTRFS_WRITE_LOCK;
  				} else {
  					err = btrfs_try_tree_read_lock(b);
  					if (!err) {
  						btrfs_set_path_blocking(p);
  						btrfs_tree_read_lock(b);
  						btrfs_clear_path_blocking(p, b,
  								  BTRFS_READ_LOCK);
  					}
  					p->locks[level] = BTRFS_READ_LOCK;
b4ce94de9   Chris Mason   Btrfs: Change btr...
1773
  				}
bd681513f   Chris Mason   Btrfs: switch the...
1774
  				p->nodes[level] = b;
b4ce94de9   Chris Mason   Btrfs: Change btr...
1775
  			}
be0e5c097   Chris Mason   Btrfs: Initial ch...
1776
1777
  		} else {
  			p->slots[level] = slot;
87b29b208   Yan Zheng   Btrfs: properly c...
1778
1779
  			if (ins_len > 0 &&
  			    btrfs_leaf_free_space(root, b) < ins_len) {
bd681513f   Chris Mason   Btrfs: switch the...
1780
1781
1782
1783
1784
  				if (write_lock_level < 1) {
  					write_lock_level = 1;
  					btrfs_release_path(p);
  					goto again;
  				}
b4ce94de9   Chris Mason   Btrfs: Change btr...
1785
  				btrfs_set_path_blocking(p);
33c66f430   Yan Zheng   Btrfs: fix lockin...
1786
1787
  				err = split_leaf(trans, root, key,
  						 p, ins_len, ret == 0);
bd681513f   Chris Mason   Btrfs: switch the...
1788
  				btrfs_clear_path_blocking(p, NULL, 0);
b4ce94de9   Chris Mason   Btrfs: Change btr...
1789

33c66f430   Yan Zheng   Btrfs: fix lockin...
1790
1791
1792
  				BUG_ON(err > 0);
  				if (err) {
  					ret = err;
65b51a009   Chris Mason   btrfs_search_slot...
1793
1794
  					goto done;
  				}
5c680ed62   Chris Mason   Btrfs: switch to ...
1795
  			}
459931eca   Chris Mason   Btrfs: Delete csu...
1796
1797
  			if (!p->search_for_split)
  				unlock_up(p, level, lowest_unlock);
65b51a009   Chris Mason   btrfs_search_slot...
1798
  			goto done;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1799
1800
  		}
  	}
65b51a009   Chris Mason   btrfs_search_slot...
1801
1802
  	ret = 1;
  done:
b4ce94de9   Chris Mason   Btrfs: Change btr...
1803
1804
1805
1806
  	/*
  	 * we don't really know what they plan on doing with the path
  	 * from here on, so for now just mark it as blocking
  	 */
b9473439d   Chris Mason   Btrfs: leave btre...
1807
1808
  	if (!p->leave_spinning)
  		btrfs_set_path_blocking(p);
76a05b35a   Chris Mason   Btrfs: Don't loop...
1809
  	if (ret < 0)
b3b4aa74b   David Sterba   btrfs: drop unuse...
1810
  		btrfs_release_path(p);
65b51a009   Chris Mason   btrfs_search_slot...
1811
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1812
  }
74123bd72   Chris Mason   Btrfs: Commenting...
1813
1814
1815
1816
1817
1818
  /*
   * adjust the pointers going up the tree, starting at level
   * making sure the right key of each node is points to 'key'.
   * This is used after shifting pointers to the left, so it stops
   * fixing up pointers when a given leaf/node is not in slot 0 of the
   * higher levels
aa5d6bed2   Chris Mason   Btrfs: return cod...
1819
1820
1821
   *
   * If this fails to write a tree block, it returns -1, but continues
   * fixing up the blocks in ram so the tree is consistent.
74123bd72   Chris Mason   Btrfs: Commenting...
1822
   */
5f39d397d   Chris Mason   Btrfs: Create ext...
1823
1824
1825
  static int fixup_low_keys(struct btrfs_trans_handle *trans,
  			  struct btrfs_root *root, struct btrfs_path *path,
  			  struct btrfs_disk_key *key, int level)
be0e5c097   Chris Mason   Btrfs: Initial ch...
1826
1827
  {
  	int i;
aa5d6bed2   Chris Mason   Btrfs: return cod...
1828
  	int ret = 0;
5f39d397d   Chris Mason   Btrfs: Create ext...
1829
  	struct extent_buffer *t;
234b63a09   Chris Mason   rename funcs and ...
1830
  	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
be0e5c097   Chris Mason   Btrfs: Initial ch...
1831
  		int tslot = path->slots[i];
eb60ceac0   Chris Mason   Btrfs: Add backin...
1832
  		if (!path->nodes[i])
be0e5c097   Chris Mason   Btrfs: Initial ch...
1833
  			break;
5f39d397d   Chris Mason   Btrfs: Create ext...
1834
1835
  		t = path->nodes[i];
  		btrfs_set_node_key(t, key, tslot);
d60255795   Chris Mason   Btrfs: corruption...
1836
  		btrfs_mark_buffer_dirty(path->nodes[i]);
be0e5c097   Chris Mason   Btrfs: Initial ch...
1837
1838
1839
  		if (tslot != 0)
  			break;
  	}
aa5d6bed2   Chris Mason   Btrfs: return cod...
1840
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1841
  }
74123bd72   Chris Mason   Btrfs: Commenting...
1842
  /*
31840ae1a   Zheng Yan   Btrfs: Full back ...
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
   * update item key.
   *
   * This function isn't completely safe. It's the caller's responsibility
   * that the new key won't break the order
   */
  int btrfs_set_item_key_safe(struct btrfs_trans_handle *trans,
  			    struct btrfs_root *root, struct btrfs_path *path,
  			    struct btrfs_key *new_key)
  {
  	struct btrfs_disk_key disk_key;
  	struct extent_buffer *eb;
  	int slot;
  
  	eb = path->nodes[0];
  	slot = path->slots[0];
  	if (slot > 0) {
  		btrfs_item_key(eb, &disk_key, slot - 1);
  		if (comp_keys(&disk_key, new_key) >= 0)
  			return -1;
  	}
  	if (slot < btrfs_header_nritems(eb) - 1) {
  		btrfs_item_key(eb, &disk_key, slot + 1);
  		if (comp_keys(&disk_key, new_key) <= 0)
  			return -1;
  	}
  
  	btrfs_cpu_key_to_disk(&disk_key, new_key);
  	btrfs_set_item_key(eb, &disk_key, slot);
  	btrfs_mark_buffer_dirty(eb);
  	if (slot == 0)
  		fixup_low_keys(trans, root, path, &disk_key, 1);
  	return 0;
  }
  
  /*
74123bd72   Chris Mason   Btrfs: Commenting...
1878
   * try to push data from one node into the next node left in the
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1879
   * tree.
aa5d6bed2   Chris Mason   Btrfs: return cod...
1880
1881
1882
   *
   * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
   * error, and > 0 if there was no room in the left hand block.
74123bd72   Chris Mason   Btrfs: Commenting...
1883
   */
98ed51747   Chris Mason   Btrfs: Force inli...
1884
1885
  static int push_node_left(struct btrfs_trans_handle *trans,
  			  struct btrfs_root *root, struct extent_buffer *dst,
971a1f664   Chris Mason   Btrfs: Don't empt...
1886
  			  struct extent_buffer *src, int empty)
be0e5c097   Chris Mason   Btrfs: Initial ch...
1887
  {
be0e5c097   Chris Mason   Btrfs: Initial ch...
1888
  	int push_items = 0;
bb8039515   Chris Mason   Btrfs: merge on t...
1889
1890
  	int src_nritems;
  	int dst_nritems;
aa5d6bed2   Chris Mason   Btrfs: return cod...
1891
  	int ret = 0;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1892

5f39d397d   Chris Mason   Btrfs: Create ext...
1893
1894
  	src_nritems = btrfs_header_nritems(src);
  	dst_nritems = btrfs_header_nritems(dst);
123abc88c   Chris Mason   Btrfs: variable b...
1895
  	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
7bb86316c   Chris Mason   Btrfs: Add back p...
1896
1897
  	WARN_ON(btrfs_header_generation(src) != trans->transid);
  	WARN_ON(btrfs_header_generation(dst) != trans->transid);
54aa1f4df   Chris Mason   Btrfs: Audit call...
1898

bce4eae98   Chris Mason   Btrfs: Fix balanc...
1899
  	if (!empty && src_nritems <= 8)
971a1f664   Chris Mason   Btrfs: Don't empt...
1900
  		return 1;
d397712bc   Chris Mason   Btrfs: Fix checkp...
1901
  	if (push_items <= 0)
be0e5c097   Chris Mason   Btrfs: Initial ch...
1902
  		return 1;
bce4eae98   Chris Mason   Btrfs: Fix balanc...
1903
  	if (empty) {
971a1f664   Chris Mason   Btrfs: Don't empt...
1904
  		push_items = min(src_nritems, push_items);
bce4eae98   Chris Mason   Btrfs: Fix balanc...
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
  		if (push_items < src_nritems) {
  			/* leave at least 8 pointers in the node if
  			 * we aren't going to empty it
  			 */
  			if (src_nritems - push_items < 8) {
  				if (push_items <= 8)
  					return 1;
  				push_items -= 8;
  			}
  		}
  	} else
  		push_items = min(src_nritems - 8, push_items);
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1917

5f39d397d   Chris Mason   Btrfs: Create ext...
1918
1919
1920
  	copy_extent_buffer(dst, src,
  			   btrfs_node_key_ptr_offset(dst_nritems),
  			   btrfs_node_key_ptr_offset(0),
d397712bc   Chris Mason   Btrfs: Fix checkp...
1921
  			   push_items * sizeof(struct btrfs_key_ptr));
5f39d397d   Chris Mason   Btrfs: Create ext...
1922

bb8039515   Chris Mason   Btrfs: merge on t...
1923
  	if (push_items < src_nritems) {
5f39d397d   Chris Mason   Btrfs: Create ext...
1924
1925
1926
1927
1928
1929
1930
1931
1932
  		memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
  				      btrfs_node_key_ptr_offset(push_items),
  				      (src_nritems - push_items) *
  				      sizeof(struct btrfs_key_ptr));
  	}
  	btrfs_set_header_nritems(src, src_nritems - push_items);
  	btrfs_set_header_nritems(dst, dst_nritems + push_items);
  	btrfs_mark_buffer_dirty(src);
  	btrfs_mark_buffer_dirty(dst);
31840ae1a   Zheng Yan   Btrfs: Full back ...
1933

79f95c82d   Chris Mason   Btrfs: Fixup the ...
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
  	return ret;
  }
  
  /*
   * try to push data from one node into the next node right in the
   * tree.
   *
   * returns 0 if some ptrs were pushed, < 0 if there was some horrible
   * error, and > 0 if there was no room in the right hand block.
   *
   * this will  only push up to 1/2 the contents of the left node over
   */
5f39d397d   Chris Mason   Btrfs: Create ext...
1946
1947
1948
1949
  static int balance_node_right(struct btrfs_trans_handle *trans,
  			      struct btrfs_root *root,
  			      struct extent_buffer *dst,
  			      struct extent_buffer *src)
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1950
  {
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1951
1952
1953
1954
1955
  	int push_items = 0;
  	int max_push;
  	int src_nritems;
  	int dst_nritems;
  	int ret = 0;
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1956

7bb86316c   Chris Mason   Btrfs: Add back p...
1957
1958
  	WARN_ON(btrfs_header_generation(src) != trans->transid);
  	WARN_ON(btrfs_header_generation(dst) != trans->transid);
5f39d397d   Chris Mason   Btrfs: Create ext...
1959
1960
  	src_nritems = btrfs_header_nritems(src);
  	dst_nritems = btrfs_header_nritems(dst);
123abc88c   Chris Mason   Btrfs: variable b...
1961
  	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
d397712bc   Chris Mason   Btrfs: Fix checkp...
1962
  	if (push_items <= 0)
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1963
  		return 1;
bce4eae98   Chris Mason   Btrfs: Fix balanc...
1964

d397712bc   Chris Mason   Btrfs: Fix checkp...
1965
  	if (src_nritems < 4)
bce4eae98   Chris Mason   Btrfs: Fix balanc...
1966
  		return 1;
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1967
1968
1969
  
  	max_push = src_nritems / 2 + 1;
  	/* don't try to empty the node */
d397712bc   Chris Mason   Btrfs: Fix checkp...
1970
  	if (max_push >= src_nritems)
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1971
  		return 1;
252c38f06   Yan   Btrfs: ctree.c cl...
1972

79f95c82d   Chris Mason   Btrfs: Fixup the ...
1973
1974
  	if (max_push < push_items)
  		push_items = max_push;
5f39d397d   Chris Mason   Btrfs: Create ext...
1975
1976
1977
1978
  	memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items),
  				      btrfs_node_key_ptr_offset(0),
  				      (dst_nritems) *
  				      sizeof(struct btrfs_key_ptr));
d60255795   Chris Mason   Btrfs: corruption...
1979

5f39d397d   Chris Mason   Btrfs: Create ext...
1980
1981
1982
  	copy_extent_buffer(dst, src,
  			   btrfs_node_key_ptr_offset(0),
  			   btrfs_node_key_ptr_offset(src_nritems - push_items),
d397712bc   Chris Mason   Btrfs: Fix checkp...
1983
  			   push_items * sizeof(struct btrfs_key_ptr));
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1984

5f39d397d   Chris Mason   Btrfs: Create ext...
1985
1986
  	btrfs_set_header_nritems(src, src_nritems - push_items);
  	btrfs_set_header_nritems(dst, dst_nritems + push_items);
79f95c82d   Chris Mason   Btrfs: Fixup the ...
1987

5f39d397d   Chris Mason   Btrfs: Create ext...
1988
1989
  	btrfs_mark_buffer_dirty(src);
  	btrfs_mark_buffer_dirty(dst);
31840ae1a   Zheng Yan   Btrfs: Full back ...
1990

aa5d6bed2   Chris Mason   Btrfs: return cod...
1991
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
1992
  }
74123bd72   Chris Mason   Btrfs: Commenting...
1993
  /*
97571fd0c   Chris Mason   Btrfs: cleanup & ...
1994
1995
1996
   * helper function to insert a new root level in the tree.
   * A new node is allocated, and a single item is inserted to
   * point to the existing root
aa5d6bed2   Chris Mason   Btrfs: return cod...
1997
1998
   *
   * returns zero on success or < 0 on failure.
97571fd0c   Chris Mason   Btrfs: cleanup & ...
1999
   */
d397712bc   Chris Mason   Btrfs: Fix checkp...
2000
  static noinline int insert_new_root(struct btrfs_trans_handle *trans,
5f39d397d   Chris Mason   Btrfs: Create ext...
2001
2002
  			   struct btrfs_root *root,
  			   struct btrfs_path *path, int level)
5c680ed62   Chris Mason   Btrfs: switch to ...
2003
  {
7bb86316c   Chris Mason   Btrfs: Add back p...
2004
  	u64 lower_gen;
5f39d397d   Chris Mason   Btrfs: Create ext...
2005
2006
  	struct extent_buffer *lower;
  	struct extent_buffer *c;
925baeddc   Chris Mason   Btrfs: Start btre...
2007
  	struct extent_buffer *old;
5f39d397d   Chris Mason   Btrfs: Create ext...
2008
  	struct btrfs_disk_key lower_key;
5c680ed62   Chris Mason   Btrfs: switch to ...
2009
2010
2011
  
  	BUG_ON(path->nodes[level]);
  	BUG_ON(path->nodes[level-1] != root->node);
7bb86316c   Chris Mason   Btrfs: Add back p...
2012
2013
2014
2015
2016
  	lower = path->nodes[level-1];
  	if (level == 1)
  		btrfs_item_key(lower, &lower_key, 0);
  	else
  		btrfs_node_key(lower, &lower_key, 0);
31840ae1a   Zheng Yan   Btrfs: Full back ...
2017
  	c = btrfs_alloc_free_block(trans, root, root->nodesize, 0,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2018
  				   root->root_key.objectid, &lower_key,
ad3d81ba8   Christoph Hellwig   Btrfs: missing en...
2019
  				   level, root->node->start, 0);
5f39d397d   Chris Mason   Btrfs: Create ext...
2020
2021
  	if (IS_ERR(c))
  		return PTR_ERR(c);
925baeddc   Chris Mason   Btrfs: Start btre...
2022

f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2023
  	root_add_used(root, root->nodesize);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2024
  	memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header));
5f39d397d   Chris Mason   Btrfs: Create ext...
2025
2026
  	btrfs_set_header_nritems(c, 1);
  	btrfs_set_header_level(c, level);
db94535db   Chris Mason   Btrfs: Allow tree...
2027
  	btrfs_set_header_bytenr(c, c->start);
5f39d397d   Chris Mason   Btrfs: Create ext...
2028
  	btrfs_set_header_generation(c, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2029
  	btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV);
5f39d397d   Chris Mason   Btrfs: Create ext...
2030
  	btrfs_set_header_owner(c, root->root_key.objectid);
5f39d397d   Chris Mason   Btrfs: Create ext...
2031
2032
2033
2034
  
  	write_extent_buffer(c, root->fs_info->fsid,
  			    (unsigned long)btrfs_header_fsid(c),
  			    BTRFS_FSID_SIZE);
e17cade25   Chris Mason   Btrfs: Add chunk ...
2035
2036
2037
2038
  
  	write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
  			    (unsigned long)btrfs_header_chunk_tree_uuid(c),
  			    BTRFS_UUID_SIZE);
5f39d397d   Chris Mason   Btrfs: Create ext...
2039
  	btrfs_set_node_key(c, &lower_key, 0);
db94535db   Chris Mason   Btrfs: Allow tree...
2040
  	btrfs_set_node_blockptr(c, 0, lower->start);
7bb86316c   Chris Mason   Btrfs: Add back p...
2041
  	lower_gen = btrfs_header_generation(lower);
31840ae1a   Zheng Yan   Btrfs: Full back ...
2042
  	WARN_ON(lower_gen != trans->transid);
7bb86316c   Chris Mason   Btrfs: Add back p...
2043
2044
  
  	btrfs_set_node_ptr_generation(c, 0, lower_gen);
d57197629   Chris Mason   btrfs_create, btr...
2045

5f39d397d   Chris Mason   Btrfs: Create ext...
2046
  	btrfs_mark_buffer_dirty(c);
d57197629   Chris Mason   btrfs_create, btr...
2047

925baeddc   Chris Mason   Btrfs: Start btre...
2048
  	old = root->node;
240f62c87   Chris Mason   Btrfs: use RCU in...
2049
  	rcu_assign_pointer(root->node, c);
925baeddc   Chris Mason   Btrfs: Start btre...
2050
2051
2052
  
  	/* the super has an extra ref to root->node */
  	free_extent_buffer(old);
0b86a832a   Chris Mason   Btrfs: Add suppor...
2053
  	add_root_to_dirty_list(root);
5f39d397d   Chris Mason   Btrfs: Create ext...
2054
2055
  	extent_buffer_get(c);
  	path->nodes[level] = c;
bd681513f   Chris Mason   Btrfs: switch the...
2056
  	path->locks[level] = BTRFS_WRITE_LOCK;
5c680ed62   Chris Mason   Btrfs: switch to ...
2057
2058
2059
  	path->slots[level] = 0;
  	return 0;
  }
74123bd72   Chris Mason   Btrfs: Commenting...
2060
2061
2062
  /*
   * worker function to insert a single pointer in a node.
   * the node should have enough room for the pointer already
97571fd0c   Chris Mason   Btrfs: cleanup & ...
2063
   *
74123bd72   Chris Mason   Btrfs: Commenting...
2064
2065
   * slot and level indicate where you want the key to go, and
   * blocknr is the block the key points to.
aa5d6bed2   Chris Mason   Btrfs: return cod...
2066
2067
   *
   * returns zero on success and < 0 on any error
74123bd72   Chris Mason   Btrfs: Commenting...
2068
   */
e089f05c1   Chris Mason   Btrfs: transactio...
2069
2070
  static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
  		      *root, struct btrfs_path *path, struct btrfs_disk_key
db94535db   Chris Mason   Btrfs: Allow tree...
2071
  		      *key, u64 bytenr, int slot, int level)
74123bd72   Chris Mason   Btrfs: Commenting...
2072
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
2073
  	struct extent_buffer *lower;
74123bd72   Chris Mason   Btrfs: Commenting...
2074
  	int nritems;
5c680ed62   Chris Mason   Btrfs: switch to ...
2075
2076
  
  	BUG_ON(!path->nodes[level]);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2077
  	btrfs_assert_tree_locked(path->nodes[level]);
5f39d397d   Chris Mason   Btrfs: Create ext...
2078
2079
  	lower = path->nodes[level];
  	nritems = btrfs_header_nritems(lower);
c293498be   Stoyan Gaydarov   Btrfs: BUG to BUG...
2080
  	BUG_ON(slot > nritems);
123abc88c   Chris Mason   Btrfs: variable b...
2081
  	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
74123bd72   Chris Mason   Btrfs: Commenting...
2082
2083
  		BUG();
  	if (slot != nritems) {
5f39d397d   Chris Mason   Btrfs: Create ext...
2084
2085
2086
  		memmove_extent_buffer(lower,
  			      btrfs_node_key_ptr_offset(slot + 1),
  			      btrfs_node_key_ptr_offset(slot),
d60255795   Chris Mason   Btrfs: corruption...
2087
  			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
74123bd72   Chris Mason   Btrfs: Commenting...
2088
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
2089
  	btrfs_set_node_key(lower, key, slot);
db94535db   Chris Mason   Btrfs: Allow tree...
2090
  	btrfs_set_node_blockptr(lower, slot, bytenr);
74493f7a5   Chris Mason   Btrfs: Implement ...
2091
2092
  	WARN_ON(trans->transid == 0);
  	btrfs_set_node_ptr_generation(lower, slot, trans->transid);
5f39d397d   Chris Mason   Btrfs: Create ext...
2093
2094
  	btrfs_set_header_nritems(lower, nritems + 1);
  	btrfs_mark_buffer_dirty(lower);
74123bd72   Chris Mason   Btrfs: Commenting...
2095
2096
  	return 0;
  }
97571fd0c   Chris Mason   Btrfs: cleanup & ...
2097
2098
2099
2100
2101
2102
  /*
   * split the node at the specified level in path in two.
   * The path is corrected to point to the appropriate node after the split
   *
   * Before splitting this tries to make some room in the node by pushing
   * left and right, if either one works, it returns right away.
aa5d6bed2   Chris Mason   Btrfs: return cod...
2103
2104
   *
   * returns 0 on success and < 0 on failure
97571fd0c   Chris Mason   Btrfs: cleanup & ...
2105
   */
e02119d5a   Chris Mason   Btrfs: Add a writ...
2106
2107
2108
  static noinline int split_node(struct btrfs_trans_handle *trans,
  			       struct btrfs_root *root,
  			       struct btrfs_path *path, int level)
be0e5c097   Chris Mason   Btrfs: Initial ch...
2109
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
2110
2111
2112
  	struct extent_buffer *c;
  	struct extent_buffer *split;
  	struct btrfs_disk_key disk_key;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2113
  	int mid;
5c680ed62   Chris Mason   Btrfs: switch to ...
2114
  	int ret;
aa5d6bed2   Chris Mason   Btrfs: return cod...
2115
  	int wret;
7518a238e   Chris Mason   Btrfs: get/set fo...
2116
  	u32 c_nritems;
eb60ceac0   Chris Mason   Btrfs: Add backin...
2117

5f39d397d   Chris Mason   Btrfs: Create ext...
2118
  	c = path->nodes[level];
7bb86316c   Chris Mason   Btrfs: Add back p...
2119
  	WARN_ON(btrfs_header_generation(c) != trans->transid);
5f39d397d   Chris Mason   Btrfs: Create ext...
2120
  	if (c == root->node) {
5c680ed62   Chris Mason   Btrfs: switch to ...
2121
  		/* trying to split the root, lets make a new one */
e089f05c1   Chris Mason   Btrfs: transactio...
2122
  		ret = insert_new_root(trans, root, path, level + 1);
5c680ed62   Chris Mason   Btrfs: switch to ...
2123
2124
  		if (ret)
  			return ret;
b36124210   Chris Mason   Btrfs: stop avoid...
2125
  	} else {
e66f709b1   Chris Mason   Btrfs: write barr...
2126
  		ret = push_nodes_for_insert(trans, root, path, level);
5f39d397d   Chris Mason   Btrfs: Create ext...
2127
2128
  		c = path->nodes[level];
  		if (!ret && btrfs_header_nritems(c) <
c448acf0a   Chris Mason   Btrfs: Fix split_...
2129
  		    BTRFS_NODEPTRS_PER_BLOCK(root) - 3)
e66f709b1   Chris Mason   Btrfs: write barr...
2130
  			return 0;
54aa1f4df   Chris Mason   Btrfs: Audit call...
2131
2132
  		if (ret < 0)
  			return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2133
  	}
e66f709b1   Chris Mason   Btrfs: write barr...
2134

5f39d397d   Chris Mason   Btrfs: Create ext...
2135
  	c_nritems = btrfs_header_nritems(c);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2136
2137
  	mid = (c_nritems + 1) / 2;
  	btrfs_node_key(c, &disk_key, mid);
7bb86316c   Chris Mason   Btrfs: Add back p...
2138

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2139
  	split = btrfs_alloc_free_block(trans, root, root->nodesize, 0,
31840ae1a   Zheng Yan   Btrfs: Full back ...
2140
  					root->root_key.objectid,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2141
  					&disk_key, level, c->start, 0);
5f39d397d   Chris Mason   Btrfs: Create ext...
2142
2143
  	if (IS_ERR(split))
  		return PTR_ERR(split);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2144
  	root_add_used(root, root->nodesize);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2145
  	memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header));
5f39d397d   Chris Mason   Btrfs: Create ext...
2146
  	btrfs_set_header_level(split, btrfs_header_level(c));
db94535db   Chris Mason   Btrfs: Allow tree...
2147
  	btrfs_set_header_bytenr(split, split->start);
5f39d397d   Chris Mason   Btrfs: Create ext...
2148
  	btrfs_set_header_generation(split, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2149
  	btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV);
5f39d397d   Chris Mason   Btrfs: Create ext...
2150
2151
2152
2153
  	btrfs_set_header_owner(split, root->root_key.objectid);
  	write_extent_buffer(split, root->fs_info->fsid,
  			    (unsigned long)btrfs_header_fsid(split),
  			    BTRFS_FSID_SIZE);
e17cade25   Chris Mason   Btrfs: Add chunk ...
2154
2155
2156
  	write_extent_buffer(split, root->fs_info->chunk_tree_uuid,
  			    (unsigned long)btrfs_header_chunk_tree_uuid(split),
  			    BTRFS_UUID_SIZE);
54aa1f4df   Chris Mason   Btrfs: Audit call...
2157

5f39d397d   Chris Mason   Btrfs: Create ext...
2158
2159
2160
2161
2162
2163
2164
  
  	copy_extent_buffer(split, c,
  			   btrfs_node_key_ptr_offset(0),
  			   btrfs_node_key_ptr_offset(mid),
  			   (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
  	btrfs_set_header_nritems(split, c_nritems - mid);
  	btrfs_set_header_nritems(c, mid);
aa5d6bed2   Chris Mason   Btrfs: return cod...
2165
  	ret = 0;
5f39d397d   Chris Mason   Btrfs: Create ext...
2166
2167
  	btrfs_mark_buffer_dirty(c);
  	btrfs_mark_buffer_dirty(split);
db94535db   Chris Mason   Btrfs: Allow tree...
2168
  	wret = insert_ptr(trans, root, path, &disk_key, split->start,
5f39d397d   Chris Mason   Btrfs: Create ext...
2169
  			  path->slots[level + 1] + 1,
123abc88c   Chris Mason   Btrfs: variable b...
2170
  			  level + 1);
aa5d6bed2   Chris Mason   Btrfs: return cod...
2171
2172
  	if (wret)
  		ret = wret;
5de08d7d5   Chris Mason   Btrfs: Break up c...
2173
  	if (path->slots[level] >= mid) {
5c680ed62   Chris Mason   Btrfs: switch to ...
2174
  		path->slots[level] -= mid;
925baeddc   Chris Mason   Btrfs: Start btre...
2175
  		btrfs_tree_unlock(c);
5f39d397d   Chris Mason   Btrfs: Create ext...
2176
2177
  		free_extent_buffer(c);
  		path->nodes[level] = split;
5c680ed62   Chris Mason   Btrfs: switch to ...
2178
2179
  		path->slots[level + 1] += 1;
  	} else {
925baeddc   Chris Mason   Btrfs: Start btre...
2180
  		btrfs_tree_unlock(split);
5f39d397d   Chris Mason   Btrfs: Create ext...
2181
  		free_extent_buffer(split);
be0e5c097   Chris Mason   Btrfs: Initial ch...
2182
  	}
aa5d6bed2   Chris Mason   Btrfs: return cod...
2183
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2184
  }
74123bd72   Chris Mason   Btrfs: Commenting...
2185
2186
2187
2188
2189
  /*
   * how many bytes are required to store the items in a leaf.  start
   * and nr indicate which items in the leaf to check.  This totals up the
   * space used both by the item structs and the item data
   */
5f39d397d   Chris Mason   Btrfs: Create ext...
2190
  static int leaf_space_used(struct extent_buffer *l, int start, int nr)
be0e5c097   Chris Mason   Btrfs: Initial ch...
2191
2192
  {
  	int data_len;
5f39d397d   Chris Mason   Btrfs: Create ext...
2193
  	int nritems = btrfs_header_nritems(l);
d4dbff953   Chris Mason   Btrfs: support fo...
2194
  	int end = min(nritems, start + nr) - 1;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2195
2196
2197
  
  	if (!nr)
  		return 0;
5f39d397d   Chris Mason   Btrfs: Create ext...
2198
2199
  	data_len = btrfs_item_end_nr(l, start);
  	data_len = data_len - btrfs_item_offset_nr(l, end);
0783fcfc4   Chris Mason   Btrfs: struct ite...
2200
  	data_len += sizeof(struct btrfs_item) * nr;
d4dbff953   Chris Mason   Btrfs: support fo...
2201
  	WARN_ON(data_len < 0);
be0e5c097   Chris Mason   Btrfs: Initial ch...
2202
2203
  	return data_len;
  }
74123bd72   Chris Mason   Btrfs: Commenting...
2204
  /*
d4dbff953   Chris Mason   Btrfs: support fo...
2205
2206
2207
2208
   * The space between the end of the leaf items and
   * the start of the leaf data.  IOW, how much room
   * the leaf has left for both items and data
   */
d397712bc   Chris Mason   Btrfs: Fix checkp...
2209
  noinline int btrfs_leaf_free_space(struct btrfs_root *root,
e02119d5a   Chris Mason   Btrfs: Add a writ...
2210
  				   struct extent_buffer *leaf)
d4dbff953   Chris Mason   Btrfs: support fo...
2211
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
2212
2213
2214
2215
  	int nritems = btrfs_header_nritems(leaf);
  	int ret;
  	ret = BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
  	if (ret < 0) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
2216
2217
2218
  		printk(KERN_CRIT "leaf free space ret %d, leaf data size %lu, "
  		       "used %d nritems %d
  ",
ae2f5411c   Jens Axboe   btrfs: 32-bit typ...
2219
  		       ret, (unsigned long) BTRFS_LEAF_DATA_SIZE(root),
5f39d397d   Chris Mason   Btrfs: Create ext...
2220
2221
2222
  		       leaf_space_used(leaf, 0, nritems), nritems);
  	}
  	return ret;
d4dbff953   Chris Mason   Btrfs: support fo...
2223
  }
99d8f83c9   Chris Mason   Btrfs: fix split_...
2224
2225
2226
2227
  /*
   * min slot controls the lowest index we're willing to push to the
   * right.  We'll push up to and including min_slot, but no lower
   */
44871b1b2   Chris Mason   Btrfs: reduce sta...
2228
2229
2230
2231
2232
  static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
  				      struct btrfs_root *root,
  				      struct btrfs_path *path,
  				      int data_size, int empty,
  				      struct extent_buffer *right,
99d8f83c9   Chris Mason   Btrfs: fix split_...
2233
2234
  				      int free_space, u32 left_nritems,
  				      u32 min_slot)
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2235
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
2236
  	struct extent_buffer *left = path->nodes[0];
44871b1b2   Chris Mason   Btrfs: reduce sta...
2237
  	struct extent_buffer *upper = path->nodes[1];
5f39d397d   Chris Mason   Btrfs: Create ext...
2238
  	struct btrfs_disk_key disk_key;
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2239
  	int slot;
34a382187   Chris Mason   Btrfs: Change pus...
2240
  	u32 i;
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2241
2242
  	int push_space = 0;
  	int push_items = 0;
0783fcfc4   Chris Mason   Btrfs: struct ite...
2243
  	struct btrfs_item *item;
34a382187   Chris Mason   Btrfs: Change pus...
2244
  	u32 nr;
7518a238e   Chris Mason   Btrfs: get/set fo...
2245
  	u32 right_nritems;
5f39d397d   Chris Mason   Btrfs: Create ext...
2246
  	u32 data_end;
db94535db   Chris Mason   Btrfs: Allow tree...
2247
  	u32 this_item_size;
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2248

34a382187   Chris Mason   Btrfs: Change pus...
2249
2250
2251
  	if (empty)
  		nr = 0;
  	else
99d8f83c9   Chris Mason   Btrfs: fix split_...
2252
  		nr = max_t(u32, 1, min_slot);
34a382187   Chris Mason   Btrfs: Change pus...
2253

31840ae1a   Zheng Yan   Btrfs: Full back ...
2254
  	if (path->slots[0] >= left_nritems)
87b29b208   Yan Zheng   Btrfs: properly c...
2255
  		push_space += data_size;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2256

44871b1b2   Chris Mason   Btrfs: reduce sta...
2257
  	slot = path->slots[1];
34a382187   Chris Mason   Btrfs: Change pus...
2258
2259
  	i = left_nritems - 1;
  	while (i >= nr) {
5f39d397d   Chris Mason   Btrfs: Create ext...
2260
  		item = btrfs_item_nr(left, i);
db94535db   Chris Mason   Btrfs: Allow tree...
2261

31840ae1a   Zheng Yan   Btrfs: Full back ...
2262
2263
2264
2265
2266
2267
2268
2269
2270
  		if (!empty && push_items > 0) {
  			if (path->slots[0] > i)
  				break;
  			if (path->slots[0] == i) {
  				int space = btrfs_leaf_free_space(root, left);
  				if (space + push_space * 2 > free_space)
  					break;
  			}
  		}
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2271
  		if (path->slots[0] == i)
87b29b208   Yan Zheng   Btrfs: properly c...
2272
  			push_space += data_size;
db94535db   Chris Mason   Btrfs: Allow tree...
2273

db94535db   Chris Mason   Btrfs: Allow tree...
2274
2275
  		this_item_size = btrfs_item_size(left, item);
  		if (this_item_size + sizeof(*item) + push_space > free_space)
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2276
  			break;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2277

00ec4c516   Chris Mason   Btrfs: push_leaf_...
2278
  		push_items++;
db94535db   Chris Mason   Btrfs: Allow tree...
2279
  		push_space += this_item_size + sizeof(*item);
34a382187   Chris Mason   Btrfs: Change pus...
2280
2281
2282
  		if (i == 0)
  			break;
  		i--;
db94535db   Chris Mason   Btrfs: Allow tree...
2283
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
2284

925baeddc   Chris Mason   Btrfs: Start btre...
2285
2286
  	if (push_items == 0)
  		goto out_unlock;
5f39d397d   Chris Mason   Btrfs: Create ext...
2287

34a382187   Chris Mason   Btrfs: Change pus...
2288
  	if (!empty && push_items == left_nritems)
a429e5137   Chris Mason   Btrfs: working fi...
2289
  		WARN_ON(1);
5f39d397d   Chris Mason   Btrfs: Create ext...
2290

00ec4c516   Chris Mason   Btrfs: push_leaf_...
2291
  	/* push left to right */
5f39d397d   Chris Mason   Btrfs: Create ext...
2292
  	right_nritems = btrfs_header_nritems(right);
34a382187   Chris Mason   Btrfs: Change pus...
2293

5f39d397d   Chris Mason   Btrfs: Create ext...
2294
  	push_space = btrfs_item_end_nr(left, left_nritems - push_items);
123abc88c   Chris Mason   Btrfs: variable b...
2295
  	push_space -= leaf_data_end(root, left);
5f39d397d   Chris Mason   Btrfs: Create ext...
2296

00ec4c516   Chris Mason   Btrfs: push_leaf_...
2297
  	/* make room in the right data area */
5f39d397d   Chris Mason   Btrfs: Create ext...
2298
2299
2300
2301
2302
  	data_end = leaf_data_end(root, right);
  	memmove_extent_buffer(right,
  			      btrfs_leaf_data(right) + data_end - push_space,
  			      btrfs_leaf_data(right) + data_end,
  			      BTRFS_LEAF_DATA_SIZE(root) - data_end);
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2303
  	/* copy from the left data area */
5f39d397d   Chris Mason   Btrfs: Create ext...
2304
  	copy_extent_buffer(right, left, btrfs_leaf_data(right) +
d60255795   Chris Mason   Btrfs: corruption...
2305
2306
2307
  		     BTRFS_LEAF_DATA_SIZE(root) - push_space,
  		     btrfs_leaf_data(left) + leaf_data_end(root, left),
  		     push_space);
5f39d397d   Chris Mason   Btrfs: Create ext...
2308
2309
2310
2311
  
  	memmove_extent_buffer(right, btrfs_item_nr_offset(push_items),
  			      btrfs_item_nr_offset(0),
  			      right_nritems * sizeof(struct btrfs_item));
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2312
  	/* copy the items from left to right */
5f39d397d   Chris Mason   Btrfs: Create ext...
2313
2314
2315
  	copy_extent_buffer(right, left, btrfs_item_nr_offset(0),
  		   btrfs_item_nr_offset(left_nritems - push_items),
  		   push_items * sizeof(struct btrfs_item));
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2316
2317
  
  	/* update the item pointers */
7518a238e   Chris Mason   Btrfs: get/set fo...
2318
  	right_nritems += push_items;
5f39d397d   Chris Mason   Btrfs: Create ext...
2319
  	btrfs_set_header_nritems(right, right_nritems);
123abc88c   Chris Mason   Btrfs: variable b...
2320
  	push_space = BTRFS_LEAF_DATA_SIZE(root);
7518a238e   Chris Mason   Btrfs: get/set fo...
2321
  	for (i = 0; i < right_nritems; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
2322
  		item = btrfs_item_nr(right, i);
db94535db   Chris Mason   Btrfs: Allow tree...
2323
2324
2325
  		push_space -= btrfs_item_size(right, item);
  		btrfs_set_item_offset(right, item, push_space);
  	}
7518a238e   Chris Mason   Btrfs: get/set fo...
2326
  	left_nritems -= push_items;
5f39d397d   Chris Mason   Btrfs: Create ext...
2327
  	btrfs_set_header_nritems(left, left_nritems);
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2328

34a382187   Chris Mason   Btrfs: Change pus...
2329
2330
  	if (left_nritems)
  		btrfs_mark_buffer_dirty(left);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2331
2332
  	else
  		clean_tree_block(trans, root, left);
5f39d397d   Chris Mason   Btrfs: Create ext...
2333
  	btrfs_mark_buffer_dirty(right);
a429e5137   Chris Mason   Btrfs: working fi...
2334

5f39d397d   Chris Mason   Btrfs: Create ext...
2335
2336
  	btrfs_item_key(right, &disk_key, 0);
  	btrfs_set_node_key(upper, &disk_key, slot + 1);
d60255795   Chris Mason   Btrfs: corruption...
2337
  	btrfs_mark_buffer_dirty(upper);
02217ed29   Chris Mason   Btrfs: early refe...
2338

00ec4c516   Chris Mason   Btrfs: push_leaf_...
2339
  	/* then fixup the leaf pointer in the path */
7518a238e   Chris Mason   Btrfs: get/set fo...
2340
2341
  	if (path->slots[0] >= left_nritems) {
  		path->slots[0] -= left_nritems;
925baeddc   Chris Mason   Btrfs: Start btre...
2342
2343
2344
  		if (btrfs_header_nritems(path->nodes[0]) == 0)
  			clean_tree_block(trans, root, path->nodes[0]);
  		btrfs_tree_unlock(path->nodes[0]);
5f39d397d   Chris Mason   Btrfs: Create ext...
2345
2346
  		free_extent_buffer(path->nodes[0]);
  		path->nodes[0] = right;
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2347
2348
  		path->slots[1] += 1;
  	} else {
925baeddc   Chris Mason   Btrfs: Start btre...
2349
  		btrfs_tree_unlock(right);
5f39d397d   Chris Mason   Btrfs: Create ext...
2350
  		free_extent_buffer(right);
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2351
2352
  	}
  	return 0;
925baeddc   Chris Mason   Btrfs: Start btre...
2353
2354
2355
2356
2357
  
  out_unlock:
  	btrfs_tree_unlock(right);
  	free_extent_buffer(right);
  	return 1;
00ec4c516   Chris Mason   Btrfs: push_leaf_...
2358
  }
925baeddc   Chris Mason   Btrfs: Start btre...
2359

00ec4c516   Chris Mason   Btrfs: push_leaf_...
2360
  /*
44871b1b2   Chris Mason   Btrfs: reduce sta...
2361
2362
2363
2364
2365
   * push some data in the path leaf to the right, trying to free up at
   * least data_size bytes.  returns zero if the push worked, nonzero otherwise
   *
   * returns 1 if the push failed because the other node didn't have enough
   * room, 0 if everything worked out and < 0 if there were major errors.
99d8f83c9   Chris Mason   Btrfs: fix split_...
2366
2367
2368
   *
   * this will push starting from min_slot to the end of the leaf.  It won't
   * push any slot lower than min_slot
44871b1b2   Chris Mason   Btrfs: reduce sta...
2369
2370
   */
  static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
99d8f83c9   Chris Mason   Btrfs: fix split_...
2371
2372
2373
  			   *root, struct btrfs_path *path,
  			   int min_data_size, int data_size,
  			   int empty, u32 min_slot)
44871b1b2   Chris Mason   Btrfs: reduce sta...
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
  {
  	struct extent_buffer *left = path->nodes[0];
  	struct extent_buffer *right;
  	struct extent_buffer *upper;
  	int slot;
  	int free_space;
  	u32 left_nritems;
  	int ret;
  
  	if (!path->nodes[1])
  		return 1;
  
  	slot = path->slots[1];
  	upper = path->nodes[1];
  	if (slot >= btrfs_header_nritems(upper) - 1)
  		return 1;
  
  	btrfs_assert_tree_locked(path->nodes[1]);
  
  	right = read_node_slot(root, upper, slot + 1);
91ca338d7   Tsutomu Itoh   btrfs: check NULL...
2394
2395
  	if (right == NULL)
  		return 1;
44871b1b2   Chris Mason   Btrfs: reduce sta...
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
  	btrfs_tree_lock(right);
  	btrfs_set_lock_blocking(right);
  
  	free_space = btrfs_leaf_free_space(root, right);
  	if (free_space < data_size)
  		goto out_unlock;
  
  	/* cow and double check */
  	ret = btrfs_cow_block(trans, root, right, upper,
  			      slot + 1, &right);
  	if (ret)
  		goto out_unlock;
  
  	free_space = btrfs_leaf_free_space(root, right);
  	if (free_space < data_size)
  		goto out_unlock;
  
  	left_nritems = btrfs_header_nritems(left);
  	if (left_nritems == 0)
  		goto out_unlock;
99d8f83c9   Chris Mason   Btrfs: fix split_...
2416
2417
  	return __push_leaf_right(trans, root, path, min_data_size, empty,
  				right, free_space, left_nritems, min_slot);
44871b1b2   Chris Mason   Btrfs: reduce sta...
2418
2419
2420
2421
2422
2423
2424
  out_unlock:
  	btrfs_tree_unlock(right);
  	free_extent_buffer(right);
  	return 1;
  }
  
  /*
74123bd72   Chris Mason   Btrfs: Commenting...
2425
2426
   * push some data in the path leaf to the left, trying to free up at
   * least data_size bytes.  returns zero if the push worked, nonzero otherwise
99d8f83c9   Chris Mason   Btrfs: fix split_...
2427
2428
2429
2430
   *
   * max_slot can put a limit on how far into the leaf we'll push items.  The
   * item at 'max_slot' won't be touched.  Use (u32)-1 to make us do all the
   * items
74123bd72   Chris Mason   Btrfs: Commenting...
2431
   */
44871b1b2   Chris Mason   Btrfs: reduce sta...
2432
2433
2434
2435
  static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
  				     struct btrfs_root *root,
  				     struct btrfs_path *path, int data_size,
  				     int empty, struct extent_buffer *left,
99d8f83c9   Chris Mason   Btrfs: fix split_...
2436
2437
  				     int free_space, u32 right_nritems,
  				     u32 max_slot)
be0e5c097   Chris Mason   Btrfs: Initial ch...
2438
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
2439
2440
  	struct btrfs_disk_key disk_key;
  	struct extent_buffer *right = path->nodes[0];
be0e5c097   Chris Mason   Btrfs: Initial ch...
2441
  	int i;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2442
2443
  	int push_space = 0;
  	int push_items = 0;
0783fcfc4   Chris Mason   Btrfs: struct ite...
2444
  	struct btrfs_item *item;
7518a238e   Chris Mason   Btrfs: get/set fo...
2445
  	u32 old_left_nritems;
34a382187   Chris Mason   Btrfs: Change pus...
2446
  	u32 nr;
aa5d6bed2   Chris Mason   Btrfs: return cod...
2447
2448
  	int ret = 0;
  	int wret;
db94535db   Chris Mason   Btrfs: Allow tree...
2449
2450
  	u32 this_item_size;
  	u32 old_left_item_size;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2451

34a382187   Chris Mason   Btrfs: Change pus...
2452
  	if (empty)
99d8f83c9   Chris Mason   Btrfs: fix split_...
2453
  		nr = min(right_nritems, max_slot);
34a382187   Chris Mason   Btrfs: Change pus...
2454
  	else
99d8f83c9   Chris Mason   Btrfs: fix split_...
2455
  		nr = min(right_nritems - 1, max_slot);
34a382187   Chris Mason   Btrfs: Change pus...
2456
2457
  
  	for (i = 0; i < nr; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
2458
  		item = btrfs_item_nr(right, i);
db94535db   Chris Mason   Btrfs: Allow tree...
2459

31840ae1a   Zheng Yan   Btrfs: Full back ...
2460
2461
2462
2463
2464
2465
2466
2467
2468
  		if (!empty && push_items > 0) {
  			if (path->slots[0] < i)
  				break;
  			if (path->slots[0] == i) {
  				int space = btrfs_leaf_free_space(root, right);
  				if (space + push_space * 2 > free_space)
  					break;
  			}
  		}
be0e5c097   Chris Mason   Btrfs: Initial ch...
2469
  		if (path->slots[0] == i)
87b29b208   Yan Zheng   Btrfs: properly c...
2470
  			push_space += data_size;
db94535db   Chris Mason   Btrfs: Allow tree...
2471
2472
2473
  
  		this_item_size = btrfs_item_size(right, item);
  		if (this_item_size + sizeof(*item) + push_space > free_space)
be0e5c097   Chris Mason   Btrfs: Initial ch...
2474
  			break;
db94535db   Chris Mason   Btrfs: Allow tree...
2475

be0e5c097   Chris Mason   Btrfs: Initial ch...
2476
  		push_items++;
db94535db   Chris Mason   Btrfs: Allow tree...
2477
2478
  		push_space += this_item_size + sizeof(*item);
  	}
be0e5c097   Chris Mason   Btrfs: Initial ch...
2479
  	if (push_items == 0) {
925baeddc   Chris Mason   Btrfs: Start btre...
2480
2481
  		ret = 1;
  		goto out;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2482
  	}
34a382187   Chris Mason   Btrfs: Change pus...
2483
  	if (!empty && push_items == btrfs_header_nritems(right))
a429e5137   Chris Mason   Btrfs: working fi...
2484
  		WARN_ON(1);
5f39d397d   Chris Mason   Btrfs: Create ext...
2485

be0e5c097   Chris Mason   Btrfs: Initial ch...
2486
  	/* push data from right to left */
5f39d397d   Chris Mason   Btrfs: Create ext...
2487
2488
2489
2490
  	copy_extent_buffer(left, right,
  			   btrfs_item_nr_offset(btrfs_header_nritems(left)),
  			   btrfs_item_nr_offset(0),
  			   push_items * sizeof(struct btrfs_item));
123abc88c   Chris Mason   Btrfs: variable b...
2491
  	push_space = BTRFS_LEAF_DATA_SIZE(root) -
d397712bc   Chris Mason   Btrfs: Fix checkp...
2492
  		     btrfs_item_offset_nr(right, push_items - 1);
5f39d397d   Chris Mason   Btrfs: Create ext...
2493
2494
  
  	copy_extent_buffer(left, right, btrfs_leaf_data(left) +
d60255795   Chris Mason   Btrfs: corruption...
2495
2496
  		     leaf_data_end(root, left) - push_space,
  		     btrfs_leaf_data(right) +
5f39d397d   Chris Mason   Btrfs: Create ext...
2497
  		     btrfs_item_offset_nr(right, push_items - 1),
d60255795   Chris Mason   Btrfs: corruption...
2498
  		     push_space);
5f39d397d   Chris Mason   Btrfs: Create ext...
2499
  	old_left_nritems = btrfs_header_nritems(left);
87b29b208   Yan Zheng   Btrfs: properly c...
2500
  	BUG_ON(old_left_nritems <= 0);
eb60ceac0   Chris Mason   Btrfs: Add backin...
2501

db94535db   Chris Mason   Btrfs: Allow tree...
2502
  	old_left_item_size = btrfs_item_offset_nr(left, old_left_nritems - 1);
0783fcfc4   Chris Mason   Btrfs: struct ite...
2503
  	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
2504
  		u32 ioff;
db94535db   Chris Mason   Btrfs: Allow tree...
2505

5f39d397d   Chris Mason   Btrfs: Create ext...
2506
  		item = btrfs_item_nr(left, i);
db94535db   Chris Mason   Btrfs: Allow tree...
2507

5f39d397d   Chris Mason   Btrfs: Create ext...
2508
2509
  		ioff = btrfs_item_offset(left, item);
  		btrfs_set_item_offset(left, item,
db94535db   Chris Mason   Btrfs: Allow tree...
2510
  		      ioff - (BTRFS_LEAF_DATA_SIZE(root) - old_left_item_size));
be0e5c097   Chris Mason   Btrfs: Initial ch...
2511
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
2512
  	btrfs_set_header_nritems(left, old_left_nritems + push_items);
be0e5c097   Chris Mason   Btrfs: Initial ch...
2513
2514
  
  	/* fixup right node */
34a382187   Chris Mason   Btrfs: Change pus...
2515
  	if (push_items > right_nritems) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
2516
2517
2518
  		printk(KERN_CRIT "push items %d nr %u
  ", push_items,
  		       right_nritems);
34a382187   Chris Mason   Btrfs: Change pus...
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
  		WARN_ON(1);
  	}
  
  	if (push_items < right_nritems) {
  		push_space = btrfs_item_offset_nr(right, push_items - 1) -
  						  leaf_data_end(root, right);
  		memmove_extent_buffer(right, btrfs_leaf_data(right) +
  				      BTRFS_LEAF_DATA_SIZE(root) - push_space,
  				      btrfs_leaf_data(right) +
  				      leaf_data_end(root, right), push_space);
  
  		memmove_extent_buffer(right, btrfs_item_nr_offset(0),
5f39d397d   Chris Mason   Btrfs: Create ext...
2531
2532
2533
  			      btrfs_item_nr_offset(push_items),
  			     (btrfs_header_nritems(right) - push_items) *
  			     sizeof(struct btrfs_item));
34a382187   Chris Mason   Btrfs: Change pus...
2534
  	}
eef1c494a   Yan   Btrfs: Properly u...
2535
2536
  	right_nritems -= push_items;
  	btrfs_set_header_nritems(right, right_nritems);
123abc88c   Chris Mason   Btrfs: variable b...
2537
  	push_space = BTRFS_LEAF_DATA_SIZE(root);
5f39d397d   Chris Mason   Btrfs: Create ext...
2538
2539
  	for (i = 0; i < right_nritems; i++) {
  		item = btrfs_item_nr(right, i);
db94535db   Chris Mason   Btrfs: Allow tree...
2540

db94535db   Chris Mason   Btrfs: Allow tree...
2541
2542
2543
  		push_space = push_space - btrfs_item_size(right, item);
  		btrfs_set_item_offset(right, item, push_space);
  	}
eb60ceac0   Chris Mason   Btrfs: Add backin...
2544

5f39d397d   Chris Mason   Btrfs: Create ext...
2545
  	btrfs_mark_buffer_dirty(left);
34a382187   Chris Mason   Btrfs: Change pus...
2546
2547
  	if (right_nritems)
  		btrfs_mark_buffer_dirty(right);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2548
2549
  	else
  		clean_tree_block(trans, root, right);
098f59c25   Chris Mason   Btrfs: patch queu...
2550

5f39d397d   Chris Mason   Btrfs: Create ext...
2551
2552
  	btrfs_item_key(right, &disk_key, 0);
  	wret = fixup_low_keys(trans, root, path, &disk_key, 1);
aa5d6bed2   Chris Mason   Btrfs: return cod...
2553
2554
  	if (wret)
  		ret = wret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2555
2556
2557
2558
  
  	/* then fixup the leaf pointer in the path */
  	if (path->slots[0] < push_items) {
  		path->slots[0] += old_left_nritems;
925baeddc   Chris Mason   Btrfs: Start btre...
2559
  		btrfs_tree_unlock(path->nodes[0]);
5f39d397d   Chris Mason   Btrfs: Create ext...
2560
2561
  		free_extent_buffer(path->nodes[0]);
  		path->nodes[0] = left;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2562
2563
  		path->slots[1] -= 1;
  	} else {
925baeddc   Chris Mason   Btrfs: Start btre...
2564
  		btrfs_tree_unlock(left);
5f39d397d   Chris Mason   Btrfs: Create ext...
2565
  		free_extent_buffer(left);
be0e5c097   Chris Mason   Btrfs: Initial ch...
2566
2567
  		path->slots[0] -= push_items;
  	}
eb60ceac0   Chris Mason   Btrfs: Add backin...
2568
  	BUG_ON(path->slots[0] < 0);
aa5d6bed2   Chris Mason   Btrfs: return cod...
2569
  	return ret;
925baeddc   Chris Mason   Btrfs: Start btre...
2570
2571
2572
2573
  out:
  	btrfs_tree_unlock(left);
  	free_extent_buffer(left);
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2574
  }
74123bd72   Chris Mason   Btrfs: Commenting...
2575
  /*
44871b1b2   Chris Mason   Btrfs: reduce sta...
2576
2577
   * push some data in the path leaf to the left, trying to free up at
   * least data_size bytes.  returns zero if the push worked, nonzero otherwise
99d8f83c9   Chris Mason   Btrfs: fix split_...
2578
2579
2580
2581
   *
   * max_slot can put a limit on how far into the leaf we'll push items.  The
   * item at 'max_slot' won't be touched.  Use (u32)-1 to make us push all the
   * items
44871b1b2   Chris Mason   Btrfs: reduce sta...
2582
2583
   */
  static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
99d8f83c9   Chris Mason   Btrfs: fix split_...
2584
2585
  			  *root, struct btrfs_path *path, int min_data_size,
  			  int data_size, int empty, u32 max_slot)
44871b1b2   Chris Mason   Btrfs: reduce sta...
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
  {
  	struct extent_buffer *right = path->nodes[0];
  	struct extent_buffer *left;
  	int slot;
  	int free_space;
  	u32 right_nritems;
  	int ret = 0;
  
  	slot = path->slots[1];
  	if (slot == 0)
  		return 1;
  	if (!path->nodes[1])
  		return 1;
  
  	right_nritems = btrfs_header_nritems(right);
  	if (right_nritems == 0)
  		return 1;
  
  	btrfs_assert_tree_locked(path->nodes[1]);
  
  	left = read_node_slot(root, path->nodes[1], slot - 1);
91ca338d7   Tsutomu Itoh   btrfs: check NULL...
2607
2608
  	if (left == NULL)
  		return 1;
44871b1b2   Chris Mason   Btrfs: reduce sta...
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
  	btrfs_tree_lock(left);
  	btrfs_set_lock_blocking(left);
  
  	free_space = btrfs_leaf_free_space(root, left);
  	if (free_space < data_size) {
  		ret = 1;
  		goto out;
  	}
  
  	/* cow and double check */
  	ret = btrfs_cow_block(trans, root, left,
  			      path->nodes[1], slot - 1, &left);
  	if (ret) {
  		/* we hit -ENOSPC, but it isn't fatal here */
  		ret = 1;
  		goto out;
  	}
  
  	free_space = btrfs_leaf_free_space(root, left);
  	if (free_space < data_size) {
  		ret = 1;
  		goto out;
  	}
99d8f83c9   Chris Mason   Btrfs: fix split_...
2632
2633
2634
  	return __push_leaf_left(trans, root, path, min_data_size,
  			       empty, left, free_space, right_nritems,
  			       max_slot);
44871b1b2   Chris Mason   Btrfs: reduce sta...
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
  out:
  	btrfs_tree_unlock(left);
  	free_extent_buffer(left);
  	return ret;
  }
  
  /*
   * split the path's leaf in two, making sure there is at least data_size
   * available for the resulting leaf level of the path.
   *
   * returns 0 if all went well and < 0 on failure.
   */
  static noinline int copy_for_split(struct btrfs_trans_handle *trans,
  			       struct btrfs_root *root,
  			       struct btrfs_path *path,
  			       struct extent_buffer *l,
  			       struct extent_buffer *right,
  			       int slot, int mid, int nritems)
  {
  	int data_copy_size;
  	int rt_data_off;
  	int i;
  	int ret = 0;
  	int wret;
  	struct btrfs_disk_key disk_key;
  
  	nritems = nritems - mid;
  	btrfs_set_header_nritems(right, nritems);
  	data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(root, l);
  
  	copy_extent_buffer(right, l, btrfs_item_nr_offset(0),
  			   btrfs_item_nr_offset(mid),
  			   nritems * sizeof(struct btrfs_item));
  
  	copy_extent_buffer(right, l,
  		     btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) -
  		     data_copy_size, btrfs_leaf_data(l) +
  		     leaf_data_end(root, l), data_copy_size);
  
  	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
  		      btrfs_item_end_nr(l, mid);
  
  	for (i = 0; i < nritems; i++) {
  		struct btrfs_item *item = btrfs_item_nr(right, i);
  		u32 ioff;
44871b1b2   Chris Mason   Btrfs: reduce sta...
2680
2681
2682
  		ioff = btrfs_item_offset(right, item);
  		btrfs_set_item_offset(right, item, ioff + rt_data_off);
  	}
44871b1b2   Chris Mason   Btrfs: reduce sta...
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
  	btrfs_set_header_nritems(l, mid);
  	ret = 0;
  	btrfs_item_key(right, &disk_key, 0);
  	wret = insert_ptr(trans, root, path, &disk_key, right->start,
  			  path->slots[1] + 1, 1);
  	if (wret)
  		ret = wret;
  
  	btrfs_mark_buffer_dirty(right);
  	btrfs_mark_buffer_dirty(l);
  	BUG_ON(path->slots[0] != slot);
44871b1b2   Chris Mason   Btrfs: reduce sta...
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
  	if (mid <= slot) {
  		btrfs_tree_unlock(path->nodes[0]);
  		free_extent_buffer(path->nodes[0]);
  		path->nodes[0] = right;
  		path->slots[0] -= mid;
  		path->slots[1] += 1;
  	} else {
  		btrfs_tree_unlock(right);
  		free_extent_buffer(right);
  	}
  
  	BUG_ON(path->slots[0] < 0);
  
  	return ret;
  }
  
  /*
99d8f83c9   Chris Mason   Btrfs: fix split_...
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
   * double splits happen when we need to insert a big item in the middle
   * of a leaf.  A double split can leave us with 3 mostly empty leaves:
   * leaf: [ slots 0 - N] [ our target ] [ N + 1 - total in leaf ]
   *          A                 B                 C
   *
   * We avoid this by trying to push the items on either side of our target
   * into the adjacent leaves.  If all goes well we can avoid the double split
   * completely.
   */
  static noinline int push_for_double_split(struct btrfs_trans_handle *trans,
  					  struct btrfs_root *root,
  					  struct btrfs_path *path,
  					  int data_size)
  {
  	int ret;
  	int progress = 0;
  	int slot;
  	u32 nritems;
  
  	slot = path->slots[0];
  
  	/*
  	 * try to push all the items after our slot into the
  	 * right leaf
  	 */
  	ret = push_leaf_right(trans, root, path, 1, data_size, 0, slot);
  	if (ret < 0)
  		return ret;
  
  	if (ret == 0)
  		progress++;
  
  	nritems = btrfs_header_nritems(path->nodes[0]);
  	/*
  	 * our goal is to get our slot at the start or end of a leaf.  If
  	 * we've done so we're done
  	 */
  	if (path->slots[0] == 0 || path->slots[0] == nritems)
  		return 0;
  
  	if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size)
  		return 0;
  
  	/* try to push all the items before our slot into the next leaf */
  	slot = path->slots[0];
  	ret = push_leaf_left(trans, root, path, 1, data_size, 0, slot);
  	if (ret < 0)
  		return ret;
  
  	if (ret == 0)
  		progress++;
  
  	if (progress)
  		return 0;
  	return 1;
  }
  
  /*
74123bd72   Chris Mason   Btrfs: Commenting...
2769
2770
   * split the path's leaf in two, making sure there is at least data_size
   * available for the resulting leaf level of the path.
aa5d6bed2   Chris Mason   Btrfs: return cod...
2771
2772
   *
   * returns 0 if all went well and < 0 on failure.
74123bd72   Chris Mason   Btrfs: Commenting...
2773
   */
e02119d5a   Chris Mason   Btrfs: Add a writ...
2774
2775
2776
2777
2778
  static noinline int split_leaf(struct btrfs_trans_handle *trans,
  			       struct btrfs_root *root,
  			       struct btrfs_key *ins_key,
  			       struct btrfs_path *path, int data_size,
  			       int extend)
be0e5c097   Chris Mason   Btrfs: Initial ch...
2779
  {
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2780
  	struct btrfs_disk_key disk_key;
5f39d397d   Chris Mason   Btrfs: Create ext...
2781
  	struct extent_buffer *l;
7518a238e   Chris Mason   Btrfs: get/set fo...
2782
  	u32 nritems;
eb60ceac0   Chris Mason   Btrfs: Add backin...
2783
2784
  	int mid;
  	int slot;
5f39d397d   Chris Mason   Btrfs: Create ext...
2785
  	struct extent_buffer *right;
d4dbff953   Chris Mason   Btrfs: support fo...
2786
  	int ret = 0;
aa5d6bed2   Chris Mason   Btrfs: return cod...
2787
  	int wret;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2788
  	int split;
cc0c55384   Chris Mason   Btrfs: Fix split_...
2789
  	int num_doubles = 0;
99d8f83c9   Chris Mason   Btrfs: fix split_...
2790
  	int tried_avoid_double = 0;
aa5d6bed2   Chris Mason   Btrfs: return cod...
2791

a57195214   Yan, Zheng   Btrfs: check size...
2792
2793
2794
2795
2796
  	l = path->nodes[0];
  	slot = path->slots[0];
  	if (extend && data_size + btrfs_item_size_nr(l, slot) +
  	    sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root))
  		return -EOVERFLOW;
406894788   Chris Mason   Btrfs: minor comm...
2797
  	/* first try to make some room by pushing left and right */
99d8f83c9   Chris Mason   Btrfs: fix split_...
2798
2799
2800
  	if (data_size) {
  		wret = push_leaf_right(trans, root, path, data_size,
  				       data_size, 0, 0);
d397712bc   Chris Mason   Btrfs: Fix checkp...
2801
  		if (wret < 0)
eaee50e88   Chris Mason   Btrfs: merge leav...
2802
  			return wret;
3685f7916   Chris Mason   Btrfs: CPU usage ...
2803
  		if (wret) {
99d8f83c9   Chris Mason   Btrfs: fix split_...
2804
2805
  			wret = push_leaf_left(trans, root, path, data_size,
  					      data_size, 0, (u32)-1);
3685f7916   Chris Mason   Btrfs: CPU usage ...
2806
2807
2808
2809
  			if (wret < 0)
  				return wret;
  		}
  		l = path->nodes[0];
aa5d6bed2   Chris Mason   Btrfs: return cod...
2810

3685f7916   Chris Mason   Btrfs: CPU usage ...
2811
  		/* did the pushes work? */
87b29b208   Yan Zheng   Btrfs: properly c...
2812
  		if (btrfs_leaf_free_space(root, l) >= data_size)
3685f7916   Chris Mason   Btrfs: CPU usage ...
2813
  			return 0;
3326d1b07   Chris Mason   Btrfs: Allow tail...
2814
  	}
aa5d6bed2   Chris Mason   Btrfs: return cod...
2815

5c680ed62   Chris Mason   Btrfs: switch to ...
2816
  	if (!path->nodes[1]) {
e089f05c1   Chris Mason   Btrfs: transactio...
2817
  		ret = insert_new_root(trans, root, path, 1);
5c680ed62   Chris Mason   Btrfs: switch to ...
2818
2819
2820
  		if (ret)
  			return ret;
  	}
cc0c55384   Chris Mason   Btrfs: Fix split_...
2821
  again:
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2822
  	split = 1;
cc0c55384   Chris Mason   Btrfs: Fix split_...
2823
  	l = path->nodes[0];
eb60ceac0   Chris Mason   Btrfs: Add backin...
2824
  	slot = path->slots[0];
5f39d397d   Chris Mason   Btrfs: Create ext...
2825
  	nritems = btrfs_header_nritems(l);
d397712bc   Chris Mason   Btrfs: Fix checkp...
2826
  	mid = (nritems + 1) / 2;
54aa1f4df   Chris Mason   Btrfs: Audit call...
2827

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
  	if (mid <= slot) {
  		if (nritems == 1 ||
  		    leaf_space_used(l, mid, nritems - mid) + data_size >
  			BTRFS_LEAF_DATA_SIZE(root)) {
  			if (slot >= nritems) {
  				split = 0;
  			} else {
  				mid = slot;
  				if (mid != nritems &&
  				    leaf_space_used(l, mid, nritems - mid) +
  				    data_size > BTRFS_LEAF_DATA_SIZE(root)) {
99d8f83c9   Chris Mason   Btrfs: fix split_...
2839
2840
  					if (data_size && !tried_avoid_double)
  						goto push_for_double;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
  					split = 2;
  				}
  			}
  		}
  	} else {
  		if (leaf_space_used(l, 0, mid) + data_size >
  			BTRFS_LEAF_DATA_SIZE(root)) {
  			if (!extend && data_size && slot == 0) {
  				split = 0;
  			} else if ((extend || !data_size) && slot == 0) {
  				mid = 1;
  			} else {
  				mid = slot;
  				if (mid != nritems &&
  				    leaf_space_used(l, mid, nritems - mid) +
  				    data_size > BTRFS_LEAF_DATA_SIZE(root)) {
99d8f83c9   Chris Mason   Btrfs: fix split_...
2857
2858
  					if (data_size && !tried_avoid_double)
  						goto push_for_double;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
  					split = 2 ;
  				}
  			}
  		}
  	}
  
  	if (split == 0)
  		btrfs_cpu_key_to_disk(&disk_key, ins_key);
  	else
  		btrfs_item_key(l, &disk_key, mid);
  
  	right = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
31840ae1a   Zheng Yan   Btrfs: Full back ...
2871
  					root->root_key.objectid,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2872
  					&disk_key, 0, l->start, 0);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2873
  	if (IS_ERR(right))
5f39d397d   Chris Mason   Btrfs: Create ext...
2874
  		return PTR_ERR(right);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2875
2876
  
  	root_add_used(root, root->leafsize);
5f39d397d   Chris Mason   Btrfs: Create ext...
2877
2878
  
  	memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header));
db94535db   Chris Mason   Btrfs: Allow tree...
2879
  	btrfs_set_header_bytenr(right, right->start);
5f39d397d   Chris Mason   Btrfs: Create ext...
2880
  	btrfs_set_header_generation(right, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2881
  	btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV);
5f39d397d   Chris Mason   Btrfs: Create ext...
2882
2883
2884
2885
2886
  	btrfs_set_header_owner(right, root->root_key.objectid);
  	btrfs_set_header_level(right, 0);
  	write_extent_buffer(right, root->fs_info->fsid,
  			    (unsigned long)btrfs_header_fsid(right),
  			    BTRFS_FSID_SIZE);
e17cade25   Chris Mason   Btrfs: Add chunk ...
2887
2888
2889
2890
  
  	write_extent_buffer(right, root->fs_info->chunk_tree_uuid,
  			    (unsigned long)btrfs_header_chunk_tree_uuid(right),
  			    BTRFS_UUID_SIZE);
44871b1b2   Chris Mason   Btrfs: reduce sta...
2891

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2892
2893
2894
2895
2896
2897
2898
2899
  	if (split == 0) {
  		if (mid <= slot) {
  			btrfs_set_header_nritems(right, 0);
  			wret = insert_ptr(trans, root, path,
  					  &disk_key, right->start,
  					  path->slots[1] + 1, 1);
  			if (wret)
  				ret = wret;
925baeddc   Chris Mason   Btrfs: Start btre...
2900

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
  			btrfs_tree_unlock(path->nodes[0]);
  			free_extent_buffer(path->nodes[0]);
  			path->nodes[0] = right;
  			path->slots[0] = 0;
  			path->slots[1] += 1;
  		} else {
  			btrfs_set_header_nritems(right, 0);
  			wret = insert_ptr(trans, root, path,
  					  &disk_key,
  					  right->start,
  					  path->slots[1], 1);
  			if (wret)
  				ret = wret;
  			btrfs_tree_unlock(path->nodes[0]);
  			free_extent_buffer(path->nodes[0]);
  			path->nodes[0] = right;
  			path->slots[0] = 0;
  			if (path->slots[1] == 0) {
  				wret = fixup_low_keys(trans, root,
  						path, &disk_key, 1);
d4dbff953   Chris Mason   Btrfs: support fo...
2921
2922
  				if (wret)
  					ret = wret;
5ee78ac70   Chris Mason   Btrfs: Fix split_...
2923
  			}
d4dbff953   Chris Mason   Btrfs: support fo...
2924
  		}
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2925
2926
  		btrfs_mark_buffer_dirty(right);
  		return ret;
d4dbff953   Chris Mason   Btrfs: support fo...
2927
  	}
74123bd72   Chris Mason   Btrfs: Commenting...
2928

44871b1b2   Chris Mason   Btrfs: reduce sta...
2929
  	ret = copy_for_split(trans, root, path, l, right, slot, mid, nritems);
31840ae1a   Zheng Yan   Btrfs: Full back ...
2930
  	BUG_ON(ret);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2931
  	if (split == 2) {
cc0c55384   Chris Mason   Btrfs: Fix split_...
2932
2933
2934
  		BUG_ON(num_doubles != 0);
  		num_doubles++;
  		goto again;
a429e5137   Chris Mason   Btrfs: working fi...
2935
  	}
44871b1b2   Chris Mason   Btrfs: reduce sta...
2936

be0e5c097   Chris Mason   Btrfs: Initial ch...
2937
  	return ret;
99d8f83c9   Chris Mason   Btrfs: fix split_...
2938
2939
2940
2941
2942
2943
2944
  
  push_for_double:
  	push_for_double_split(trans, root, path, data_size);
  	tried_avoid_double = 1;
  	if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size)
  		return 0;
  	goto again;
be0e5c097   Chris Mason   Btrfs: Initial ch...
2945
  }
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2946
2947
2948
  static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
  					 struct btrfs_root *root,
  					 struct btrfs_path *path, int ins_len)
459931eca   Chris Mason   Btrfs: Delete csu...
2949
  {
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2950
  	struct btrfs_key key;
459931eca   Chris Mason   Btrfs: Delete csu...
2951
  	struct extent_buffer *leaf;
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2952
2953
2954
2955
  	struct btrfs_file_extent_item *fi;
  	u64 extent_len = 0;
  	u32 item_size;
  	int ret;
459931eca   Chris Mason   Btrfs: Delete csu...
2956
2957
  
  	leaf = path->nodes[0];
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2958
2959
2960
2961
2962
2963
2964
  	btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
  
  	BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY &&
  	       key.type != BTRFS_EXTENT_CSUM_KEY);
  
  	if (btrfs_leaf_free_space(root, leaf) >= ins_len)
  		return 0;
459931eca   Chris Mason   Btrfs: Delete csu...
2965
2966
  
  	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2967
2968
2969
2970
2971
  	if (key.type == BTRFS_EXTENT_DATA_KEY) {
  		fi = btrfs_item_ptr(leaf, path->slots[0],
  				    struct btrfs_file_extent_item);
  		extent_len = btrfs_file_extent_num_bytes(leaf, fi);
  	}
b3b4aa74b   David Sterba   btrfs: drop unuse...
2972
  	btrfs_release_path(path);
459931eca   Chris Mason   Btrfs: Delete csu...
2973

459931eca   Chris Mason   Btrfs: Delete csu...
2974
  	path->keep_locks = 1;
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2975
2976
  	path->search_for_split = 1;
  	ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
459931eca   Chris Mason   Btrfs: Delete csu...
2977
  	path->search_for_split = 0;
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2978
2979
  	if (ret < 0)
  		goto err;
459931eca   Chris Mason   Btrfs: Delete csu...
2980

ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2981
2982
  	ret = -EAGAIN;
  	leaf = path->nodes[0];
459931eca   Chris Mason   Btrfs: Delete csu...
2983
  	/* if our item isn't there or got smaller, return now */
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2984
2985
  	if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
  		goto err;
109f6aef5   Chris Mason   Btrfs: add check ...
2986
2987
2988
  	/* the leaf has  changed, it now has room.  return now */
  	if (btrfs_leaf_free_space(root, path->nodes[0]) >= ins_len)
  		goto err;
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2989
2990
2991
2992
2993
  	if (key.type == BTRFS_EXTENT_DATA_KEY) {
  		fi = btrfs_item_ptr(leaf, path->slots[0],
  				    struct btrfs_file_extent_item);
  		if (extent_len != btrfs_file_extent_num_bytes(leaf, fi))
  			goto err;
459931eca   Chris Mason   Btrfs: Delete csu...
2994
  	}
b9473439d   Chris Mason   Btrfs: leave btre...
2995
  	btrfs_set_path_blocking(path);
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
2996
  	ret = split_leaf(trans, root, &key, path, ins_len, 1);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
2997
2998
  	if (ret)
  		goto err;
459931eca   Chris Mason   Btrfs: Delete csu...
2999

ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3000
  	path->keep_locks = 0;
b9473439d   Chris Mason   Btrfs: leave btre...
3001
  	btrfs_unlock_up_safe(path, 1);
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
  	return 0;
  err:
  	path->keep_locks = 0;
  	return ret;
  }
  
  static noinline int split_item(struct btrfs_trans_handle *trans,
  			       struct btrfs_root *root,
  			       struct btrfs_path *path,
  			       struct btrfs_key *new_key,
  			       unsigned long split_offset)
  {
  	struct extent_buffer *leaf;
  	struct btrfs_item *item;
  	struct btrfs_item *new_item;
  	int slot;
  	char *buf;
  	u32 nritems;
  	u32 item_size;
  	u32 orig_offset;
  	struct btrfs_disk_key disk_key;
b9473439d   Chris Mason   Btrfs: leave btre...
3023
3024
  	leaf = path->nodes[0];
  	BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
b4ce94de9   Chris Mason   Btrfs: Change btr...
3025
  	btrfs_set_path_blocking(path);
459931eca   Chris Mason   Btrfs: Delete csu...
3026
3027
3028
  	item = btrfs_item_nr(leaf, path->slots[0]);
  	orig_offset = btrfs_item_offset(leaf, item);
  	item_size = btrfs_item_size(leaf, item);
459931eca   Chris Mason   Btrfs: Delete csu...
3029
  	buf = kmalloc(item_size, GFP_NOFS);
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3030
3031
  	if (!buf)
  		return -ENOMEM;
459931eca   Chris Mason   Btrfs: Delete csu...
3032
3033
  	read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
  			    path->slots[0]), item_size);
459931eca   Chris Mason   Btrfs: Delete csu...
3034

ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3035
  	slot = path->slots[0] + 1;
459931eca   Chris Mason   Btrfs: Delete csu...
3036
  	nritems = btrfs_header_nritems(leaf);
459931eca   Chris Mason   Btrfs: Delete csu...
3037
3038
3039
  	if (slot != nritems) {
  		/* shift the items */
  		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3040
3041
  				btrfs_item_nr_offset(slot),
  				(nritems - slot) * sizeof(struct btrfs_item));
459931eca   Chris Mason   Btrfs: Delete csu...
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
  	}
  
  	btrfs_cpu_key_to_disk(&disk_key, new_key);
  	btrfs_set_item_key(leaf, &disk_key, slot);
  
  	new_item = btrfs_item_nr(leaf, slot);
  
  	btrfs_set_item_offset(leaf, new_item, orig_offset);
  	btrfs_set_item_size(leaf, new_item, item_size - split_offset);
  
  	btrfs_set_item_offset(leaf, item,
  			      orig_offset + item_size - split_offset);
  	btrfs_set_item_size(leaf, item, split_offset);
  
  	btrfs_set_header_nritems(leaf, nritems + 1);
  
  	/* write the data for the start of the original item */
  	write_extent_buffer(leaf, buf,
  			    btrfs_item_ptr_offset(leaf, path->slots[0]),
  			    split_offset);
  
  	/* write the data for the new item */
  	write_extent_buffer(leaf, buf + split_offset,
  			    btrfs_item_ptr_offset(leaf, slot),
  			    item_size - split_offset);
  	btrfs_mark_buffer_dirty(leaf);
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3068
  	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
459931eca   Chris Mason   Btrfs: Delete csu...
3069
  	kfree(buf);
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
  	return 0;
  }
  
  /*
   * This function splits a single item into two items,
   * giving 'new_key' to the new item and splitting the
   * old one at split_offset (from the start of the item).
   *
   * The path may be released by this operation.  After
   * the split, the path is pointing to the old item.  The
   * new item is going to be in the same node as the old one.
   *
   * Note, the item being split must be smaller enough to live alone on
   * a tree block with room for one extra struct btrfs_item
   *
   * This allows us to split the item in place, keeping a lock on the
   * leaf the entire time.
   */
  int btrfs_split_item(struct btrfs_trans_handle *trans,
  		     struct btrfs_root *root,
  		     struct btrfs_path *path,
  		     struct btrfs_key *new_key,
  		     unsigned long split_offset)
  {
  	int ret;
  	ret = setup_leaf_for_split(trans, root, path,
  				   sizeof(struct btrfs_item));
  	if (ret)
  		return ret;
  
  	ret = split_item(trans, root, path, new_key, split_offset);
459931eca   Chris Mason   Btrfs: Delete csu...
3101
3102
3103
3104
  	return ret;
  }
  
  /*
ad48fd754   Yan, Zheng   Btrfs: Add btrfs_...
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
   * This function duplicate a item, giving 'new_key' to the new item.
   * It guarantees both items live in the same tree leaf and the new item
   * is contiguous with the original item.
   *
   * This allows us to split file extent in place, keeping a lock on the
   * leaf the entire time.
   */
  int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
  			 struct btrfs_root *root,
  			 struct btrfs_path *path,
  			 struct btrfs_key *new_key)
  {
  	struct extent_buffer *leaf;
  	int ret;
  	u32 item_size;
  
  	leaf = path->nodes[0];
  	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
  	ret = setup_leaf_for_split(trans, root, path,
  				   item_size + sizeof(struct btrfs_item));
  	if (ret)
  		return ret;
  
  	path->slots[0]++;
  	ret = setup_items_for_insert(trans, root, path, new_key, &item_size,
  				     item_size, item_size +
  				     sizeof(struct btrfs_item), 1);
  	BUG_ON(ret);
  
  	leaf = path->nodes[0];
  	memcpy_extent_buffer(leaf,
  			     btrfs_item_ptr_offset(leaf, path->slots[0]),
  			     btrfs_item_ptr_offset(leaf, path->slots[0] - 1),
  			     item_size);
  	return 0;
  }
  
  /*
d352ac681   Chris Mason   Btrfs: add and im...
3143
3144
3145
3146
3147
   * make the item pointed to by the path smaller.  new_size indicates
   * how small to make it, and from_end tells us if we just chop bytes
   * off the end of the item or if we shift the item to chop bytes off
   * the front.
   */
b18c66858   Chris Mason   Btrfs: progress o...
3148
3149
3150
  int btrfs_truncate_item(struct btrfs_trans_handle *trans,
  			struct btrfs_root *root,
  			struct btrfs_path *path,
179e29e48   Chris Mason   Btrfs: Fix a numb...
3151
  			u32 new_size, int from_end)
b18c66858   Chris Mason   Btrfs: progress o...
3152
  {
b18c66858   Chris Mason   Btrfs: progress o...
3153
  	int slot;
5f39d397d   Chris Mason   Btrfs: Create ext...
3154
3155
  	struct extent_buffer *leaf;
  	struct btrfs_item *item;
b18c66858   Chris Mason   Btrfs: progress o...
3156
3157
3158
3159
3160
3161
  	u32 nritems;
  	unsigned int data_end;
  	unsigned int old_data_start;
  	unsigned int old_size;
  	unsigned int size_diff;
  	int i;
5f39d397d   Chris Mason   Btrfs: Create ext...
3162
  	leaf = path->nodes[0];
179e29e48   Chris Mason   Btrfs: Fix a numb...
3163
3164
3165
3166
3167
  	slot = path->slots[0];
  
  	old_size = btrfs_item_size_nr(leaf, slot);
  	if (old_size == new_size)
  		return 0;
b18c66858   Chris Mason   Btrfs: progress o...
3168

5f39d397d   Chris Mason   Btrfs: Create ext...
3169
  	nritems = btrfs_header_nritems(leaf);
b18c66858   Chris Mason   Btrfs: progress o...
3170
  	data_end = leaf_data_end(root, leaf);
5f39d397d   Chris Mason   Btrfs: Create ext...
3171
  	old_data_start = btrfs_item_offset_nr(leaf, slot);
179e29e48   Chris Mason   Btrfs: Fix a numb...
3172

b18c66858   Chris Mason   Btrfs: progress o...
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
  	size_diff = old_size - new_size;
  
  	BUG_ON(slot < 0);
  	BUG_ON(slot >= nritems);
  
  	/*
  	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
  	 */
  	/* first correct the data pointers */
  	for (i = slot; i < nritems; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3183
3184
  		u32 ioff;
  		item = btrfs_item_nr(leaf, i);
db94535db   Chris Mason   Btrfs: Allow tree...
3185

5f39d397d   Chris Mason   Btrfs: Create ext...
3186
3187
  		ioff = btrfs_item_offset(leaf, item);
  		btrfs_set_item_offset(leaf, item, ioff + size_diff);
b18c66858   Chris Mason   Btrfs: progress o...
3188
  	}
db94535db   Chris Mason   Btrfs: Allow tree...
3189

b18c66858   Chris Mason   Btrfs: progress o...
3190
  	/* shift the data */
179e29e48   Chris Mason   Btrfs: Fix a numb...
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
  	if (from_end) {
  		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
  			      data_end + size_diff, btrfs_leaf_data(leaf) +
  			      data_end, old_data_start + new_size - data_end);
  	} else {
  		struct btrfs_disk_key disk_key;
  		u64 offset;
  
  		btrfs_item_key(leaf, &disk_key, slot);
  
  		if (btrfs_disk_key_type(&disk_key) == BTRFS_EXTENT_DATA_KEY) {
  			unsigned long ptr;
  			struct btrfs_file_extent_item *fi;
  
  			fi = btrfs_item_ptr(leaf, slot,
  					    struct btrfs_file_extent_item);
  			fi = (struct btrfs_file_extent_item *)(
  			     (unsigned long)fi - size_diff);
  
  			if (btrfs_file_extent_type(leaf, fi) ==
  			    BTRFS_FILE_EXTENT_INLINE) {
  				ptr = btrfs_item_ptr_offset(leaf, slot);
  				memmove_extent_buffer(leaf, ptr,
d397712bc   Chris Mason   Btrfs: Fix checkp...
3214
3215
  				      (unsigned long)fi,
  				      offsetof(struct btrfs_file_extent_item,
179e29e48   Chris Mason   Btrfs: Fix a numb...
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
  						 disk_bytenr));
  			}
  		}
  
  		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
  			      data_end + size_diff, btrfs_leaf_data(leaf) +
  			      data_end, old_data_start - data_end);
  
  		offset = btrfs_disk_key_offset(&disk_key);
  		btrfs_set_disk_key_offset(&disk_key, offset + size_diff);
  		btrfs_set_item_key(leaf, &disk_key, slot);
  		if (slot == 0)
  			fixup_low_keys(trans, root, path, &disk_key, 1);
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
3230
3231
3232
3233
  
  	item = btrfs_item_nr(leaf, slot);
  	btrfs_set_item_size(leaf, item, new_size);
  	btrfs_mark_buffer_dirty(leaf);
b18c66858   Chris Mason   Btrfs: progress o...
3234

5f39d397d   Chris Mason   Btrfs: Create ext...
3235
3236
  	if (btrfs_leaf_free_space(root, leaf) < 0) {
  		btrfs_print_leaf(root, leaf);
b18c66858   Chris Mason   Btrfs: progress o...
3237
  		BUG();
5f39d397d   Chris Mason   Btrfs: Create ext...
3238
  	}
1cd307990   Tsutomu Itoh   Btrfs: BUG_ON is ...
3239
  	return 0;
b18c66858   Chris Mason   Btrfs: progress o...
3240
  }
d352ac681   Chris Mason   Btrfs: add and im...
3241
3242
3243
  /*
   * make the item pointed to by the path bigger, data_size is the new size.
   */
5f39d397d   Chris Mason   Btrfs: Create ext...
3244
3245
3246
  int btrfs_extend_item(struct btrfs_trans_handle *trans,
  		      struct btrfs_root *root, struct btrfs_path *path,
  		      u32 data_size)
6567e837d   Chris Mason   Btrfs: early work...
3247
  {
6567e837d   Chris Mason   Btrfs: early work...
3248
  	int slot;
5f39d397d   Chris Mason   Btrfs: Create ext...
3249
3250
  	struct extent_buffer *leaf;
  	struct btrfs_item *item;
6567e837d   Chris Mason   Btrfs: early work...
3251
3252
3253
3254
3255
  	u32 nritems;
  	unsigned int data_end;
  	unsigned int old_data;
  	unsigned int old_size;
  	int i;
5f39d397d   Chris Mason   Btrfs: Create ext...
3256
  	leaf = path->nodes[0];
6567e837d   Chris Mason   Btrfs: early work...
3257

5f39d397d   Chris Mason   Btrfs: Create ext...
3258
  	nritems = btrfs_header_nritems(leaf);
6567e837d   Chris Mason   Btrfs: early work...
3259
  	data_end = leaf_data_end(root, leaf);
5f39d397d   Chris Mason   Btrfs: Create ext...
3260
3261
  	if (btrfs_leaf_free_space(root, leaf) < data_size) {
  		btrfs_print_leaf(root, leaf);
6567e837d   Chris Mason   Btrfs: early work...
3262
  		BUG();
5f39d397d   Chris Mason   Btrfs: Create ext...
3263
  	}
6567e837d   Chris Mason   Btrfs: early work...
3264
  	slot = path->slots[0];
5f39d397d   Chris Mason   Btrfs: Create ext...
3265
  	old_data = btrfs_item_end_nr(leaf, slot);
6567e837d   Chris Mason   Btrfs: early work...
3266
3267
  
  	BUG_ON(slot < 0);
3326d1b07   Chris Mason   Btrfs: Allow tail...
3268
3269
  	if (slot >= nritems) {
  		btrfs_print_leaf(root, leaf);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3270
3271
3272
  		printk(KERN_CRIT "slot %d too large, nritems %d
  ",
  		       slot, nritems);
3326d1b07   Chris Mason   Btrfs: Allow tail...
3273
3274
  		BUG_ON(1);
  	}
6567e837d   Chris Mason   Btrfs: early work...
3275
3276
3277
3278
3279
3280
  
  	/*
  	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
  	 */
  	/* first correct the data pointers */
  	for (i = slot; i < nritems; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3281
3282
  		u32 ioff;
  		item = btrfs_item_nr(leaf, i);
db94535db   Chris Mason   Btrfs: Allow tree...
3283

5f39d397d   Chris Mason   Btrfs: Create ext...
3284
3285
  		ioff = btrfs_item_offset(leaf, item);
  		btrfs_set_item_offset(leaf, item, ioff - data_size);
6567e837d   Chris Mason   Btrfs: early work...
3286
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
3287

6567e837d   Chris Mason   Btrfs: early work...
3288
  	/* shift the data */
5f39d397d   Chris Mason   Btrfs: Create ext...
3289
  	memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
6567e837d   Chris Mason   Btrfs: early work...
3290
3291
  		      data_end - data_size, btrfs_leaf_data(leaf) +
  		      data_end, old_data - data_end);
5f39d397d   Chris Mason   Btrfs: Create ext...
3292

6567e837d   Chris Mason   Btrfs: early work...
3293
  	data_end = old_data;
5f39d397d   Chris Mason   Btrfs: Create ext...
3294
3295
3296
3297
  	old_size = btrfs_item_size_nr(leaf, slot);
  	item = btrfs_item_nr(leaf, slot);
  	btrfs_set_item_size(leaf, item, old_size + data_size);
  	btrfs_mark_buffer_dirty(leaf);
6567e837d   Chris Mason   Btrfs: early work...
3298

5f39d397d   Chris Mason   Btrfs: Create ext...
3299
3300
  	if (btrfs_leaf_free_space(root, leaf) < 0) {
  		btrfs_print_leaf(root, leaf);
6567e837d   Chris Mason   Btrfs: early work...
3301
  		BUG();
5f39d397d   Chris Mason   Btrfs: Create ext...
3302
  	}
1cd307990   Tsutomu Itoh   Btrfs: BUG_ON is ...
3303
  	return 0;
6567e837d   Chris Mason   Btrfs: early work...
3304
  }
74123bd72   Chris Mason   Btrfs: Commenting...
3305
  /*
d352ac681   Chris Mason   Btrfs: add and im...
3306
   * Given a key and some data, insert items into the tree.
74123bd72   Chris Mason   Btrfs: Commenting...
3307
   * This does all the path init required, making room in the tree if needed.
f3465ca44   Josef Bacik   Btrfs: batch exte...
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
   * Returns the number of keys that were inserted.
   */
  int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
  			    struct btrfs_root *root,
  			    struct btrfs_path *path,
  			    struct btrfs_key *cpu_key, u32 *data_size,
  			    int nr)
  {
  	struct extent_buffer *leaf;
  	struct btrfs_item *item;
  	int ret = 0;
  	int slot;
f3465ca44   Josef Bacik   Btrfs: batch exte...
3320
3321
3322
3323
3324
3325
3326
  	int i;
  	u32 nritems;
  	u32 total_data = 0;
  	u32 total_size = 0;
  	unsigned int data_end;
  	struct btrfs_disk_key disk_key;
  	struct btrfs_key found_key;
87b29b208   Yan Zheng   Btrfs: properly c...
3327
3328
3329
3330
3331
3332
  	for (i = 0; i < nr; i++) {
  		if (total_size + data_size[i] + sizeof(struct btrfs_item) >
  		    BTRFS_LEAF_DATA_SIZE(root)) {
  			break;
  			nr = i;
  		}
f3465ca44   Josef Bacik   Btrfs: batch exte...
3333
  		total_data += data_size[i];
87b29b208   Yan Zheng   Btrfs: properly c...
3334
3335
3336
  		total_size += data_size[i] + sizeof(struct btrfs_item);
  	}
  	BUG_ON(nr == 0);
f3465ca44   Josef Bacik   Btrfs: batch exte...
3337

f3465ca44   Josef Bacik   Btrfs: batch exte...
3338
3339
3340
3341
3342
  	ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1);
  	if (ret == 0)
  		return -EEXIST;
  	if (ret < 0)
  		goto out;
f3465ca44   Josef Bacik   Btrfs: batch exte...
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
  	leaf = path->nodes[0];
  
  	nritems = btrfs_header_nritems(leaf);
  	data_end = leaf_data_end(root, leaf);
  
  	if (btrfs_leaf_free_space(root, leaf) < total_size) {
  		for (i = nr; i >= 0; i--) {
  			total_data -= data_size[i];
  			total_size -= data_size[i] + sizeof(struct btrfs_item);
  			if (total_size < btrfs_leaf_free_space(root, leaf))
  				break;
  		}
  		nr = i;
  	}
  
  	slot = path->slots[0];
  	BUG_ON(slot < 0);
  
  	if (slot != nritems) {
  		unsigned int old_data = btrfs_item_end_nr(leaf, slot);
  
  		item = btrfs_item_nr(leaf, slot);
  		btrfs_item_key_to_cpu(leaf, &found_key, slot);
  
  		/* figure out how many keys we can insert in here */
  		total_data = data_size[0];
  		for (i = 1; i < nr; i++) {
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3370
  			if (btrfs_comp_cpu_keys(&found_key, cpu_key + i) <= 0)
f3465ca44   Josef Bacik   Btrfs: batch exte...
3371
3372
3373
3374
3375
3376
3377
  				break;
  			total_data += data_size[i];
  		}
  		nr = i;
  
  		if (old_data < data_end) {
  			btrfs_print_leaf(root, leaf);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3378
3379
  			printk(KERN_CRIT "slot %d old_data %d data_end %d
  ",
f3465ca44   Josef Bacik   Btrfs: batch exte...
3380
3381
3382
3383
3384
3385
3386
  			       slot, old_data, data_end);
  			BUG_ON(1);
  		}
  		/*
  		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
  		 */
  		/* first correct the data pointers */
f3465ca44   Josef Bacik   Btrfs: batch exte...
3387
3388
3389
3390
  		for (i = slot; i < nritems; i++) {
  			u32 ioff;
  
  			item = btrfs_item_nr(leaf, i);
f3465ca44   Josef Bacik   Btrfs: batch exte...
3391
3392
3393
  			ioff = btrfs_item_offset(leaf, item);
  			btrfs_set_item_offset(leaf, item, ioff - total_data);
  		}
f3465ca44   Josef Bacik   Btrfs: batch exte...
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
  		/* shift the items */
  		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
  			      btrfs_item_nr_offset(slot),
  			      (nritems - slot) * sizeof(struct btrfs_item));
  
  		/* shift the data */
  		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
  			      data_end - total_data, btrfs_leaf_data(leaf) +
  			      data_end, old_data - data_end);
  		data_end = old_data;
  	} else {
  		/*
  		 * this sucks but it has to be done, if we are inserting at
  		 * the end of the leaf only insert 1 of the items, since we
  		 * have no way of knowing whats on the next leaf and we'd have
  		 * to drop our current locks to figure it out
  		 */
  		nr = 1;
  	}
  
  	/* setup the item for the new data */
  	for (i = 0; i < nr; i++) {
  		btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
  		btrfs_set_item_key(leaf, &disk_key, slot + i);
  		item = btrfs_item_nr(leaf, slot + i);
  		btrfs_set_item_offset(leaf, item, data_end - data_size[i]);
  		data_end -= data_size[i];
  		btrfs_set_item_size(leaf, item, data_size[i]);
  	}
  	btrfs_set_header_nritems(leaf, nritems + nr);
  	btrfs_mark_buffer_dirty(leaf);
  
  	ret = 0;
  	if (slot == 0) {
  		btrfs_cpu_key_to_disk(&disk_key, cpu_key);
  		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
  	}
  
  	if (btrfs_leaf_free_space(root, leaf) < 0) {
  		btrfs_print_leaf(root, leaf);
  		BUG();
  	}
  out:
  	if (!ret)
  		ret = nr;
  	return ret;
  }
  
  /*
44871b1b2   Chris Mason   Btrfs: reduce sta...
3443
3444
3445
   * this is a helper for btrfs_insert_empty_items, the main goal here is
   * to save stack depth by doing the bulk of the work in a function
   * that doesn't call btrfs_search_slot
74123bd72   Chris Mason   Btrfs: Commenting...
3446
   */
16cdcec73   Miao Xie   btrfs: implement ...
3447
3448
3449
3450
  int setup_items_for_insert(struct btrfs_trans_handle *trans,
  			   struct btrfs_root *root, struct btrfs_path *path,
  			   struct btrfs_key *cpu_key, u32 *data_size,
  			   u32 total_data, u32 total_size, int nr)
be0e5c097   Chris Mason   Btrfs: Initial ch...
3451
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
3452
  	struct btrfs_item *item;
9c58309d6   Chris Mason   Btrfs: Add inode ...
3453
  	int i;
7518a238e   Chris Mason   Btrfs: get/set fo...
3454
  	u32 nritems;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3455
  	unsigned int data_end;
e2fa7227c   Chris Mason   Btrfs: struct key...
3456
  	struct btrfs_disk_key disk_key;
44871b1b2   Chris Mason   Btrfs: reduce sta...
3457
3458
3459
  	int ret;
  	struct extent_buffer *leaf;
  	int slot;
e2fa7227c   Chris Mason   Btrfs: struct key...
3460

5f39d397d   Chris Mason   Btrfs: Create ext...
3461
  	leaf = path->nodes[0];
44871b1b2   Chris Mason   Btrfs: reduce sta...
3462
  	slot = path->slots[0];
74123bd72   Chris Mason   Btrfs: Commenting...
3463

5f39d397d   Chris Mason   Btrfs: Create ext...
3464
  	nritems = btrfs_header_nritems(leaf);
123abc88c   Chris Mason   Btrfs: variable b...
3465
  	data_end = leaf_data_end(root, leaf);
eb60ceac0   Chris Mason   Btrfs: Add backin...
3466

f25956cc5   Chris Mason   Fix leaf overflow...
3467
  	if (btrfs_leaf_free_space(root, leaf) < total_size) {
3326d1b07   Chris Mason   Btrfs: Allow tail...
3468
  		btrfs_print_leaf(root, leaf);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3469
3470
  		printk(KERN_CRIT "not enough freespace need %u have %d
  ",
9c58309d6   Chris Mason   Btrfs: Add inode ...
3471
  		       total_size, btrfs_leaf_free_space(root, leaf));
be0e5c097   Chris Mason   Btrfs: Initial ch...
3472
  		BUG();
d4dbff953   Chris Mason   Btrfs: support fo...
3473
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
3474

be0e5c097   Chris Mason   Btrfs: Initial ch...
3475
  	if (slot != nritems) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3476
  		unsigned int old_data = btrfs_item_end_nr(leaf, slot);
be0e5c097   Chris Mason   Btrfs: Initial ch...
3477

5f39d397d   Chris Mason   Btrfs: Create ext...
3478
3479
  		if (old_data < data_end) {
  			btrfs_print_leaf(root, leaf);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3480
3481
  			printk(KERN_CRIT "slot %d old_data %d data_end %d
  ",
5f39d397d   Chris Mason   Btrfs: Create ext...
3482
3483
3484
  			       slot, old_data, data_end);
  			BUG_ON(1);
  		}
be0e5c097   Chris Mason   Btrfs: Initial ch...
3485
3486
3487
3488
  		/*
  		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
  		 */
  		/* first correct the data pointers */
0783fcfc4   Chris Mason   Btrfs: struct ite...
3489
  		for (i = slot; i < nritems; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3490
  			u32 ioff;
db94535db   Chris Mason   Btrfs: Allow tree...
3491

5f39d397d   Chris Mason   Btrfs: Create ext...
3492
3493
  			item = btrfs_item_nr(leaf, i);
  			ioff = btrfs_item_offset(leaf, item);
9c58309d6   Chris Mason   Btrfs: Add inode ...
3494
  			btrfs_set_item_offset(leaf, item, ioff - total_data);
0783fcfc4   Chris Mason   Btrfs: struct ite...
3495
  		}
be0e5c097   Chris Mason   Btrfs: Initial ch...
3496
  		/* shift the items */
9c58309d6   Chris Mason   Btrfs: Add inode ...
3497
  		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
5f39d397d   Chris Mason   Btrfs: Create ext...
3498
  			      btrfs_item_nr_offset(slot),
d60255795   Chris Mason   Btrfs: corruption...
3499
  			      (nritems - slot) * sizeof(struct btrfs_item));
be0e5c097   Chris Mason   Btrfs: Initial ch...
3500
3501
  
  		/* shift the data */
5f39d397d   Chris Mason   Btrfs: Create ext...
3502
  		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
9c58309d6   Chris Mason   Btrfs: Add inode ...
3503
  			      data_end - total_data, btrfs_leaf_data(leaf) +
d60255795   Chris Mason   Btrfs: corruption...
3504
  			      data_end, old_data - data_end);
be0e5c097   Chris Mason   Btrfs: Initial ch...
3505
3506
  		data_end = old_data;
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
3507

62e2749e0   Chris Mason   Btrfs: Use a chun...
3508
  	/* setup the item for the new data */
9c58309d6   Chris Mason   Btrfs: Add inode ...
3509
3510
3511
3512
3513
3514
3515
3516
  	for (i = 0; i < nr; i++) {
  		btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
  		btrfs_set_item_key(leaf, &disk_key, slot + i);
  		item = btrfs_item_nr(leaf, slot + i);
  		btrfs_set_item_offset(leaf, item, data_end - data_size[i]);
  		data_end -= data_size[i];
  		btrfs_set_item_size(leaf, item, data_size[i]);
  	}
44871b1b2   Chris Mason   Btrfs: reduce sta...
3517

9c58309d6   Chris Mason   Btrfs: Add inode ...
3518
  	btrfs_set_header_nritems(leaf, nritems + nr);
aa5d6bed2   Chris Mason   Btrfs: return cod...
3519
3520
  
  	ret = 0;
5a01a2e3a   Chris Mason   Btrfs: Copy corre...
3521
3522
  	if (slot == 0) {
  		btrfs_cpu_key_to_disk(&disk_key, cpu_key);
e089f05c1   Chris Mason   Btrfs: transactio...
3523
  		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
5a01a2e3a   Chris Mason   Btrfs: Copy corre...
3524
  	}
b9473439d   Chris Mason   Btrfs: leave btre...
3525
3526
  	btrfs_unlock_up_safe(path, 1);
  	btrfs_mark_buffer_dirty(leaf);
aa5d6bed2   Chris Mason   Btrfs: return cod...
3527

5f39d397d   Chris Mason   Btrfs: Create ext...
3528
3529
  	if (btrfs_leaf_free_space(root, leaf) < 0) {
  		btrfs_print_leaf(root, leaf);
be0e5c097   Chris Mason   Btrfs: Initial ch...
3530
  		BUG();
5f39d397d   Chris Mason   Btrfs: Create ext...
3531
  	}
44871b1b2   Chris Mason   Btrfs: reduce sta...
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
  	return ret;
  }
  
  /*
   * Given a key and some data, insert items into the tree.
   * This does all the path init required, making room in the tree if needed.
   */
  int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
  			    struct btrfs_root *root,
  			    struct btrfs_path *path,
  			    struct btrfs_key *cpu_key, u32 *data_size,
  			    int nr)
  {
44871b1b2   Chris Mason   Btrfs: reduce sta...
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
  	int ret = 0;
  	int slot;
  	int i;
  	u32 total_size = 0;
  	u32 total_data = 0;
  
  	for (i = 0; i < nr; i++)
  		total_data += data_size[i];
  
  	total_size = total_data + (nr * sizeof(struct btrfs_item));
  	ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1);
  	if (ret == 0)
  		return -EEXIST;
  	if (ret < 0)
  		goto out;
44871b1b2   Chris Mason   Btrfs: reduce sta...
3560
3561
3562
3563
3564
  	slot = path->slots[0];
  	BUG_ON(slot < 0);
  
  	ret = setup_items_for_insert(trans, root, path, cpu_key, data_size,
  			       total_data, total_size, nr);
ed2ff2cba   Chris Mason   Btrfs: pretend pa...
3565
  out:
62e2749e0   Chris Mason   Btrfs: Use a chun...
3566
3567
3568
3569
3570
3571
3572
  	return ret;
  }
  
  /*
   * Given a key and some data, insert an item into the tree.
   * This does all the path init required, making room in the tree if needed.
   */
e089f05c1   Chris Mason   Btrfs: transactio...
3573
3574
3575
  int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
  		      *root, struct btrfs_key *cpu_key, void *data, u32
  		      data_size)
62e2749e0   Chris Mason   Btrfs: Use a chun...
3576
3577
  {
  	int ret = 0;
2c90e5d65   Chris Mason   Btrfs: still corr...
3578
  	struct btrfs_path *path;
5f39d397d   Chris Mason   Btrfs: Create ext...
3579
3580
  	struct extent_buffer *leaf;
  	unsigned long ptr;
62e2749e0   Chris Mason   Btrfs: Use a chun...
3581

2c90e5d65   Chris Mason   Btrfs: still corr...
3582
  	path = btrfs_alloc_path();
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
3583
3584
  	if (!path)
  		return -ENOMEM;
2c90e5d65   Chris Mason   Btrfs: still corr...
3585
  	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
62e2749e0   Chris Mason   Btrfs: Use a chun...
3586
  	if (!ret) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3587
3588
3589
3590
  		leaf = path->nodes[0];
  		ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
  		write_extent_buffer(leaf, data, ptr, data_size);
  		btrfs_mark_buffer_dirty(leaf);
62e2749e0   Chris Mason   Btrfs: Use a chun...
3591
  	}
2c90e5d65   Chris Mason   Btrfs: still corr...
3592
  	btrfs_free_path(path);
aa5d6bed2   Chris Mason   Btrfs: return cod...
3593
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3594
  }
74123bd72   Chris Mason   Btrfs: Commenting...
3595
  /*
5de08d7d5   Chris Mason   Btrfs: Break up c...
3596
   * delete the pointer from a given node.
74123bd72   Chris Mason   Btrfs: Commenting...
3597
   *
d352ac681   Chris Mason   Btrfs: add and im...
3598
3599
   * the tree should have been previously balanced so the deletion does not
   * empty a node.
74123bd72   Chris Mason   Btrfs: Commenting...
3600
   */
e089f05c1   Chris Mason   Btrfs: transactio...
3601
3602
  static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
  		   struct btrfs_path *path, int level, int slot)
be0e5c097   Chris Mason   Btrfs: Initial ch...
3603
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
3604
  	struct extent_buffer *parent = path->nodes[level];
7518a238e   Chris Mason   Btrfs: get/set fo...
3605
  	u32 nritems;
aa5d6bed2   Chris Mason   Btrfs: return cod...
3606
  	int ret = 0;
bb8039515   Chris Mason   Btrfs: merge on t...
3607
  	int wret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3608

5f39d397d   Chris Mason   Btrfs: Create ext...
3609
  	nritems = btrfs_header_nritems(parent);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3610
  	if (slot != nritems - 1) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3611
3612
3613
  		memmove_extent_buffer(parent,
  			      btrfs_node_key_ptr_offset(slot),
  			      btrfs_node_key_ptr_offset(slot + 1),
d60255795   Chris Mason   Btrfs: corruption...
3614
3615
  			      sizeof(struct btrfs_key_ptr) *
  			      (nritems - slot - 1));
bb8039515   Chris Mason   Btrfs: merge on t...
3616
  	}
7518a238e   Chris Mason   Btrfs: get/set fo...
3617
  	nritems--;
5f39d397d   Chris Mason   Btrfs: Create ext...
3618
  	btrfs_set_header_nritems(parent, nritems);
7518a238e   Chris Mason   Btrfs: get/set fo...
3619
  	if (nritems == 0 && parent == root->node) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3620
  		BUG_ON(btrfs_header_level(root->node) != 1);
bb8039515   Chris Mason   Btrfs: merge on t...
3621
  		/* just turn the root into a leaf and break */
5f39d397d   Chris Mason   Btrfs: Create ext...
3622
  		btrfs_set_header_level(root->node, 0);
bb8039515   Chris Mason   Btrfs: merge on t...
3623
  	} else if (slot == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3624
3625
3626
3627
  		struct btrfs_disk_key disk_key;
  
  		btrfs_node_key(parent, &disk_key, 0);
  		wret = fixup_low_keys(trans, root, path, &disk_key, level + 1);
0f70abe2b   Chris Mason   Btrfs: more retur...
3628
3629
  		if (wret)
  			ret = wret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3630
  	}
d60255795   Chris Mason   Btrfs: corruption...
3631
  	btrfs_mark_buffer_dirty(parent);
aa5d6bed2   Chris Mason   Btrfs: return cod...
3632
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3633
  }
74123bd72   Chris Mason   Btrfs: Commenting...
3634
  /*
323ac95bc   Chris Mason   Btrfs: don't read...
3635
   * a helper function to delete the leaf pointed to by path->slots[1] and
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3636
   * path->nodes[1].
323ac95bc   Chris Mason   Btrfs: don't read...
3637
3638
3639
3640
3641
3642
3643
   *
   * This deletes the pointer in path->nodes[1] and frees the leaf
   * block extent.  zero is returned if it all worked out, < 0 otherwise.
   *
   * The path must have already been setup for deleting the leaf, including
   * all the proper balancing.  path->nodes[1] must be locked.
   */
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3644
3645
3646
3647
  static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
  				   struct btrfs_root *root,
  				   struct btrfs_path *path,
  				   struct extent_buffer *leaf)
323ac95bc   Chris Mason   Btrfs: don't read...
3648
3649
  {
  	int ret;
323ac95bc   Chris Mason   Btrfs: don't read...
3650

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3651
  	WARN_ON(btrfs_header_generation(leaf) != trans->transid);
323ac95bc   Chris Mason   Btrfs: don't read...
3652
3653
3654
  	ret = del_ptr(trans, root, path, 1, path->slots[1]);
  	if (ret)
  		return ret;
4d081c41a   Chris Mason   Btrfs: change btr...
3655
3656
3657
3658
3659
  	/*
  	 * btrfs_free_extent is expensive, we want to make sure we
  	 * aren't holding any locks when we call it
  	 */
  	btrfs_unlock_up_safe(path, 0);
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
3660
3661
3662
3663
  	root_sub_used(root, leaf->len);
  
  	btrfs_free_tree_block(trans, root, leaf, 0, 1);
  	return 0;
323ac95bc   Chris Mason   Btrfs: don't read...
3664
3665
  }
  /*
74123bd72   Chris Mason   Btrfs: Commenting...
3666
3667
3668
   * delete the item at the leaf level in path.  If that empties
   * the leaf, remove it from the tree
   */
85e21bac1   Chris Mason   Btrfs: During del...
3669
3670
  int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
  		    struct btrfs_path *path, int slot, int nr)
be0e5c097   Chris Mason   Btrfs: Initial ch...
3671
  {
5f39d397d   Chris Mason   Btrfs: Create ext...
3672
3673
  	struct extent_buffer *leaf;
  	struct btrfs_item *item;
85e21bac1   Chris Mason   Btrfs: During del...
3674
3675
  	int last_off;
  	int dsize = 0;
aa5d6bed2   Chris Mason   Btrfs: return cod...
3676
3677
  	int ret = 0;
  	int wret;
85e21bac1   Chris Mason   Btrfs: During del...
3678
  	int i;
7518a238e   Chris Mason   Btrfs: get/set fo...
3679
  	u32 nritems;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3680

5f39d397d   Chris Mason   Btrfs: Create ext...
3681
  	leaf = path->nodes[0];
85e21bac1   Chris Mason   Btrfs: During del...
3682
3683
3684
3685
  	last_off = btrfs_item_offset_nr(leaf, slot + nr - 1);
  
  	for (i = 0; i < nr; i++)
  		dsize += btrfs_item_size_nr(leaf, slot + i);
5f39d397d   Chris Mason   Btrfs: Create ext...
3686
  	nritems = btrfs_header_nritems(leaf);
be0e5c097   Chris Mason   Btrfs: Initial ch...
3687

85e21bac1   Chris Mason   Btrfs: During del...
3688
  	if (slot + nr != nritems) {
123abc88c   Chris Mason   Btrfs: variable b...
3689
  		int data_end = leaf_data_end(root, leaf);
5f39d397d   Chris Mason   Btrfs: Create ext...
3690
3691
  
  		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
d60255795   Chris Mason   Btrfs: corruption...
3692
3693
  			      data_end + dsize,
  			      btrfs_leaf_data(leaf) + data_end,
85e21bac1   Chris Mason   Btrfs: During del...
3694
  			      last_off - data_end);
5f39d397d   Chris Mason   Btrfs: Create ext...
3695

85e21bac1   Chris Mason   Btrfs: During del...
3696
  		for (i = slot + nr; i < nritems; i++) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3697
  			u32 ioff;
db94535db   Chris Mason   Btrfs: Allow tree...
3698

5f39d397d   Chris Mason   Btrfs: Create ext...
3699
3700
3701
  			item = btrfs_item_nr(leaf, i);
  			ioff = btrfs_item_offset(leaf, item);
  			btrfs_set_item_offset(leaf, item, ioff + dsize);
0783fcfc4   Chris Mason   Btrfs: struct ite...
3702
  		}
db94535db   Chris Mason   Btrfs: Allow tree...
3703

5f39d397d   Chris Mason   Btrfs: Create ext...
3704
  		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot),
85e21bac1   Chris Mason   Btrfs: During del...
3705
  			      btrfs_item_nr_offset(slot + nr),
d60255795   Chris Mason   Btrfs: corruption...
3706
  			      sizeof(struct btrfs_item) *
85e21bac1   Chris Mason   Btrfs: During del...
3707
  			      (nritems - slot - nr));
be0e5c097   Chris Mason   Btrfs: Initial ch...
3708
  	}
85e21bac1   Chris Mason   Btrfs: During del...
3709
3710
  	btrfs_set_header_nritems(leaf, nritems - nr);
  	nritems -= nr;
5f39d397d   Chris Mason   Btrfs: Create ext...
3711

74123bd72   Chris Mason   Btrfs: Commenting...
3712
  	/* delete the leaf if we've emptied it */
7518a238e   Chris Mason   Btrfs: get/set fo...
3713
  	if (nritems == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3714
3715
  		if (leaf == root->node) {
  			btrfs_set_header_level(leaf, 0);
9a8dd1502   Chris Mason   Btrfs: Block size...
3716
  		} else {
f0486c68e   Yan, Zheng   Btrfs: Introduce ...
3717
3718
  			btrfs_set_path_blocking(path);
  			clean_tree_block(trans, root, leaf);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3719
  			ret = btrfs_del_leaf(trans, root, path, leaf);
323ac95bc   Chris Mason   Btrfs: don't read...
3720
  			BUG_ON(ret);
9a8dd1502   Chris Mason   Btrfs: Block size...
3721
  		}
be0e5c097   Chris Mason   Btrfs: Initial ch...
3722
  	} else {
7518a238e   Chris Mason   Btrfs: get/set fo...
3723
  		int used = leaf_space_used(leaf, 0, nritems);
aa5d6bed2   Chris Mason   Btrfs: return cod...
3724
  		if (slot == 0) {
5f39d397d   Chris Mason   Btrfs: Create ext...
3725
3726
3727
  			struct btrfs_disk_key disk_key;
  
  			btrfs_item_key(leaf, &disk_key, 0);
e089f05c1   Chris Mason   Btrfs: transactio...
3728
  			wret = fixup_low_keys(trans, root, path,
5f39d397d   Chris Mason   Btrfs: Create ext...
3729
  					      &disk_key, 1);
aa5d6bed2   Chris Mason   Btrfs: return cod...
3730
3731
3732
  			if (wret)
  				ret = wret;
  		}
aa5d6bed2   Chris Mason   Btrfs: return cod...
3733

74123bd72   Chris Mason   Btrfs: Commenting...
3734
  		/* delete the leaf if it is mostly empty */
d717aa1d3   Yan Zheng   Btrfs: Avoid dela...
3735
  		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
be0e5c097   Chris Mason   Btrfs: Initial ch...
3736
3737
3738
3739
  			/* push_leaf_left fixes the path.
  			 * make sure the path still points to our leaf
  			 * for possible call to del_ptr below
  			 */
4920c9ac9   Chris Mason   Btrfs: Faster del...
3740
  			slot = path->slots[1];
5f39d397d   Chris Mason   Btrfs: Create ext...
3741
  			extent_buffer_get(leaf);
b9473439d   Chris Mason   Btrfs: leave btre...
3742
  			btrfs_set_path_blocking(path);
99d8f83c9   Chris Mason   Btrfs: fix split_...
3743
3744
  			wret = push_leaf_left(trans, root, path, 1, 1,
  					      1, (u32)-1);
54aa1f4df   Chris Mason   Btrfs: Audit call...
3745
  			if (wret < 0 && wret != -ENOSPC)
aa5d6bed2   Chris Mason   Btrfs: return cod...
3746
  				ret = wret;
5f39d397d   Chris Mason   Btrfs: Create ext...
3747
3748
3749
  
  			if (path->nodes[0] == leaf &&
  			    btrfs_header_nritems(leaf)) {
99d8f83c9   Chris Mason   Btrfs: fix split_...
3750
3751
  				wret = push_leaf_right(trans, root, path, 1,
  						       1, 1, 0);
54aa1f4df   Chris Mason   Btrfs: Audit call...
3752
  				if (wret < 0 && wret != -ENOSPC)
aa5d6bed2   Chris Mason   Btrfs: return cod...
3753
3754
  					ret = wret;
  			}
5f39d397d   Chris Mason   Btrfs: Create ext...
3755
3756
  
  			if (btrfs_header_nritems(leaf) == 0) {
323ac95bc   Chris Mason   Btrfs: don't read...
3757
  				path->slots[1] = slot;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3758
  				ret = btrfs_del_leaf(trans, root, path, leaf);
323ac95bc   Chris Mason   Btrfs: don't read...
3759
  				BUG_ON(ret);
5f39d397d   Chris Mason   Btrfs: Create ext...
3760
  				free_extent_buffer(leaf);
5de08d7d5   Chris Mason   Btrfs: Break up c...
3761
  			} else {
925baeddc   Chris Mason   Btrfs: Start btre...
3762
3763
3764
3765
3766
3767
3768
  				/* if we're still in the path, make sure
  				 * we're dirty.  Otherwise, one of the
  				 * push_leaf functions must have already
  				 * dirtied this buffer
  				 */
  				if (path->nodes[0] == leaf)
  					btrfs_mark_buffer_dirty(leaf);
5f39d397d   Chris Mason   Btrfs: Create ext...
3769
  				free_extent_buffer(leaf);
be0e5c097   Chris Mason   Btrfs: Initial ch...
3770
  			}
d57197629   Chris Mason   btrfs_create, btr...
3771
  		} else {
5f39d397d   Chris Mason   Btrfs: Create ext...
3772
  			btrfs_mark_buffer_dirty(leaf);
be0e5c097   Chris Mason   Btrfs: Initial ch...
3773
3774
  		}
  	}
aa5d6bed2   Chris Mason   Btrfs: return cod...
3775
  	return ret;
be0e5c097   Chris Mason   Btrfs: Initial ch...
3776
  }
97571fd0c   Chris Mason   Btrfs: cleanup & ...
3777
  /*
925baeddc   Chris Mason   Btrfs: Start btre...
3778
   * search the tree again to find a leaf with lesser keys
7bb86316c   Chris Mason   Btrfs: Add back p...
3779
3780
   * returns 0 if it found something or 1 if there are no lesser leaves.
   * returns < 0 on io errors.
d352ac681   Chris Mason   Btrfs: add and im...
3781
3782
3783
   *
   * This may release the path, and so you may lose any locks held at the
   * time you call it.
7bb86316c   Chris Mason   Btrfs: Add back p...
3784
3785
3786
   */
  int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
  {
925baeddc   Chris Mason   Btrfs: Start btre...
3787
3788
3789
  	struct btrfs_key key;
  	struct btrfs_disk_key found_key;
  	int ret;
7bb86316c   Chris Mason   Btrfs: Add back p...
3790

925baeddc   Chris Mason   Btrfs: Start btre...
3791
  	btrfs_item_key_to_cpu(path->nodes[0], &key, 0);
7bb86316c   Chris Mason   Btrfs: Add back p...
3792

925baeddc   Chris Mason   Btrfs: Start btre...
3793
3794
3795
3796
3797
3798
3799
3800
  	if (key.offset > 0)
  		key.offset--;
  	else if (key.type > 0)
  		key.type--;
  	else if (key.objectid > 0)
  		key.objectid--;
  	else
  		return 1;
7bb86316c   Chris Mason   Btrfs: Add back p...
3801

b3b4aa74b   David Sterba   btrfs: drop unuse...
3802
  	btrfs_release_path(path);
925baeddc   Chris Mason   Btrfs: Start btre...
3803
3804
3805
3806
3807
3808
3809
3810
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0)
  		return ret;
  	btrfs_item_key(path->nodes[0], &found_key, 0);
  	ret = comp_keys(&found_key, &key);
  	if (ret < 0)
  		return 0;
  	return 1;
7bb86316c   Chris Mason   Btrfs: Add back p...
3811
  }
3f157a2fd   Chris Mason   Btrfs: Online btr...
3812
3813
3814
  /*
   * A helper function to walk down the tree starting at min_key, and looking
   * for nodes or leaves that are either in cache or have a minimum
d352ac681   Chris Mason   Btrfs: add and im...
3815
   * transaction id.  This is used by the btree defrag code, and tree logging
3f157a2fd   Chris Mason   Btrfs: Online btr...
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
   *
   * This does not cow, but it does stuff the starting key it finds back
   * into min_key, so you can call btrfs_search_slot with cow=1 on the
   * key and get a writable path.
   *
   * This does lock as it descends, and path->keep_locks should be set
   * to 1 by the caller.
   *
   * This honors path->lowest_level to prevent descent past a given level
   * of the tree.
   *
d352ac681   Chris Mason   Btrfs: add and im...
3827
3828
3829
3830
   * min_trans indicates the oldest transaction that you are interested
   * in walking through.  Any nodes or leaves older than min_trans are
   * skipped over (without reading them).
   *
3f157a2fd   Chris Mason   Btrfs: Online btr...
3831
3832
3833
3834
   * returns zero if something useful was found, < 0 on error and 1 if there
   * was nothing in the tree that matched the search criteria.
   */
  int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
e02119d5a   Chris Mason   Btrfs: Add a writ...
3835
  			 struct btrfs_key *max_key,
3f157a2fd   Chris Mason   Btrfs: Online btr...
3836
3837
3838
3839
3840
3841
  			 struct btrfs_path *path, int cache_only,
  			 u64 min_trans)
  {
  	struct extent_buffer *cur;
  	struct btrfs_key found_key;
  	int slot;
9652480bf   Yan   Fix path slots se...
3842
  	int sret;
3f157a2fd   Chris Mason   Btrfs: Online btr...
3843
3844
3845
  	u32 nritems;
  	int level;
  	int ret = 1;
934d375ba   Chris Mason   Btrfs: Use map_pr...
3846
  	WARN_ON(!path->keep_locks);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3847
  again:
bd681513f   Chris Mason   Btrfs: switch the...
3848
  	cur = btrfs_read_lock_root_node(root);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3849
  	level = btrfs_header_level(cur);
e02119d5a   Chris Mason   Btrfs: Add a writ...
3850
  	WARN_ON(path->nodes[level]);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3851
  	path->nodes[level] = cur;
bd681513f   Chris Mason   Btrfs: switch the...
3852
  	path->locks[level] = BTRFS_READ_LOCK;
3f157a2fd   Chris Mason   Btrfs: Online btr...
3853
3854
3855
3856
3857
  
  	if (btrfs_header_generation(cur) < min_trans) {
  		ret = 1;
  		goto out;
  	}
d397712bc   Chris Mason   Btrfs: Fix checkp...
3858
  	while (1) {
3f157a2fd   Chris Mason   Btrfs: Online btr...
3859
3860
  		nritems = btrfs_header_nritems(cur);
  		level = btrfs_header_level(cur);
9652480bf   Yan   Fix path slots se...
3861
  		sret = bin_search(cur, min_key, level, &slot);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3862

323ac95bc   Chris Mason   Btrfs: don't read...
3863
3864
  		/* at the lowest level, we're done, setup the path and exit */
  		if (level == path->lowest_level) {
e02119d5a   Chris Mason   Btrfs: Add a writ...
3865
3866
  			if (slot >= nritems)
  				goto find_next_key;
3f157a2fd   Chris Mason   Btrfs: Online btr...
3867
3868
3869
3870
3871
  			ret = 0;
  			path->slots[level] = slot;
  			btrfs_item_key_to_cpu(cur, &found_key, slot);
  			goto out;
  		}
9652480bf   Yan   Fix path slots se...
3872
3873
  		if (sret && slot > 0)
  			slot--;
3f157a2fd   Chris Mason   Btrfs: Online btr...
3874
3875
3876
3877
3878
  		/*
  		 * check this node pointer against the cache_only and
  		 * min_trans parameters.  If it isn't in cache or is too
  		 * old, skip to the next one.
  		 */
d397712bc   Chris Mason   Btrfs: Fix checkp...
3879
  		while (slot < nritems) {
3f157a2fd   Chris Mason   Btrfs: Online btr...
3880
3881
3882
  			u64 blockptr;
  			u64 gen;
  			struct extent_buffer *tmp;
e02119d5a   Chris Mason   Btrfs: Add a writ...
3883
  			struct btrfs_disk_key disk_key;
3f157a2fd   Chris Mason   Btrfs: Online btr...
3884
3885
3886
3887
3888
3889
3890
3891
  			blockptr = btrfs_node_blockptr(cur, slot);
  			gen = btrfs_node_ptr_generation(cur, slot);
  			if (gen < min_trans) {
  				slot++;
  				continue;
  			}
  			if (!cache_only)
  				break;
e02119d5a   Chris Mason   Btrfs: Add a writ...
3892
3893
3894
3895
3896
3897
3898
  			if (max_key) {
  				btrfs_node_key(cur, &disk_key, slot);
  				if (comp_keys(&disk_key, max_key) >= 0) {
  					ret = 1;
  					goto out;
  				}
  			}
3f157a2fd   Chris Mason   Btrfs: Online btr...
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
  			tmp = btrfs_find_tree_block(root, blockptr,
  					    btrfs_level_size(root, level - 1));
  
  			if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
  				free_extent_buffer(tmp);
  				break;
  			}
  			if (tmp)
  				free_extent_buffer(tmp);
  			slot++;
  		}
e02119d5a   Chris Mason   Btrfs: Add a writ...
3910
  find_next_key:
3f157a2fd   Chris Mason   Btrfs: Online btr...
3911
3912
3913
3914
3915
  		/*
  		 * we didn't find a candidate key in this node, walk forward
  		 * and find another one
  		 */
  		if (slot >= nritems) {
e02119d5a   Chris Mason   Btrfs: Add a writ...
3916
  			path->slots[level] = slot;
b4ce94de9   Chris Mason   Btrfs: Change btr...
3917
  			btrfs_set_path_blocking(path);
e02119d5a   Chris Mason   Btrfs: Add a writ...
3918
  			sret = btrfs_find_next_key(root, path, min_key, level,
3f157a2fd   Chris Mason   Btrfs: Online btr...
3919
  						  cache_only, min_trans);
e02119d5a   Chris Mason   Btrfs: Add a writ...
3920
  			if (sret == 0) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
3921
  				btrfs_release_path(path);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
  				goto again;
  			} else {
  				goto out;
  			}
  		}
  		/* save our key for returning back */
  		btrfs_node_key_to_cpu(cur, &found_key, slot);
  		path->slots[level] = slot;
  		if (level == path->lowest_level) {
  			ret = 0;
  			unlock_up(path, level, 1);
  			goto out;
  		}
b4ce94de9   Chris Mason   Btrfs: Change btr...
3935
  		btrfs_set_path_blocking(path);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3936
  		cur = read_node_slot(root, cur, slot);
97d9a8a42   Tsutomu Itoh   Btrfs: check retu...
3937
  		BUG_ON(!cur);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3938

bd681513f   Chris Mason   Btrfs: switch the...
3939
  		btrfs_tree_read_lock(cur);
b4ce94de9   Chris Mason   Btrfs: Change btr...
3940

bd681513f   Chris Mason   Btrfs: switch the...
3941
  		path->locks[level - 1] = BTRFS_READ_LOCK;
3f157a2fd   Chris Mason   Btrfs: Online btr...
3942
3943
  		path->nodes[level - 1] = cur;
  		unlock_up(path, level, 1);
bd681513f   Chris Mason   Btrfs: switch the...
3944
  		btrfs_clear_path_blocking(path, NULL, 0);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3945
3946
3947
3948
  	}
  out:
  	if (ret == 0)
  		memcpy(min_key, &found_key, sizeof(found_key));
b4ce94de9   Chris Mason   Btrfs: Change btr...
3949
  	btrfs_set_path_blocking(path);
3f157a2fd   Chris Mason   Btrfs: Online btr...
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
  	return ret;
  }
  
  /*
   * this is similar to btrfs_next_leaf, but does not try to preserve
   * and fixup the path.  It looks for and returns the next key in the
   * tree based on the current path and the cache_only and min_trans
   * parameters.
   *
   * 0 is returned if another key is found, < 0 if there are any errors
   * and 1 is returned if there are no higher keys in the tree
   *
   * path->keep_locks should be set to 1 on the search made before
   * calling this function.
   */
e7a84565b   Chris Mason   Btrfs: Add btree ...
3965
  int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
33c66f430   Yan Zheng   Btrfs: fix lockin...
3966
  			struct btrfs_key *key, int level,
3f157a2fd   Chris Mason   Btrfs: Online btr...
3967
  			int cache_only, u64 min_trans)
e7a84565b   Chris Mason   Btrfs: Add btree ...
3968
  {
e7a84565b   Chris Mason   Btrfs: Add btree ...
3969
3970
  	int slot;
  	struct extent_buffer *c;
934d375ba   Chris Mason   Btrfs: Use map_pr...
3971
  	WARN_ON(!path->keep_locks);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3972
  	while (level < BTRFS_MAX_LEVEL) {
e7a84565b   Chris Mason   Btrfs: Add btree ...
3973
3974
3975
3976
3977
  		if (!path->nodes[level])
  			return 1;
  
  		slot = path->slots[level] + 1;
  		c = path->nodes[level];
3f157a2fd   Chris Mason   Btrfs: Online btr...
3978
  next:
e7a84565b   Chris Mason   Btrfs: Add btree ...
3979
  		if (slot >= btrfs_header_nritems(c)) {
33c66f430   Yan Zheng   Btrfs: fix lockin...
3980
3981
3982
3983
3984
  			int ret;
  			int orig_lowest;
  			struct btrfs_key cur_key;
  			if (level + 1 >= BTRFS_MAX_LEVEL ||
  			    !path->nodes[level + 1])
e7a84565b   Chris Mason   Btrfs: Add btree ...
3985
  				return 1;
33c66f430   Yan Zheng   Btrfs: fix lockin...
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
  
  			if (path->locks[level + 1]) {
  				level++;
  				continue;
  			}
  
  			slot = btrfs_header_nritems(c) - 1;
  			if (level == 0)
  				btrfs_item_key_to_cpu(c, &cur_key, slot);
  			else
  				btrfs_node_key_to_cpu(c, &cur_key, slot);
  
  			orig_lowest = path->lowest_level;
b3b4aa74b   David Sterba   btrfs: drop unuse...
3999
  			btrfs_release_path(path);
33c66f430   Yan Zheng   Btrfs: fix lockin...
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
  			path->lowest_level = level;
  			ret = btrfs_search_slot(NULL, root, &cur_key, path,
  						0, 0);
  			path->lowest_level = orig_lowest;
  			if (ret < 0)
  				return ret;
  
  			c = path->nodes[level];
  			slot = path->slots[level];
  			if (ret == 0)
  				slot++;
  			goto next;
e7a84565b   Chris Mason   Btrfs: Add btree ...
4012
  		}
33c66f430   Yan Zheng   Btrfs: fix lockin...
4013

e7a84565b   Chris Mason   Btrfs: Add btree ...
4014
4015
  		if (level == 0)
  			btrfs_item_key_to_cpu(c, key, slot);
3f157a2fd   Chris Mason   Btrfs: Online btr...
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
  		else {
  			u64 blockptr = btrfs_node_blockptr(c, slot);
  			u64 gen = btrfs_node_ptr_generation(c, slot);
  
  			if (cache_only) {
  				struct extent_buffer *cur;
  				cur = btrfs_find_tree_block(root, blockptr,
  					    btrfs_level_size(root, level - 1));
  				if (!cur || !btrfs_buffer_uptodate(cur, gen)) {
  					slot++;
  					if (cur)
  						free_extent_buffer(cur);
  					goto next;
  				}
  				free_extent_buffer(cur);
  			}
  			if (gen < min_trans) {
  				slot++;
  				goto next;
  			}
e7a84565b   Chris Mason   Btrfs: Add btree ...
4036
  			btrfs_node_key_to_cpu(c, key, slot);
3f157a2fd   Chris Mason   Btrfs: Online btr...
4037
  		}
e7a84565b   Chris Mason   Btrfs: Add btree ...
4038
4039
4040
4041
  		return 0;
  	}
  	return 1;
  }
7bb86316c   Chris Mason   Btrfs: Add back p...
4042
  /*
925baeddc   Chris Mason   Btrfs: Start btre...
4043
   * search the tree again to find a leaf with greater keys
0f70abe2b   Chris Mason   Btrfs: more retur...
4044
4045
   * returns 0 if it found something or 1 if there are no greater leaves.
   * returns < 0 on io errors.
97571fd0c   Chris Mason   Btrfs: cleanup & ...
4046
   */
234b63a09   Chris Mason   rename funcs and ...
4047
  int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
d97e63b69   Chris Mason   Btrfs: early exte...
4048
4049
  {
  	int slot;
8e73f2750   Chris Mason   Btrfs: Optimize l...
4050
  	int level;
5f39d397d   Chris Mason   Btrfs: Create ext...
4051
  	struct extent_buffer *c;
8e73f2750   Chris Mason   Btrfs: Optimize l...
4052
  	struct extent_buffer *next;
925baeddc   Chris Mason   Btrfs: Start btre...
4053
4054
4055
  	struct btrfs_key key;
  	u32 nritems;
  	int ret;
8e73f2750   Chris Mason   Btrfs: Optimize l...
4056
  	int old_spinning = path->leave_spinning;
bd681513f   Chris Mason   Btrfs: switch the...
4057
  	int next_rw_lock = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
4058
4059
  
  	nritems = btrfs_header_nritems(path->nodes[0]);
d397712bc   Chris Mason   Btrfs: Fix checkp...
4060
  	if (nritems == 0)
925baeddc   Chris Mason   Btrfs: Start btre...
4061
  		return 1;
925baeddc   Chris Mason   Btrfs: Start btre...
4062

8e73f2750   Chris Mason   Btrfs: Optimize l...
4063
4064
4065
4066
  	btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
  again:
  	level = 1;
  	next = NULL;
bd681513f   Chris Mason   Btrfs: switch the...
4067
  	next_rw_lock = 0;
b3b4aa74b   David Sterba   btrfs: drop unuse...
4068
  	btrfs_release_path(path);
8e73f2750   Chris Mason   Btrfs: Optimize l...
4069

a21350115   Chris Mason   Btrfs: Replace th...
4070
  	path->keep_locks = 1;
31533fb26   Chris Mason   Btrfs: remove loc...
4071
  	path->leave_spinning = 1;
8e73f2750   Chris Mason   Btrfs: Optimize l...
4072

925baeddc   Chris Mason   Btrfs: Start btre...
4073
4074
4075
4076
4077
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	path->keep_locks = 0;
  
  	if (ret < 0)
  		return ret;
a21350115   Chris Mason   Btrfs: Replace th...
4078
  	nritems = btrfs_header_nritems(path->nodes[0]);
168fd7d27   Chris Mason   Fix btrfs_next_le...
4079
4080
4081
4082
4083
4084
  	/*
  	 * by releasing the path above we dropped all our locks.  A balance
  	 * could have added more items next to the key that used to be
  	 * at the very end of the block.  So, check again here and
  	 * advance the path if there are now more items available.
  	 */
a21350115   Chris Mason   Btrfs: Replace th...
4085
  	if (nritems > 0 && path->slots[0] < nritems - 1) {
e457afec6   Yan Zheng   Btrfs: fix double...
4086
4087
  		if (ret == 0)
  			path->slots[0]++;
8e73f2750   Chris Mason   Btrfs: Optimize l...
4088
  		ret = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
4089
4090
  		goto done;
  	}
d97e63b69   Chris Mason   Btrfs: early exte...
4091

d397712bc   Chris Mason   Btrfs: Fix checkp...
4092
  	while (level < BTRFS_MAX_LEVEL) {
8e73f2750   Chris Mason   Btrfs: Optimize l...
4093
4094
4095
4096
  		if (!path->nodes[level]) {
  			ret = 1;
  			goto done;
  		}
5f39d397d   Chris Mason   Btrfs: Create ext...
4097

d97e63b69   Chris Mason   Btrfs: early exte...
4098
4099
  		slot = path->slots[level] + 1;
  		c = path->nodes[level];
5f39d397d   Chris Mason   Btrfs: Create ext...
4100
  		if (slot >= btrfs_header_nritems(c)) {
d97e63b69   Chris Mason   Btrfs: early exte...
4101
  			level++;
8e73f2750   Chris Mason   Btrfs: Optimize l...
4102
4103
4104
4105
  			if (level == BTRFS_MAX_LEVEL) {
  				ret = 1;
  				goto done;
  			}
d97e63b69   Chris Mason   Btrfs: early exte...
4106
4107
  			continue;
  		}
5f39d397d   Chris Mason   Btrfs: Create ext...
4108

925baeddc   Chris Mason   Btrfs: Start btre...
4109
  		if (next) {
bd681513f   Chris Mason   Btrfs: switch the...
4110
  			btrfs_tree_unlock_rw(next, next_rw_lock);
5f39d397d   Chris Mason   Btrfs: Create ext...
4111
  			free_extent_buffer(next);
925baeddc   Chris Mason   Btrfs: Start btre...
4112
  		}
5f39d397d   Chris Mason   Btrfs: Create ext...
4113

8e73f2750   Chris Mason   Btrfs: Optimize l...
4114
  		next = c;
bd681513f   Chris Mason   Btrfs: switch the...
4115
  		next_rw_lock = path->locks[level];
8e73f2750   Chris Mason   Btrfs: Optimize l...
4116
4117
4118
4119
  		ret = read_block_for_search(NULL, root, path, &next, level,
  					    slot, &key);
  		if (ret == -EAGAIN)
  			goto again;
5f39d397d   Chris Mason   Btrfs: Create ext...
4120

76a05b35a   Chris Mason   Btrfs: Don't loop...
4121
  		if (ret < 0) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
4122
  			btrfs_release_path(path);
76a05b35a   Chris Mason   Btrfs: Don't loop...
4123
4124
  			goto done;
  		}
5cd57b2cb   Chris Mason   Btrfs: Add a skip...
4125
  		if (!path->skip_locking) {
bd681513f   Chris Mason   Btrfs: switch the...
4126
  			ret = btrfs_try_tree_read_lock(next);
8e73f2750   Chris Mason   Btrfs: Optimize l...
4127
4128
  			if (!ret) {
  				btrfs_set_path_blocking(path);
bd681513f   Chris Mason   Btrfs: switch the...
4129
  				btrfs_tree_read_lock(next);
31533fb26   Chris Mason   Btrfs: remove loc...
4130
  				btrfs_clear_path_blocking(path, next,
bd681513f   Chris Mason   Btrfs: switch the...
4131
  							  BTRFS_READ_LOCK);
8e73f2750   Chris Mason   Btrfs: Optimize l...
4132
  			}
31533fb26   Chris Mason   Btrfs: remove loc...
4133
  			next_rw_lock = BTRFS_READ_LOCK;
5cd57b2cb   Chris Mason   Btrfs: Add a skip...
4134
  		}
d97e63b69   Chris Mason   Btrfs: early exte...
4135
4136
4137
  		break;
  	}
  	path->slots[level] = slot;
d397712bc   Chris Mason   Btrfs: Fix checkp...
4138
  	while (1) {
d97e63b69   Chris Mason   Btrfs: early exte...
4139
4140
  		level--;
  		c = path->nodes[level];
925baeddc   Chris Mason   Btrfs: Start btre...
4141
  		if (path->locks[level])
bd681513f   Chris Mason   Btrfs: switch the...
4142
  			btrfs_tree_unlock_rw(c, path->locks[level]);
8e73f2750   Chris Mason   Btrfs: Optimize l...
4143

5f39d397d   Chris Mason   Btrfs: Create ext...
4144
  		free_extent_buffer(c);
d97e63b69   Chris Mason   Btrfs: early exte...
4145
4146
  		path->nodes[level] = next;
  		path->slots[level] = 0;
a74a4b97b   Chris Mason   Btrfs: Replace th...
4147
  		if (!path->skip_locking)
bd681513f   Chris Mason   Btrfs: switch the...
4148
  			path->locks[level] = next_rw_lock;
d97e63b69   Chris Mason   Btrfs: early exte...
4149
4150
  		if (!level)
  			break;
b4ce94de9   Chris Mason   Btrfs: Change btr...
4151

8e73f2750   Chris Mason   Btrfs: Optimize l...
4152
4153
4154
4155
  		ret = read_block_for_search(NULL, root, path, &next, level,
  					    0, &key);
  		if (ret == -EAGAIN)
  			goto again;
76a05b35a   Chris Mason   Btrfs: Don't loop...
4156
  		if (ret < 0) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
4157
  			btrfs_release_path(path);
76a05b35a   Chris Mason   Btrfs: Don't loop...
4158
4159
  			goto done;
  		}
5cd57b2cb   Chris Mason   Btrfs: Add a skip...
4160
  		if (!path->skip_locking) {
bd681513f   Chris Mason   Btrfs: switch the...
4161
  			ret = btrfs_try_tree_read_lock(next);
8e73f2750   Chris Mason   Btrfs: Optimize l...
4162
4163
  			if (!ret) {
  				btrfs_set_path_blocking(path);
bd681513f   Chris Mason   Btrfs: switch the...
4164
  				btrfs_tree_read_lock(next);
31533fb26   Chris Mason   Btrfs: remove loc...
4165
  				btrfs_clear_path_blocking(path, next,
bd681513f   Chris Mason   Btrfs: switch the...
4166
4167
  							  BTRFS_READ_LOCK);
  			}
31533fb26   Chris Mason   Btrfs: remove loc...
4168
  			next_rw_lock = BTRFS_READ_LOCK;
5cd57b2cb   Chris Mason   Btrfs: Add a skip...
4169
  		}
d97e63b69   Chris Mason   Btrfs: early exte...
4170
  	}
8e73f2750   Chris Mason   Btrfs: Optimize l...
4171
  	ret = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
4172
4173
  done:
  	unlock_up(path, 0, 1);
8e73f2750   Chris Mason   Btrfs: Optimize l...
4174
4175
4176
4177
4178
  	path->leave_spinning = old_spinning;
  	if (!old_spinning)
  		btrfs_set_path_blocking(path);
  
  	return ret;
d97e63b69   Chris Mason   Btrfs: early exte...
4179
  }
0b86a832a   Chris Mason   Btrfs: Add suppor...
4180

3f157a2fd   Chris Mason   Btrfs: Online btr...
4181
4182
4183
4184
4185
4186
  /*
   * this uses btrfs_prev_leaf to walk backwards in the tree, and keeps
   * searching until it gets past min_objectid or finds an item of 'type'
   *
   * returns 0 if something is found, 1 if nothing was found and < 0 on error
   */
0b86a832a   Chris Mason   Btrfs: Add suppor...
4187
4188
4189
4190
4191
4192
  int btrfs_previous_item(struct btrfs_root *root,
  			struct btrfs_path *path, u64 min_objectid,
  			int type)
  {
  	struct btrfs_key found_key;
  	struct extent_buffer *leaf;
e02119d5a   Chris Mason   Btrfs: Add a writ...
4193
  	u32 nritems;
0b86a832a   Chris Mason   Btrfs: Add suppor...
4194
  	int ret;
d397712bc   Chris Mason   Btrfs: Fix checkp...
4195
  	while (1) {
0b86a832a   Chris Mason   Btrfs: Add suppor...
4196
  		if (path->slots[0] == 0) {
b4ce94de9   Chris Mason   Btrfs: Change btr...
4197
  			btrfs_set_path_blocking(path);
0b86a832a   Chris Mason   Btrfs: Add suppor...
4198
4199
4200
4201
4202
4203
4204
  			ret = btrfs_prev_leaf(root, path);
  			if (ret != 0)
  				return ret;
  		} else {
  			path->slots[0]--;
  		}
  		leaf = path->nodes[0];
e02119d5a   Chris Mason   Btrfs: Add a writ...
4205
4206
4207
4208
4209
  		nritems = btrfs_header_nritems(leaf);
  		if (nritems == 0)
  			return 1;
  		if (path->slots[0] == nritems)
  			path->slots[0]--;
0b86a832a   Chris Mason   Btrfs: Add suppor...
4210
  		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
e02119d5a   Chris Mason   Btrfs: Add a writ...
4211
4212
  		if (found_key.objectid < min_objectid)
  			break;
0a4eefbb7   Yan Zheng   Btrfs: Fix orderi...
4213
4214
  		if (found_key.type == type)
  			return 0;
e02119d5a   Chris Mason   Btrfs: Add a writ...
4215
4216
4217
  		if (found_key.objectid == min_objectid &&
  		    found_key.type < type)
  			break;
0b86a832a   Chris Mason   Btrfs: Add suppor...
4218
4219
4220
  	}
  	return 1;
  }