Blame view

fs/xfs/xfs_ialloc_btree.c 7.9 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"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include "xfs_bmap_btree.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
29
  #include "xfs_alloc_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #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
37
  #include "xfs_ialloc.h"
  #include "xfs_alloc.h"
  #include "xfs_error.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

91cca5df9   Christoph Hellwig   [XFS] implement g...
39
40
41
42
43
44
45
  STATIC int
  xfs_inobt_get_minrecs(
  	struct xfs_btree_cur	*cur,
  	int			level)
  {
  	return cur->bc_mp->m_inobt_mnr[level != 0];
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

561f7d173   Christoph Hellwig   [XFS] split up xf...
47
48
49
50
51
52
53
  STATIC struct xfs_btree_cur *
  xfs_inobt_dup_cursor(
  	struct xfs_btree_cur	*cur)
  {
  	return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp,
  			cur->bc_private.a.agbp, cur->bc_private.a.agno);
  }
344207ce8   Christoph Hellwig   [XFS] implement s...
54
55
56
57
58
59
60
61
62
63
64
65
66
  STATIC void
  xfs_inobt_set_root(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_ptr	*nptr,
  	int			inc)	/* level change */
  {
  	struct xfs_buf		*agbp = cur->bc_private.a.agbp;
  	struct xfs_agi		*agi = XFS_BUF_TO_AGI(agbp);
  
  	agi->agi_root = nptr->s;
  	be32_add_cpu(&agi->agi_level, inc);
  	xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);
  }
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
67
  STATIC int
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
68
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
103
104
105
106
  xfs_inobt_alloc_block(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_ptr	*start,
  	union xfs_btree_ptr	*new,
  	int			length,
  	int			*stat)
  {
  	xfs_alloc_arg_t		args;		/* block allocation args */
  	int			error;		/* error return value */
  	xfs_agblock_t		sbno = be32_to_cpu(start->s);
  
  	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
  
  	memset(&args, 0, sizeof(args));
  	args.tp = cur->bc_tp;
  	args.mp = cur->bc_mp;
  	args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno);
  	args.minlen = 1;
  	args.maxlen = 1;
  	args.prod = 1;
  	args.type = XFS_ALLOCTYPE_NEAR_BNO;
  
  	error = xfs_alloc_vextent(&args);
  	if (error) {
  		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
  		return error;
  	}
  	if (args.fsbno == NULLFSBLOCK) {
  		XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
  		*stat = 0;
  		return 0;
  	}
  	ASSERT(args.len == 1);
  	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
  
  	new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));
  	*stat = 1;
  	return 0;
  }
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  STATIC int
  xfs_inobt_free_block(
  	struct xfs_btree_cur	*cur,
  	struct xfs_buf		*bp)
  {
  	xfs_fsblock_t		fsbno;
  	int			error;
  
  	fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp));
  	error = xfs_free_extent(cur->bc_tp, fsbno, 1);
  	if (error)
  		return error;
  
  	xfs_trans_binval(cur->bc_tp, bp);
  	return error;
  }
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
123
124
  
  STATIC int
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
125
126
127
128
129
130
  xfs_inobt_get_maxrecs(
  	struct xfs_btree_cur	*cur,
  	int			level)
  {
  	return cur->bc_mp->m_inobt_mxr[level != 0];
  }
fe033cc84   Christoph Hellwig   [XFS] implement g...
131
132
133
134
135
136
137
  STATIC void
  xfs_inobt_init_key_from_rec(
  	union xfs_btree_key	*key,
  	union xfs_btree_rec	*rec)
  {
  	key->inobt.ir_startino = rec->inobt.ir_startino;
  }
4b22a5718   Christoph Hellwig   [XFS] implement g...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  STATIC void
  xfs_inobt_init_rec_from_key(
  	union xfs_btree_key	*key,
  	union xfs_btree_rec	*rec)
  {
  	rec->inobt.ir_startino = key->inobt.ir_startino;
  }
  
  STATIC void
  xfs_inobt_init_rec_from_cur(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_rec	*rec)
  {
  	rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);
  	rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount);
  	rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
  }
fe033cc84   Christoph Hellwig   [XFS] implement g...
155
  /*
9da096fd1   Malcolm Parsons   xfs: fix various ...
156
   * initial value of ptr for lookup
fe033cc84   Christoph Hellwig   [XFS] implement g...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
   */
  STATIC void
  xfs_inobt_init_ptr_from_cur(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_ptr	*ptr)
  {
  	struct xfs_agi		*agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp);
  
  	ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno));
  
  	ptr->s = agi->agi_root;
  }
  
  STATIC __int64_t
  xfs_inobt_key_diff(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_key	*key)
  {
  	return (__int64_t)be32_to_cpu(key->inobt.ir_startino) -
  			  cur->bc_rec.i.ir_startino;
  }
4a26e66e7   Christoph Hellwig   [XFS] add keys_in...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  #ifdef DEBUG
  STATIC int
  xfs_inobt_keys_inorder(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_key	*k1,
  	union xfs_btree_key	*k2)
  {
  	return be32_to_cpu(k1->inobt.ir_startino) <
  		be32_to_cpu(k2->inobt.ir_startino);
  }
  
  STATIC int
  xfs_inobt_recs_inorder(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_rec	*r1,
  	union xfs_btree_rec	*r2)
  {
  	return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <=
  		be32_to_cpu(r2->inobt.ir_startino);
  }
  #endif	/* DEBUG */
8c4ed633e   Christoph Hellwig   [XFS] make btree ...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  #ifdef XFS_BTREE_TRACE
  ktrace_t	*xfs_inobt_trace_buf;
  
  STATIC void
  xfs_inobt_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_inobt_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_inobt_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.i.ir_startino;
  	*l1 = cur->bc_rec.i.ir_free;
  }
  
  STATIC void
  xfs_inobt_trace_key(
  	struct xfs_btree_cur	*cur,
  	union xfs_btree_key	*key,
  	__uint64_t		*l0,
  	__uint64_t		*l1)
  {
  	*l0 = be32_to_cpu(key->inobt.ir_startino);
  	*l1 = 0;
  }
  
  STATIC void
  xfs_inobt_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->inobt.ir_startino);
  	*l1 = be32_to_cpu(rec->inobt.ir_freecount);
  	*l2 = be64_to_cpu(rec->inobt.ir_free);
  }
  #endif /* XFS_BTREE_TRACE */
561f7d173   Christoph Hellwig   [XFS] split up xf...
264
  static const struct xfs_btree_ops xfs_inobt_ops = {
65f1eaeac   Christoph Hellwig   [XFS] add helpers...
265
266
  	.rec_len		= sizeof(xfs_inobt_rec_t),
  	.key_len		= sizeof(xfs_inobt_key_t),
561f7d173   Christoph Hellwig   [XFS] split up xf...
267
  	.dup_cursor		= xfs_inobt_dup_cursor,
344207ce8   Christoph Hellwig   [XFS] implement s...
268
  	.set_root		= xfs_inobt_set_root,
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
269
  	.alloc_block		= xfs_inobt_alloc_block,
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
270
  	.free_block		= xfs_inobt_free_block,
91cca5df9   Christoph Hellwig   [XFS] implement g...
271
  	.get_minrecs		= xfs_inobt_get_minrecs,
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
272
  	.get_maxrecs		= xfs_inobt_get_maxrecs,
fe033cc84   Christoph Hellwig   [XFS] implement g...
273
  	.init_key_from_rec	= xfs_inobt_init_key_from_rec,
4b22a5718   Christoph Hellwig   [XFS] implement g...
274
275
  	.init_rec_from_key	= xfs_inobt_init_rec_from_key,
  	.init_rec_from_cur	= xfs_inobt_init_rec_from_cur,
fe033cc84   Christoph Hellwig   [XFS] implement g...
276
277
  	.init_ptr_from_cur	= xfs_inobt_init_ptr_from_cur,
  	.key_diff		= xfs_inobt_key_diff,
8c4ed633e   Christoph Hellwig   [XFS] make btree ...
278

4a26e66e7   Christoph Hellwig   [XFS] add keys_in...
279
280
281
282
  #ifdef DEBUG
  	.keys_inorder		= xfs_inobt_keys_inorder,
  	.recs_inorder		= xfs_inobt_recs_inorder,
  #endif
8c4ed633e   Christoph Hellwig   [XFS] make btree ...
283
284
285
286
287
288
  #ifdef XFS_BTREE_TRACE
  	.trace_enter		= xfs_inobt_trace_enter,
  	.trace_cursor		= xfs_inobt_trace_cursor,
  	.trace_key		= xfs_inobt_trace_key,
  	.trace_record		= xfs_inobt_trace_record,
  #endif
561f7d173   Christoph Hellwig   [XFS] split up xf...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  };
  
  /*
   * Allocate a new inode btree cursor.
   */
  struct xfs_btree_cur *				/* new inode btree cursor */
  xfs_inobt_init_cursor(
  	struct xfs_mount	*mp,		/* file system mount point */
  	struct xfs_trans	*tp,		/* transaction pointer */
  	struct xfs_buf		*agbp,		/* buffer for agi structure */
  	xfs_agnumber_t		agno)		/* allocation group number */
  {
  	struct xfs_agi		*agi = XFS_BUF_TO_AGI(agbp);
  	struct xfs_btree_cur	*cur;
  
  	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
  
  	cur->bc_tp = tp;
  	cur->bc_mp = mp;
  	cur->bc_nlevels = be32_to_cpu(agi->agi_level);
  	cur->bc_btnum = XFS_BTNUM_INO;
  	cur->bc_blocklog = mp->m_sb.sb_blocklog;
  
  	cur->bc_ops = &xfs_inobt_ops;
  
  	cur->bc_private.a.agbp = agbp;
  	cur->bc_private.a.agno = agno;
  
  	return cur;
  }
60197e8df   Christoph Hellwig   [XFS] Cleanup max...
319
320
321
322
323
324
325
326
327
328
  
  /*
   * Calculate number of records in an inobt btree block.
   */
  int
  xfs_inobt_maxrecs(
  	struct xfs_mount	*mp,
  	int			blocklen,
  	int			leaf)
  {
7cc95a821   Christoph Hellwig   [XFS] Always use ...
329
  	blocklen -= XFS_INOBT_BLOCK_LEN(mp);
60197e8df   Christoph Hellwig   [XFS] Cleanup max...
330
331
332
333
334
  
  	if (leaf)
  		return blocklen / sizeof(xfs_inobt_rec_t);
  	return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t));
  }