Blame view

fs/xfs/xfs_ialloc_btree.c 6.35 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
34
35
36
  #include "xfs_btree.h"
  #include "xfs_ialloc.h"
  #include "xfs_alloc.h"
  #include "xfs_error.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

91cca5df9   Christoph Hellwig   [XFS] implement g...
38
39
40
41
42
43
44
  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
45

561f7d173   Christoph Hellwig   [XFS] split up xf...
46
47
48
49
50
51
52
  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...
53
54
55
56
57
58
59
60
61
62
63
64
65
  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...
66
  STATIC int
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
67
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
  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...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  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...
122
123
  
  STATIC int
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
124
125
126
127
128
129
  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...
130
131
132
133
134
135
136
  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...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  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...
154
  /*
9da096fd1   Malcolm Parsons   xfs: fix various ...
155
   * initial value of ptr for lookup
fe033cc84   Christoph Hellwig   [XFS] implement g...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
   */
  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...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  #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 */
561f7d173   Christoph Hellwig   [XFS] split up xf...
198
  static const struct xfs_btree_ops xfs_inobt_ops = {
65f1eaeac   Christoph Hellwig   [XFS] add helpers...
199
200
  	.rec_len		= sizeof(xfs_inobt_rec_t),
  	.key_len		= sizeof(xfs_inobt_key_t),
561f7d173   Christoph Hellwig   [XFS] split up xf...
201
  	.dup_cursor		= xfs_inobt_dup_cursor,
344207ce8   Christoph Hellwig   [XFS] implement s...
202
  	.set_root		= xfs_inobt_set_root,
f5eb8e7ca   Christoph Hellwig   [XFS] implement g...
203
  	.alloc_block		= xfs_inobt_alloc_block,
d4b3a4b7d   Christoph Hellwig   [XFS] move xfs_bm...
204
  	.free_block		= xfs_inobt_free_block,
91cca5df9   Christoph Hellwig   [XFS] implement g...
205
  	.get_minrecs		= xfs_inobt_get_minrecs,
ce5e42db4   Christoph Hellwig   [XFS] add get_max...
206
  	.get_maxrecs		= xfs_inobt_get_maxrecs,
fe033cc84   Christoph Hellwig   [XFS] implement g...
207
  	.init_key_from_rec	= xfs_inobt_init_key_from_rec,
4b22a5718   Christoph Hellwig   [XFS] implement g...
208
209
  	.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...
210
211
  	.init_ptr_from_cur	= xfs_inobt_init_ptr_from_cur,
  	.key_diff		= xfs_inobt_key_diff,
4a26e66e7   Christoph Hellwig   [XFS] add keys_in...
212
213
214
215
  #ifdef DEBUG
  	.keys_inorder		= xfs_inobt_keys_inorder,
  	.recs_inorder		= xfs_inobt_recs_inorder,
  #endif
561f7d173   Christoph Hellwig   [XFS] split up xf...
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
  };
  
  /*
   * 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...
246
247
248
249
250
251
252
253
254
255
  
  /*
   * 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 ...
256
  	blocklen -= XFS_INOBT_BLOCK_LEN(mp);
60197e8df   Christoph Hellwig   [XFS] Cleanup max...
257
258
259
260
261
  
  	if (leaf)
  		return blocklen / sizeof(xfs_inobt_rec_t);
  	return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t));
  }