Blame view

fs/xfs/xfs_alloc_btree.c 11.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
7b7187698   Nathan Scott   [XFS] Update lice...
2
3
   * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
7b7187698   Nathan Scott   [XFS] Update lice...
5
6
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   * published by the Free Software Foundation.
   *
7b7187698   Nathan Scott   [XFS] Update lice...
9
10
11
12
   * This program is distributed in the hope that it would 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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   *
7b7187698   Nathan Scott   [XFS] Update lice...
14
15
16
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write the Free Software Foundation,
   * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include "xfs.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
19
  #include "xfs_fs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include "xfs_types.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
21
  #include "xfs_bit.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include "xfs_log.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
23
  #include "xfs_inum.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
  #include "xfs_trans.h"
  #include "xfs_sb.h"
  #include "xfs_ag.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include "xfs_mount.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
28
  #include "xfs_bmap_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
  #include "xfs_alloc_btree.h"
  #include "xfs_ialloc_btree.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
31
32
  #include "xfs_dinode.h"
  #include "xfs_inode.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include "xfs_btree.h"
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
34
  #include "xfs_btree_trace.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
  #include "xfs_alloc.h"
  #include "xfs_error.h"
0b1b213fc   Christoph Hellwig   xfs: event tracin...
37
  #include "xfs_trace.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

278d0ca14   Christoph Hellwig   [XFS] implement g...
40
41
42
43
44
45
46
47
  STATIC struct xfs_btree_cur *
  xfs_allocbt_dup_cursor(
  	struct xfs_btree_cur	*cur)
  {
  	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
  			cur->bc_private.a.agbp, cur->bc_private.a.agno,
  			cur->bc_btnum);
  }
344207ce8   Christoph Hellwig   [XFS] implement s...
48
49
50
51
52
53
54
55
56
57
  STATIC void
  xfs_allocbt_set_root(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_ptr	*ptr,
  	int			inc)
  {
  	struct xfs_buf		*agbp = cur->bc_private.a.agbp;
  	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
  	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno);
  	int			btnum = cur->bc_btnum;
a862e0fdc   Dave Chinner   xfs: Don't direct...
58
  	struct xfs_perag	*pag = xfs_perag_get(cur->bc_mp, seqno);
344207ce8   Christoph Hellwig   [XFS] implement s...
59
60
61
62
63
  
  	ASSERT(ptr->s != 0);
  
  	agf->agf_roots[btnum] = ptr->s;
  	be32_add_cpu(&agf->agf_levels[btnum], inc);
a862e0fdc   Dave Chinner   xfs: Don't direct...
64
65
  	pag->pagf_levels[btnum] += inc;
  	xfs_perag_put(pag);
344207ce8   Christoph Hellwig   [XFS] implement s...
66
67
68
  
  	xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
  }
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  STATIC int
  xfs_allocbt_alloc_block(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_ptr	*start,
  	union xfs_btree_ptr	*new,
  	int			length,
  	int			*stat)
  {
  	int			error;
  	xfs_agblock_t		bno;
  
  	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
  
  	/* Allocate the new block from the freelist. If we can't, give up.  */
  	error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
  				       &bno, 1);
  	if (error) {
  		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
  		return error;
  	}
  
  	if (bno == NULLAGBLOCK) {
  		XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
  		*stat = 0;
  		return 0;
  	}
  
  	xfs_trans_agbtree_delta(cur->bc_tp, 1);
  	new->s = cpu_to_be32(bno);
  
  	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
  	*stat = 1;
  	return 0;
  }
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
103
104
105
106
107
108
109
110
111
  STATIC int
  xfs_allocbt_free_block(
  	struct xfs_btree_cur	*cur,
  	struct xfs_buf		*bp)
  {
  	struct xfs_buf		*agbp = cur->bc_private.a.agbp;
  	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
  	xfs_agblock_t		bno;
  	int			error;
b6e322273   Eric Sandeen   [XFS] Remove the ...
112
  	bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp));
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1);
  	if (error)
  		return error;
  
  	/*
  	 * Since blocks move to the free list without the coordination used in
  	 * xfs_bmap_finish, we can't allow block to be available for
  	 * reallocation and non-transaction writing (user data) until we know
  	 * that the transaction that moved it to the free list is permanently
  	 * on disk. We track the blocks by declaring these blocks as "busy";
  	 * the busy list is maintained on a per-ag basis and each transaction
  	 * records which entries should be removed when the iclog commits to
  	 * disk. If a busy block is allocated, the iclog is pushed up to the
  	 * LSN that freed the block.
  	 */
ed3b4d6cd   Dave Chinner   xfs: Improve scal...
128
  	xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1);
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
129
130
131
  	xfs_trans_agbtree_delta(cur->bc_tp, -1);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  /*
278d0ca14   Christoph Hellwig   [XFS] implement g...
133
   * Update the longest extent in the AGF
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
   */
278d0ca14   Christoph Hellwig   [XFS] implement g...
135
136
137
138
139
140
141
  STATIC void
  xfs_allocbt_update_lastrec(
  	struct xfs_btree_cur	*cur,
  	struct xfs_btree_block	*block,
  	union xfs_btree_rec	*rec,
  	int			ptr,
  	int			reason)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  {
278d0ca14   Christoph Hellwig   [XFS] implement g...
143
144
  	struct xfs_agf		*agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
  	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno);
a862e0fdc   Dave Chinner   xfs: Don't direct...
145
  	struct xfs_perag	*pag;
278d0ca14   Christoph Hellwig   [XFS] implement g...
146
  	__be32			len;
91cca5df9   Christoph Hellwig   [XFS] implement g...
147
  	int			numrecs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

278d0ca14   Christoph Hellwig   [XFS] implement g...
149
  	ASSERT(cur->bc_btnum == XFS_BTNUM_CNT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150

278d0ca14   Christoph Hellwig   [XFS] implement g...
151
152
  	switch (reason) {
  	case LASTREC_UPDATE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  		/*
278d0ca14   Christoph Hellwig   [XFS] implement g...
154
155
  		 * If this is the last leaf block and it's the last record,
  		 * then update the size of the longest extent in the AG.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  		 */
278d0ca14   Christoph Hellwig   [XFS] implement g...
157
158
159
160
  		if (ptr != xfs_btree_get_numrecs(block))
  			return;
  		len = rec->alloc.ar_blockcount;
  		break;
4b22a5718   Christoph Hellwig   [XFS] implement g...
161
162
163
164
165
166
  	case LASTREC_INSREC:
  		if (be32_to_cpu(rec->alloc.ar_blockcount) <=
  		    be32_to_cpu(agf->agf_longest))
  			return;
  		len = rec->alloc.ar_blockcount;
  		break;
91cca5df9   Christoph Hellwig   [XFS] implement g...
167
168
169
170
171
172
173
174
  	case LASTREC_DELREC:
  		numrecs = xfs_btree_get_numrecs(block);
  		if (ptr <= numrecs)
  			return;
  		ASSERT(ptr == numrecs + 1);
  
  		if (numrecs) {
  			xfs_alloc_rec_t *rrp;
136341b41   Christoph Hellwig   [XFS] cleanup btr...
175
  			rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs);
91cca5df9   Christoph Hellwig   [XFS] implement g...
176
177
178
179
180
181
  			len = rrp->ar_blockcount;
  		} else {
  			len = 0;
  		}
  
  		break;
278d0ca14   Christoph Hellwig   [XFS] implement g...
182
183
184
  	default:
  		ASSERT(0);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  	}
561f7d173   Christoph Hellwig   [XFS] split up xf...
186

278d0ca14   Christoph Hellwig   [XFS] implement g...
187
  	agf->agf_longest = len;
a862e0fdc   Dave Chinner   xfs: Don't direct...
188
189
190
  	pag = xfs_perag_get(cur->bc_mp, seqno);
  	pag->pagf_longest = be32_to_cpu(len);
  	xfs_perag_put(pag);
278d0ca14   Christoph Hellwig   [XFS] implement g...
191
  	xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST);
561f7d173   Christoph Hellwig   [XFS] split up xf...
192
  }
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
193
  STATIC int
91cca5df9   Christoph Hellwig   [XFS] implement g...
194
195
196
197
198
199
200
201
  xfs_allocbt_get_minrecs(
  	struct xfs_btree_cur	*cur,
  	int			level)
  {
  	return cur->bc_mp->m_alloc_mnr[level != 0];
  }
  
  STATIC int
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
202
203
204
205
206
207
  xfs_allocbt_get_maxrecs(
  	struct xfs_btree_cur	*cur,
  	int			level)
  {
  	return cur->bc_mp->m_alloc_mxr[level != 0];
  }
fe033cc84   Christoph Hellwig   [XFS] implement g...
208
209
210
211
212
213
214
215
216
217
218
219
  STATIC void
  xfs_allocbt_init_key_from_rec(
  	union xfs_btree_key	*key,
  	union xfs_btree_rec	*rec)
  {
  	ASSERT(rec->alloc.ar_startblock != 0);
  
  	key->alloc.ar_startblock = rec->alloc.ar_startblock;
  	key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
  }
  
  STATIC void
4b22a5718   Christoph Hellwig   [XFS] implement g...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  xfs_allocbt_init_rec_from_key(
  	union xfs_btree_key	*key,
  	union xfs_btree_rec	*rec)
  {
  	ASSERT(key->alloc.ar_startblock != 0);
  
  	rec->alloc.ar_startblock = key->alloc.ar_startblock;
  	rec->alloc.ar_blockcount = key->alloc.ar_blockcount;
  }
  
  STATIC void
  xfs_allocbt_init_rec_from_cur(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_rec	*rec)
  {
  	ASSERT(cur->bc_rec.a.ar_startblock != 0);
  
  	rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
  	rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
  }
  
  STATIC void
fe033cc84   Christoph Hellwig   [XFS] implement g...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  xfs_allocbt_init_ptr_from_cur(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_ptr	*ptr)
  {
  	struct xfs_agf		*agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
  
  	ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
  	ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
  
  	ptr->s = agf->agf_roots[cur->bc_btnum];
  }
  
  STATIC __int64_t
  xfs_allocbt_key_diff(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_key	*key)
  {
  	xfs_alloc_rec_incore_t	*rec = &cur->bc_rec.a;
  	xfs_alloc_key_t		*kp = &key->alloc;
  	__int64_t		diff;
  
  	if (cur->bc_btnum == XFS_BTNUM_BNO) {
  		return (__int64_t)be32_to_cpu(kp->ar_startblock) -
  				rec->ar_startblock;
  	}
  
  	diff = (__int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount;
  	if (diff)
  		return diff;
  
  	return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
  }
4a26e66e7   Christoph Hellwig   [XFS] add keys_in...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  #ifdef DEBUG
  STATIC int
  xfs_allocbt_keys_inorder(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_key	*k1,
  	union xfs_btree_key	*k2)
  {
  	if (cur->bc_btnum == XFS_BTNUM_BNO) {
  		return be32_to_cpu(k1->alloc.ar_startblock) <
  		       be32_to_cpu(k2->alloc.ar_startblock);
  	} else {
  		return be32_to_cpu(k1->alloc.ar_blockcount) <
  			be32_to_cpu(k2->alloc.ar_blockcount) ||
  			(k1->alloc.ar_blockcount == k2->alloc.ar_blockcount &&
  			 be32_to_cpu(k1->alloc.ar_startblock) <
  			 be32_to_cpu(k2->alloc.ar_startblock));
  	}
  }
  
  STATIC int
  xfs_allocbt_recs_inorder(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_rec	*r1,
  	union xfs_btree_rec	*r2)
  {
  	if (cur->bc_btnum == XFS_BTNUM_BNO) {
  		return be32_to_cpu(r1->alloc.ar_startblock) +
  			be32_to_cpu(r1->alloc.ar_blockcount) <=
  			be32_to_cpu(r2->alloc.ar_startblock);
  	} else {
  		return be32_to_cpu(r1->alloc.ar_blockcount) <
  			be32_to_cpu(r2->alloc.ar_blockcount) ||
  			(r1->alloc.ar_blockcount == r2->alloc.ar_blockcount &&
  			 be32_to_cpu(r1->alloc.ar_startblock) <
  			 be32_to_cpu(r2->alloc.ar_startblock));
  	}
  }
  #endif	/* DEBUG */
8c4ed633e   Christoph Hellwig   [XFS] make btree ...
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
  #ifdef XFS_BTREE_TRACE
  ktrace_t	*xfs_allocbt_trace_buf;
  
  STATIC void
  xfs_allocbt_trace_enter(
  	struct xfs_btree_cur	*cur,
  	const char		*func,
  	char			*s,
  	int			type,
  	int			line,
  	__psunsigned_t		a0,
  	__psunsigned_t		a1,
  	__psunsigned_t		a2,
  	__psunsigned_t		a3,
  	__psunsigned_t		a4,
  	__psunsigned_t		a5,
  	__psunsigned_t		a6,
  	__psunsigned_t		a7,
  	__psunsigned_t		a8,
  	__psunsigned_t		a9,
  	__psunsigned_t		a10)
  {
  	ktrace_enter(xfs_allocbt_trace_buf, (void *)(__psint_t)type,
  		(void *)func, (void *)s, NULL, (void *)cur,
  		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
  		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
  		(void *)a8, (void *)a9, (void *)a10);
  }
  
  STATIC void
  xfs_allocbt_trace_cursor(
  	struct xfs_btree_cur	*cur,
  	__uint32_t		*s0,
  	__uint64_t		*l0,
  	__uint64_t		*l1)
  {
  	*s0 = cur->bc_private.a.agno;
  	*l0 = cur->bc_rec.a.ar_startblock;
  	*l1 = cur->bc_rec.a.ar_blockcount;
  }
  
  STATIC void
  xfs_allocbt_trace_key(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_key	*key,
  	__uint64_t		*l0,
  	__uint64_t		*l1)
  {
  	*l0 = be32_to_cpu(key->alloc.ar_startblock);
  	*l1 = be32_to_cpu(key->alloc.ar_blockcount);
  }
  
  STATIC void
  xfs_allocbt_trace_record(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_rec	*rec,
  	__uint64_t		*l0,
  	__uint64_t		*l1,
  	__uint64_t		*l2)
  {
  	*l0 = be32_to_cpu(rec->alloc.ar_startblock);
  	*l1 = be32_to_cpu(rec->alloc.ar_blockcount);
  	*l2 = 0;
  }
  #endif /* XFS_BTREE_TRACE */
561f7d173   Christoph Hellwig   [XFS] split up xf...
377
  static const struct xfs_btree_ops xfs_allocbt_ops = {
65f1eaeac   Christoph Hellwig   [XFS] add helpers...
378
379
  	.rec_len		= sizeof(xfs_alloc_rec_t),
  	.key_len		= sizeof(xfs_alloc_key_t),
561f7d173   Christoph Hellwig   [XFS] split up xf...
380
  	.dup_cursor		= xfs_allocbt_dup_cursor,
344207ce8   Christoph Hellwig   [XFS] implement s...
381
  	.set_root		= xfs_allocbt_set_root,
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
382
  	.alloc_block		= xfs_allocbt_alloc_block,
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
383
  	.free_block		= xfs_allocbt_free_block,
278d0ca14   Christoph Hellwig   [XFS] implement g...
384
  	.update_lastrec		= xfs_allocbt_update_lastrec,
91cca5df9   Christoph Hellwig   [XFS] implement g...
385
  	.get_minrecs		= xfs_allocbt_get_minrecs,
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
386
  	.get_maxrecs		= xfs_allocbt_get_maxrecs,
fe033cc84   Christoph Hellwig   [XFS] implement g...
387
  	.init_key_from_rec	= xfs_allocbt_init_key_from_rec,
4b22a5718   Christoph Hellwig   [XFS] implement g...
388
389
  	.init_rec_from_key	= xfs_allocbt_init_rec_from_key,
  	.init_rec_from_cur	= xfs_allocbt_init_rec_from_cur,
fe033cc84   Christoph Hellwig   [XFS] implement g...
390
391
  	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
  	.key_diff		= xfs_allocbt_key_diff,
8c4ed633e   Christoph Hellwig   [XFS] make btree ...
392

4a26e66e7   Christoph Hellwig   [XFS] add keys_in...
393
394
395
396
  #ifdef DEBUG
  	.keys_inorder		= xfs_allocbt_keys_inorder,
  	.recs_inorder		= xfs_allocbt_recs_inorder,
  #endif
8c4ed633e   Christoph Hellwig   [XFS] make btree ...
397
398
399
400
401
402
  #ifdef XFS_BTREE_TRACE
  	.trace_enter		= xfs_allocbt_trace_enter,
  	.trace_cursor		= xfs_allocbt_trace_cursor,
  	.trace_key		= xfs_allocbt_trace_key,
  	.trace_record		= xfs_allocbt_trace_record,
  #endif
561f7d173   Christoph Hellwig   [XFS] split up xf...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  };
  
  /*
   * Allocate a new allocation btree cursor.
   */
  struct xfs_btree_cur *			/* new alloc btree cursor */
  xfs_allocbt_init_cursor(
  	struct xfs_mount	*mp,		/* file system mount point */
  	struct xfs_trans	*tp,		/* transaction pointer */
  	struct xfs_buf		*agbp,		/* buffer for agf structure */
  	xfs_agnumber_t		agno,		/* allocation group number */
  	xfs_btnum_t		btnum)		/* btree identifier */
  {
  	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
  	struct xfs_btree_cur	*cur;
  
  	ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
  
  	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
  
  	cur->bc_tp = tp;
  	cur->bc_mp = mp;
  	cur->bc_nlevels = be32_to_cpu(agf->agf_levels[btnum]);
  	cur->bc_btnum = btnum;
  	cur->bc_blocklog = mp->m_sb.sb_blocklog;
  
  	cur->bc_ops = &xfs_allocbt_ops;
278d0ca14   Christoph Hellwig   [XFS] implement g...
430
431
  	if (btnum == XFS_BTNUM_CNT)
  		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
561f7d173   Christoph Hellwig   [XFS] split up xf...
432
433
434
435
436
437
  
  	cur->bc_private.a.agbp = agbp;
  	cur->bc_private.a.agno = agno;
  
  	return cur;
  }
60197e8df   Christoph Hellwig   [XFS] Cleanup max...
438
439
440
441
442
443
444
445
446
447
  
  /*
   * Calculate number of records in an alloc btree block.
   */
  int
  xfs_allocbt_maxrecs(
  	struct xfs_mount	*mp,
  	int			blocklen,
  	int			leaf)
  {
7cc95a821   Christoph Hellwig   [XFS] Always use ...
448
  	blocklen -= XFS_ALLOC_BLOCK_LEN(mp);
60197e8df   Christoph Hellwig   [XFS] Cleanup max...
449
450
451
452
453
  
  	if (leaf)
  		return blocklen / sizeof(xfs_alloc_rec_t);
  	return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t));
  }