Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
  3 * All Rights Reserved.
  4 *
  5 * This program is free software; you can redistribute it and/or
  6 * modify it under the terms of the GNU General Public License as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it would be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 *
 14 * You should have received a copy of the GNU General Public License
 15 * along with this program; if not, write the Free Software Foundation,
 16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17 */
 18#include "xfs.h"
 19#include "xfs_fs.h"
 20#include "xfs_types.h"
 21#include "xfs_log.h"
 22#include "xfs_trans.h"
 23#include "xfs_sb.h"
 24#include "xfs_ag.h"
 25#include "xfs_mount.h"
 26#include "xfs_bmap_btree.h"
 27#include "xfs_alloc_btree.h"
 28#include "xfs_ialloc_btree.h"
 29#include "xfs_dinode.h"
 30#include "xfs_inode.h"
 31#include "xfs_btree.h"
 32#include "xfs_alloc.h"
 33#include "xfs_extent_busy.h"
 34#include "xfs_error.h"
 35#include "xfs_trace.h"
 36
 37
 38STATIC struct xfs_btree_cur *
 39xfs_allocbt_dup_cursor(
 40	struct xfs_btree_cur	*cur)
 41{
 42	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
 43			cur->bc_private.a.agbp, cur->bc_private.a.agno,
 44			cur->bc_btnum);
 45}
 46
 47STATIC void
 48xfs_allocbt_set_root(
 49	struct xfs_btree_cur	*cur,
 50	union xfs_btree_ptr	*ptr,
 51	int			inc)
 52{
 53	struct xfs_buf		*agbp = cur->bc_private.a.agbp;
 54	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
 55	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno);
 56	int			btnum = cur->bc_btnum;
 57	struct xfs_perag	*pag = xfs_perag_get(cur->bc_mp, seqno);
 58
 59	ASSERT(ptr->s != 0);
 60
 61	agf->agf_roots[btnum] = ptr->s;
 62	be32_add_cpu(&agf->agf_levels[btnum], inc);
 63	pag->pagf_levels[btnum] += inc;
 64	xfs_perag_put(pag);
 65
 66	xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
 67}
 68
 69STATIC int
 70xfs_allocbt_alloc_block(
 71	struct xfs_btree_cur	*cur,
 72	union xfs_btree_ptr	*start,
 73	union xfs_btree_ptr	*new,
 74	int			length,
 75	int			*stat)
 76{
 77	int			error;
 78	xfs_agblock_t		bno;
 79
 80	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
 81
 82	/* Allocate the new block from the freelist. If we can't, give up.  */
 83	error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
 84				       &bno, 1);
 85	if (error) {
 86		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
 87		return error;
 88	}
 89
 90	if (bno == NULLAGBLOCK) {
 91		XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
 92		*stat = 0;
 93		return 0;
 94	}
 95
 96	xfs_extent_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, false);
 97
 98	xfs_trans_agbtree_delta(cur->bc_tp, 1);
 99	new->s = cpu_to_be32(bno);
100
101	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
102	*stat = 1;
103	return 0;
104}
105
106STATIC int
107xfs_allocbt_free_block(
108	struct xfs_btree_cur	*cur,
109	struct xfs_buf		*bp)
110{
111	struct xfs_buf		*agbp = cur->bc_private.a.agbp;
112	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
113	xfs_agblock_t		bno;
114	int			error;
115
116	bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp));
117	error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1);
118	if (error)
119		return error;
120
121	xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
122			      XFS_EXTENT_BUSY_SKIP_DISCARD);
123	xfs_trans_agbtree_delta(cur->bc_tp, -1);
124	return 0;
125}
126
127/*
128 * Update the longest extent in the AGF
129 */
130STATIC void
131xfs_allocbt_update_lastrec(
132	struct xfs_btree_cur	*cur,
133	struct xfs_btree_block	*block,
134	union xfs_btree_rec	*rec,
135	int			ptr,
136	int			reason)
137{
138	struct xfs_agf		*agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
139	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno);
140	struct xfs_perag	*pag;
141	__be32			len;
142	int			numrecs;
143
144	ASSERT(cur->bc_btnum == XFS_BTNUM_CNT);
145
146	switch (reason) {
147	case LASTREC_UPDATE:
148		/*
149		 * If this is the last leaf block and it's the last record,
150		 * then update the size of the longest extent in the AG.
151		 */
152		if (ptr != xfs_btree_get_numrecs(block))
153			return;
154		len = rec->alloc.ar_blockcount;
155		break;
156	case LASTREC_INSREC:
157		if (be32_to_cpu(rec->alloc.ar_blockcount) <=
158		    be32_to_cpu(agf->agf_longest))
159			return;
160		len = rec->alloc.ar_blockcount;
161		break;
162	case LASTREC_DELREC:
163		numrecs = xfs_btree_get_numrecs(block);
164		if (ptr <= numrecs)
165			return;
166		ASSERT(ptr == numrecs + 1);
167
168		if (numrecs) {
169			xfs_alloc_rec_t *rrp;
170
171			rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs);
172			len = rrp->ar_blockcount;
173		} else {
174			len = 0;
175		}
176
177		break;
178	default:
179		ASSERT(0);
180		return;
181	}
182
183	agf->agf_longest = len;
184	pag = xfs_perag_get(cur->bc_mp, seqno);
185	pag->pagf_longest = be32_to_cpu(len);
186	xfs_perag_put(pag);
187	xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST);
188}
189
190STATIC int
191xfs_allocbt_get_minrecs(
192	struct xfs_btree_cur	*cur,
193	int			level)
194{
195	return cur->bc_mp->m_alloc_mnr[level != 0];
196}
197
198STATIC int
199xfs_allocbt_get_maxrecs(
200	struct xfs_btree_cur	*cur,
201	int			level)
202{
203	return cur->bc_mp->m_alloc_mxr[level != 0];
204}
205
206STATIC void
207xfs_allocbt_init_key_from_rec(
208	union xfs_btree_key	*key,
209	union xfs_btree_rec	*rec)
210{
211	ASSERT(rec->alloc.ar_startblock != 0);
212
213	key->alloc.ar_startblock = rec->alloc.ar_startblock;
214	key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
215}
216
217STATIC void
218xfs_allocbt_init_rec_from_key(
219	union xfs_btree_key	*key,
220	union xfs_btree_rec	*rec)
221{
222	ASSERT(key->alloc.ar_startblock != 0);
223
224	rec->alloc.ar_startblock = key->alloc.ar_startblock;
225	rec->alloc.ar_blockcount = key->alloc.ar_blockcount;
226}
227
228STATIC void
229xfs_allocbt_init_rec_from_cur(
230	struct xfs_btree_cur	*cur,
231	union xfs_btree_rec	*rec)
232{
233	ASSERT(cur->bc_rec.a.ar_startblock != 0);
234
235	rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
236	rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
237}
238
239STATIC void
240xfs_allocbt_init_ptr_from_cur(
241	struct xfs_btree_cur	*cur,
242	union xfs_btree_ptr	*ptr)
243{
244	struct xfs_agf		*agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
245
246	ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
247	ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
248
249	ptr->s = agf->agf_roots[cur->bc_btnum];
250}
251
252STATIC __int64_t
253xfs_allocbt_key_diff(
254	struct xfs_btree_cur	*cur,
255	union xfs_btree_key	*key)
256{
257	xfs_alloc_rec_incore_t	*rec = &cur->bc_rec.a;
258	xfs_alloc_key_t		*kp = &key->alloc;
259	__int64_t		diff;
260
261	if (cur->bc_btnum == XFS_BTNUM_BNO) {
262		return (__int64_t)be32_to_cpu(kp->ar_startblock) -
263				rec->ar_startblock;
264	}
265
266	diff = (__int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount;
267	if (diff)
268		return diff;
269
270	return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
271}
272
273#ifdef DEBUG
274STATIC int
275xfs_allocbt_keys_inorder(
276	struct xfs_btree_cur	*cur,
277	union xfs_btree_key	*k1,
278	union xfs_btree_key	*k2)
279{
280	if (cur->bc_btnum == XFS_BTNUM_BNO) {
281		return be32_to_cpu(k1->alloc.ar_startblock) <
282		       be32_to_cpu(k2->alloc.ar_startblock);
283	} else {
284		return be32_to_cpu(k1->alloc.ar_blockcount) <
285			be32_to_cpu(k2->alloc.ar_blockcount) ||
286			(k1->alloc.ar_blockcount == k2->alloc.ar_blockcount &&
287			 be32_to_cpu(k1->alloc.ar_startblock) <
288			 be32_to_cpu(k2->alloc.ar_startblock));
289	}
290}
291
292STATIC int
293xfs_allocbt_recs_inorder(
294	struct xfs_btree_cur	*cur,
295	union xfs_btree_rec	*r1,
296	union xfs_btree_rec	*r2)
297{
298	if (cur->bc_btnum == XFS_BTNUM_BNO) {
299		return be32_to_cpu(r1->alloc.ar_startblock) +
300			be32_to_cpu(r1->alloc.ar_blockcount) <=
301			be32_to_cpu(r2->alloc.ar_startblock);
302	} else {
303		return be32_to_cpu(r1->alloc.ar_blockcount) <
304			be32_to_cpu(r2->alloc.ar_blockcount) ||
305			(r1->alloc.ar_blockcount == r2->alloc.ar_blockcount &&
306			 be32_to_cpu(r1->alloc.ar_startblock) <
307			 be32_to_cpu(r2->alloc.ar_startblock));
308	}
309}
310#endif	/* DEBUG */
311
312static const struct xfs_btree_ops xfs_allocbt_ops = {
313	.rec_len		= sizeof(xfs_alloc_rec_t),
314	.key_len		= sizeof(xfs_alloc_key_t),
315
316	.dup_cursor		= xfs_allocbt_dup_cursor,
317	.set_root		= xfs_allocbt_set_root,
318	.alloc_block		= xfs_allocbt_alloc_block,
319	.free_block		= xfs_allocbt_free_block,
320	.update_lastrec		= xfs_allocbt_update_lastrec,
321	.get_minrecs		= xfs_allocbt_get_minrecs,
322	.get_maxrecs		= xfs_allocbt_get_maxrecs,
323	.init_key_from_rec	= xfs_allocbt_init_key_from_rec,
324	.init_rec_from_key	= xfs_allocbt_init_rec_from_key,
325	.init_rec_from_cur	= xfs_allocbt_init_rec_from_cur,
326	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
327	.key_diff		= xfs_allocbt_key_diff,
328#ifdef DEBUG
329	.keys_inorder		= xfs_allocbt_keys_inorder,
330	.recs_inorder		= xfs_allocbt_recs_inorder,
331#endif
332};
333
334/*
335 * Allocate a new allocation btree cursor.
336 */
337struct xfs_btree_cur *			/* new alloc btree cursor */
338xfs_allocbt_init_cursor(
339	struct xfs_mount	*mp,		/* file system mount point */
340	struct xfs_trans	*tp,		/* transaction pointer */
341	struct xfs_buf		*agbp,		/* buffer for agf structure */
342	xfs_agnumber_t		agno,		/* allocation group number */
343	xfs_btnum_t		btnum)		/* btree identifier */
344{
345	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
346	struct xfs_btree_cur	*cur;
347
348	ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
349
350	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
351
352	cur->bc_tp = tp;
353	cur->bc_mp = mp;
354	cur->bc_btnum = btnum;
355	cur->bc_blocklog = mp->m_sb.sb_blocklog;
356	cur->bc_ops = &xfs_allocbt_ops;
357
358	if (btnum == XFS_BTNUM_CNT) {
359		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
360		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
361	} else {
362		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
363	}
364
365	cur->bc_private.a.agbp = agbp;
366	cur->bc_private.a.agno = agno;
367
368	return cur;
369}
370
371/*
372 * Calculate number of records in an alloc btree block.
373 */
374int
375xfs_allocbt_maxrecs(
376	struct xfs_mount	*mp,
377	int			blocklen,
378	int			leaf)
379{
380	blocklen -= XFS_ALLOC_BLOCK_LEN(mp);
381
382	if (leaf)
383		return blocklen / sizeof(xfs_alloc_rec_t);
384	return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t));
385}