1153323Srodrigc/*
2159451Srodrigc * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3159451Srodrigc * All Rights Reserved.
4153323Srodrigc *
5159451Srodrigc * This program is free software; you can redistribute it and/or
6159451Srodrigc * modify it under the terms of the GNU General Public License as
7153323Srodrigc * published by the Free Software Foundation.
8153323Srodrigc *
9159451Srodrigc * This program is distributed in the hope that it would be useful,
10159451Srodrigc * but WITHOUT ANY WARRANTY; without even the implied warranty of
11159451Srodrigc * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12159451Srodrigc * GNU General Public License for more details.
13153323Srodrigc *
14159451Srodrigc * You should have received a copy of the GNU General Public License
15159451Srodrigc * along with this program; if not, write the Free Software Foundation,
16159451Srodrigc * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17153323Srodrigc */
18153323Srodrigc#include "xfs.h"
19159451Srodrigc#include "xfs_fs.h"
20153323Srodrigc#include "xfs_types.h"
21159451Srodrigc#include "xfs_bit.h"
22159451Srodrigc#include "xfs_log.h"
23153323Srodrigc#include "xfs_inum.h"
24153323Srodrigc#include "xfs_trans.h"
25153323Srodrigc#include "xfs_sb.h"
26153323Srodrigc#include "xfs_ag.h"
27153323Srodrigc#include "xfs_dir.h"
28153323Srodrigc#include "xfs_dir2.h"
29153323Srodrigc#include "xfs_dmapi.h"
30153323Srodrigc#include "xfs_mount.h"
31159451Srodrigc#include "xfs_bmap_btree.h"
32153323Srodrigc#include "xfs_alloc_btree.h"
33153323Srodrigc#include "xfs_ialloc_btree.h"
34153323Srodrigc#include "xfs_dir_sf.h"
35153323Srodrigc#include "xfs_dir2_sf.h"
36159451Srodrigc#include "xfs_attr_sf.h"
37153323Srodrigc#include "xfs_dinode.h"
38159451Srodrigc#include "xfs_inode.h"
39153323Srodrigc#include "xfs_inode_item.h"
40153323Srodrigc#include "xfs_alloc.h"
41159451Srodrigc#include "xfs_btree.h"
42159451Srodrigc#include "xfs_ialloc.h"
43159451Srodrigc#include "xfs_itable.h"
44153323Srodrigc#include "xfs_bmap.h"
45153323Srodrigc#include "xfs_error.h"
46153323Srodrigc#include "xfs_quota.h"
47153323Srodrigc
48153323Srodrigc#if defined(XFS_BMBT_TRACE)
49153323Srodrigcktrace_t	*xfs_bmbt_trace_buf;
50153323Srodrigc#endif
51153323Srodrigc
52153323Srodrigc/*
53153323Srodrigc * Prototypes for internal btree functions.
54153323Srodrigc */
55153323Srodrigc
56153323Srodrigc
57153323SrodrigcSTATIC int xfs_bmbt_killroot(xfs_btree_cur_t *);
58153323SrodrigcSTATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
59153323SrodrigcSTATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
60153323SrodrigcSTATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
61153323SrodrigcSTATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *);
62153323SrodrigcSTATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *,
63153323Srodrigc		xfs_bmbt_key_t *, xfs_btree_cur_t **, int *);
64153323SrodrigcSTATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int);
65153323Srodrigc
66153323Srodrigc
67153323Srodrigc#if defined(XFS_BMBT_TRACE)
68153323Srodrigc
69153323Srodrigcstatic char	ARGS[] = "args";
70153323Srodrigcstatic char	ENTRY[] = "entry";
71153323Srodrigcstatic char	ERROR[] = "error";
72153323Srodrigc#undef EXIT
73153323Srodrigcstatic char	EXIT[] = "exit";
74153323Srodrigc
75153323Srodrigc/*
76153323Srodrigc * Add a trace buffer entry for the arguments given to the routine,
77153323Srodrigc * generic form.
78153323Srodrigc */
79153323SrodrigcSTATIC void
80153323Srodrigcxfs_bmbt_trace_enter(
81153323Srodrigc	char		*func,
82153323Srodrigc	xfs_btree_cur_t	*cur,
83153323Srodrigc	char		*s,
84153323Srodrigc	int		type,
85153323Srodrigc	int		line,
86153323Srodrigc	__psunsigned_t	a0,
87153323Srodrigc	__psunsigned_t	a1,
88153323Srodrigc	__psunsigned_t	a2,
89153323Srodrigc	__psunsigned_t	a3,
90153323Srodrigc	__psunsigned_t	a4,
91153323Srodrigc	__psunsigned_t	a5,
92153323Srodrigc	__psunsigned_t	a6,
93153323Srodrigc	__psunsigned_t	a7,
94153323Srodrigc	__psunsigned_t	a8,
95153323Srodrigc	__psunsigned_t	a9,
96153323Srodrigc	__psunsigned_t	a10)
97153323Srodrigc{
98153323Srodrigc	xfs_inode_t	*ip;
99153323Srodrigc	int		whichfork;
100153323Srodrigc
101153323Srodrigc	ip = cur->bc_private.b.ip;
102153323Srodrigc	whichfork = cur->bc_private.b.whichfork;
103153323Srodrigc	ktrace_enter(xfs_bmbt_trace_buf,
104153323Srodrigc		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
105153323Srodrigc		(void *)func, (void *)s, (void *)ip, (void *)cur,
106153323Srodrigc		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
107153323Srodrigc		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
108153323Srodrigc		(void *)a8, (void *)a9, (void *)a10);
109153323Srodrigc	ASSERT(ip->i_btrace);
110153323Srodrigc	ktrace_enter(ip->i_btrace,
111153323Srodrigc		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
112153323Srodrigc		(void *)func, (void *)s, (void *)ip, (void *)cur,
113153323Srodrigc		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
114153323Srodrigc		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
115153323Srodrigc		(void *)a8, (void *)a9, (void *)a10);
116153323Srodrigc}
117153323Srodrigc/*
118153323Srodrigc * Add a trace buffer entry for arguments, for a buffer & 1 integer arg.
119153323Srodrigc */
120153323SrodrigcSTATIC void
121153323Srodrigcxfs_bmbt_trace_argbi(
122153323Srodrigc	char		*func,
123153323Srodrigc	xfs_btree_cur_t	*cur,
124153323Srodrigc	xfs_buf_t	*b,
125153323Srodrigc	int		i,
126153323Srodrigc	int		line)
127153323Srodrigc{
128153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line,
129153323Srodrigc		(__psunsigned_t)b, i, 0, 0,
130153323Srodrigc		0, 0, 0, 0,
131153323Srodrigc		0, 0, 0);
132153323Srodrigc}
133153323Srodrigc
134153323Srodrigc/*
135153323Srodrigc * Add a trace buffer entry for arguments, for a buffer & 2 integer args.
136153323Srodrigc */
137153323SrodrigcSTATIC void
138153323Srodrigcxfs_bmbt_trace_argbii(
139153323Srodrigc	char		*func,
140153323Srodrigc	xfs_btree_cur_t	*cur,
141153323Srodrigc	xfs_buf_t	*b,
142153323Srodrigc	int		i0,
143153323Srodrigc	int		i1,
144153323Srodrigc	int		line)
145153323Srodrigc{
146153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line,
147153323Srodrigc		(__psunsigned_t)b, i0, i1, 0,
148153323Srodrigc		0, 0, 0, 0,
149153323Srodrigc		0, 0, 0);
150153323Srodrigc}
151153323Srodrigc
152153323Srodrigc/*
153153323Srodrigc * Add a trace buffer entry for arguments, for 3 block-length args
154153323Srodrigc * and an integer arg.
155153323Srodrigc */
156153323SrodrigcSTATIC void
157153323Srodrigcxfs_bmbt_trace_argfffi(
158153323Srodrigc	char			*func,
159153323Srodrigc	xfs_btree_cur_t		*cur,
160153323Srodrigc	xfs_dfiloff_t		o,
161153323Srodrigc	xfs_dfsbno_t		b,
162153323Srodrigc	xfs_dfilblks_t		i,
163153323Srodrigc	int			j,
164153323Srodrigc	int			line)
165153323Srodrigc{
166153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line,
167153323Srodrigc		o >> 32, (int)o, b >> 32, (int)b,
168153323Srodrigc		i >> 32, (int)i, (int)j, 0,
169153323Srodrigc		0, 0, 0);
170153323Srodrigc}
171153323Srodrigc
172153323Srodrigc/*
173153323Srodrigc * Add a trace buffer entry for arguments, for one integer arg.
174153323Srodrigc */
175153323SrodrigcSTATIC void
176153323Srodrigcxfs_bmbt_trace_argi(
177153323Srodrigc	char		*func,
178153323Srodrigc	xfs_btree_cur_t	*cur,
179153323Srodrigc	int		i,
180153323Srodrigc	int		line)
181153323Srodrigc{
182153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line,
183153323Srodrigc		i, 0, 0, 0,
184153323Srodrigc		0, 0, 0, 0,
185153323Srodrigc		0, 0, 0);
186153323Srodrigc}
187153323Srodrigc
188153323Srodrigc/*
189153323Srodrigc * Add a trace buffer entry for arguments, for int, fsblock, key.
190153323Srodrigc */
191153323SrodrigcSTATIC void
192153323Srodrigcxfs_bmbt_trace_argifk(
193153323Srodrigc	char			*func,
194153323Srodrigc	xfs_btree_cur_t		*cur,
195153323Srodrigc	int			i,
196153323Srodrigc	xfs_fsblock_t		f,
197153323Srodrigc	xfs_bmbt_key_t		*k,
198153323Srodrigc	int			line)
199153323Srodrigc{
200153323Srodrigc	xfs_dfsbno_t		d;
201153323Srodrigc	xfs_dfiloff_t		o;
202153323Srodrigc
203153323Srodrigc	d = (xfs_dfsbno_t)f;
204153323Srodrigc	o = INT_GET(k->br_startoff, ARCH_CONVERT);
205153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
206153323Srodrigc		i, d >> 32, (int)d, o >> 32,
207153323Srodrigc		(int)o, 0, 0, 0,
208153323Srodrigc		0, 0, 0);
209153323Srodrigc}
210153323Srodrigc
211153323Srodrigc/*
212153323Srodrigc * Add a trace buffer entry for arguments, for int, fsblock, rec.
213153323Srodrigc */
214153323SrodrigcSTATIC void
215153323Srodrigcxfs_bmbt_trace_argifr(
216153323Srodrigc	char			*func,
217153323Srodrigc	xfs_btree_cur_t		*cur,
218153323Srodrigc	int			i,
219153323Srodrigc	xfs_fsblock_t		f,
220153323Srodrigc	xfs_bmbt_rec_t		*r,
221153323Srodrigc	int			line)
222153323Srodrigc{
223153323Srodrigc	xfs_dfsbno_t		b;
224153323Srodrigc	xfs_dfilblks_t		c;
225153323Srodrigc	xfs_dfsbno_t		d;
226153323Srodrigc	xfs_dfiloff_t		o;
227153323Srodrigc	xfs_bmbt_irec_t		s;
228153323Srodrigc
229153323Srodrigc	d = (xfs_dfsbno_t)f;
230153323Srodrigc	xfs_bmbt_disk_get_all(r, &s);
231153323Srodrigc	o = (xfs_dfiloff_t)s.br_startoff;
232153323Srodrigc	b = (xfs_dfsbno_t)s.br_startblock;
233153323Srodrigc	c = s.br_blockcount;
234153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line,
235153323Srodrigc		i, d >> 32, (int)d, o >> 32,
236153323Srodrigc		(int)o, b >> 32, (int)b, c >> 32,
237153323Srodrigc		(int)c, 0, 0);
238153323Srodrigc}
239153323Srodrigc
240153323Srodrigc/*
241153323Srodrigc * Add a trace buffer entry for arguments, for int, key.
242153323Srodrigc */
243153323SrodrigcSTATIC void
244153323Srodrigcxfs_bmbt_trace_argik(
245153323Srodrigc	char			*func,
246153323Srodrigc	xfs_btree_cur_t		*cur,
247153323Srodrigc	int			i,
248153323Srodrigc	xfs_bmbt_key_t		*k,
249153323Srodrigc	int			line)
250153323Srodrigc{
251153323Srodrigc	xfs_dfiloff_t		o;
252153323Srodrigc
253153323Srodrigc	o = INT_GET(k->br_startoff, ARCH_CONVERT);
254153323Srodrigc	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
255153323Srodrigc		i, o >> 32, (int)o, 0,
256153323Srodrigc		0, 0, 0, 0,
257153323Srodrigc		0, 0, 0);
258153323Srodrigc}
259153323Srodrigc
260153323Srodrigc/*
261153323Srodrigc * Add a trace buffer entry for the cursor/operation.
262153323Srodrigc */
263153323SrodrigcSTATIC void
264153323Srodrigcxfs_bmbt_trace_cursor(
265153323Srodrigc	char		*func,
266153323Srodrigc	xfs_btree_cur_t	*cur,
267153323Srodrigc	char		*s,
268153323Srodrigc	int		line)
269153323Srodrigc{
270153323Srodrigc	xfs_bmbt_rec_t	r;
271153323Srodrigc
272153323Srodrigc	xfs_bmbt_set_all(&r, &cur->bc_rec.b);
273153323Srodrigc	xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
274153323Srodrigc		(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
275153323Srodrigc		cur->bc_private.b.allocated,
276153323Srodrigc		INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
277153323Srodrigc		(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
278153323Srodrigc		(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
279153323Srodrigc		(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
280153323Srodrigc		(cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]);
281153323Srodrigc}
282153323Srodrigc
283153323Srodrigc#define	XFS_BMBT_TRACE_ARGBI(c,b,i)	\
284153323Srodrigc	xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
285153323Srodrigc#define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)	\
286153323Srodrigc	xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
287153323Srodrigc#define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)	\
288153323Srodrigc	xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
289153323Srodrigc#define	XFS_BMBT_TRACE_ARGI(c,i)	\
290153323Srodrigc	xfs_bmbt_trace_argi(fname, c, i, __LINE__)
291153323Srodrigc#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)	\
292153323Srodrigc	xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__)
293153323Srodrigc#define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
294153323Srodrigc	xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
295153323Srodrigc#define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
296153323Srodrigc	xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
297153323Srodrigc#define	XFS_BMBT_TRACE_CURSOR(c,s)	\
298153323Srodrigc	xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
299153323Srodrigc#else
300153323Srodrigc#define	XFS_BMBT_TRACE_ARGBI(c,b,i)
301153323Srodrigc#define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
302153323Srodrigc#define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
303153323Srodrigc#define	XFS_BMBT_TRACE_ARGI(c,i)
304153323Srodrigc#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)
305153323Srodrigc#define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
306153323Srodrigc#define	XFS_BMBT_TRACE_ARGIK(c,i,k)
307153323Srodrigc#define	XFS_BMBT_TRACE_CURSOR(c,s)
308153323Srodrigc#endif	/* XFS_BMBT_TRACE */
309153323Srodrigc
310153323Srodrigc
311153323Srodrigc/*
312153323Srodrigc * Internal functions.
313153323Srodrigc */
314153323Srodrigc
315153323Srodrigc/*
316153323Srodrigc * Delete record pointed to by cur/level.
317153323Srodrigc */
318153323SrodrigcSTATIC int					/* error */
319153323Srodrigcxfs_bmbt_delrec(
320153323Srodrigc	xfs_btree_cur_t		*cur,
321153323Srodrigc	int			level,
322153323Srodrigc	int			*stat)		/* success/failure */
323153323Srodrigc{
324153323Srodrigc	xfs_bmbt_block_t	*block;		/* bmap btree block */
325153323Srodrigc	xfs_fsblock_t		bno;		/* fs-relative block number */
326153323Srodrigc	xfs_buf_t		*bp;		/* buffer for block */
327153323Srodrigc	int			error;		/* error return value */
328153323Srodrigc#ifdef XFS_BMBT_TRACE
329153323Srodrigc	static char		fname[] = "xfs_bmbt_delrec";
330153323Srodrigc#endif
331153323Srodrigc	int			i;		/* loop counter */
332153323Srodrigc	int			j;		/* temp state */
333153323Srodrigc	xfs_bmbt_key_t		key;		/* bmap btree key */
334153323Srodrigc	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
335153323Srodrigc	xfs_fsblock_t		lbno;		/* left sibling block number */
336153323Srodrigc	xfs_buf_t		*lbp;		/* left buffer pointer */
337153323Srodrigc	xfs_bmbt_block_t	*left;		/* left btree block */
338153323Srodrigc	xfs_bmbt_key_t		*lkp;		/* left btree key */
339153323Srodrigc	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
340153323Srodrigc	int			lrecs=0;	/* left record count */
341153323Srodrigc	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
342153323Srodrigc	xfs_mount_t		*mp;		/* file system mount point */
343153323Srodrigc	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
344153323Srodrigc	int			ptr;		/* key/record index */
345153323Srodrigc	xfs_fsblock_t		rbno;		/* right sibling block number */
346153323Srodrigc	xfs_buf_t		*rbp;		/* right buffer pointer */
347153323Srodrigc	xfs_bmbt_block_t	*right;		/* right btree block */
348153323Srodrigc	xfs_bmbt_key_t		*rkp;		/* right btree key */
349153323Srodrigc	xfs_bmbt_rec_t		*rp;		/* pointer to bmap btree rec */
350153323Srodrigc	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
351153323Srodrigc	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */
352153323Srodrigc	xfs_buf_t		*rrbp;		/* right-right buffer pointer */
353153323Srodrigc	int			rrecs=0;	/* right record count */
354153323Srodrigc	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
355153323Srodrigc	xfs_btree_cur_t		*tcur;		/* temporary btree cursor */
356153323Srodrigc	int			numrecs;	/* temporary numrec count */
357153323Srodrigc	int			numlrecs, numrrecs;
358153323Srodrigc
359153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
360153323Srodrigc	XFS_BMBT_TRACE_ARGI(cur, level);
361153323Srodrigc	ptr = cur->bc_ptrs[level];
362153323Srodrigc	tcur = (xfs_btree_cur_t *)0;
363153323Srodrigc	if (ptr == 0) {
364153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
365153323Srodrigc		*stat = 0;
366153323Srodrigc		return 0;
367153323Srodrigc	}
368153323Srodrigc	block = xfs_bmbt_get_block(cur, level, &bp);
369159451Srodrigc	numrecs = be16_to_cpu(block->bb_numrecs);
370153323Srodrigc#ifdef DEBUG
371153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
372153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
373153323Srodrigc		goto error0;
374153323Srodrigc	}
375153323Srodrigc#endif
376153323Srodrigc	if (ptr > numrecs) {
377153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
378153323Srodrigc		*stat = 0;
379153323Srodrigc		return 0;
380153323Srodrigc	}
381153323Srodrigc	XFS_STATS_INC(xs_bmbt_delrec);
382153323Srodrigc	if (level > 0) {
383153323Srodrigc		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
384153323Srodrigc		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
385153323Srodrigc#ifdef DEBUG
386153323Srodrigc		for (i = ptr; i < numrecs; i++) {
387153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
388153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
389153323Srodrigc				goto error0;
390153323Srodrigc			}
391153323Srodrigc		}
392153323Srodrigc#endif
393153323Srodrigc		if (ptr < numrecs) {
394153323Srodrigc			memmove(&kp[ptr - 1], &kp[ptr],
395153323Srodrigc				(numrecs - ptr) * sizeof(*kp));
396153323Srodrigc			memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
397153323Srodrigc				(numrecs - ptr) * sizeof(*pp));
398153323Srodrigc			xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
399153323Srodrigc			xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
400153323Srodrigc		}
401153323Srodrigc	} else {
402153323Srodrigc		rp = XFS_BMAP_REC_IADDR(block, 1, cur);
403153323Srodrigc		if (ptr < numrecs) {
404153323Srodrigc			memmove(&rp[ptr - 1], &rp[ptr],
405153323Srodrigc				(numrecs - ptr) * sizeof(*rp));
406153323Srodrigc			xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
407153323Srodrigc		}
408153323Srodrigc		if (ptr == 1) {
409153323Srodrigc			INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp));
410153323Srodrigc			kp = &key;
411153323Srodrigc		}
412153323Srodrigc	}
413153323Srodrigc	numrecs--;
414159451Srodrigc	block->bb_numrecs = cpu_to_be16(numrecs);
415153323Srodrigc	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
416153323Srodrigc	/*
417153323Srodrigc	 * We're at the root level.
418153323Srodrigc	 * First, shrink the root block in-memory.
419153323Srodrigc	 * Try to get rid of the next level down.
420153323Srodrigc	 * If we can't then there's nothing left to do.
421153323Srodrigc	 */
422153323Srodrigc	if (level == cur->bc_nlevels - 1) {
423153323Srodrigc		xfs_iroot_realloc(cur->bc_private.b.ip, -1,
424153323Srodrigc			cur->bc_private.b.whichfork);
425153323Srodrigc		if ((error = xfs_bmbt_killroot(cur))) {
426153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
427153323Srodrigc			goto error0;
428153323Srodrigc		}
429153323Srodrigc		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
430153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
431153323Srodrigc			goto error0;
432153323Srodrigc		}
433153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
434153323Srodrigc		*stat = 1;
435153323Srodrigc		return 0;
436153323Srodrigc	}
437153323Srodrigc	if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) {
438153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
439153323Srodrigc		goto error0;
440153323Srodrigc	}
441153323Srodrigc	if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
442153323Srodrigc		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
443153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
444153323Srodrigc			goto error0;
445153323Srodrigc		}
446153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
447153323Srodrigc		*stat = 1;
448153323Srodrigc		return 0;
449153323Srodrigc	}
450159451Srodrigc	rbno = be64_to_cpu(block->bb_rightsib);
451159451Srodrigc	lbno = be64_to_cpu(block->bb_leftsib);
452153323Srodrigc	/*
453153323Srodrigc	 * One child of root, need to get a chance to copy its contents
454153323Srodrigc	 * into the root and delete it. Can't go up to next level,
455153323Srodrigc	 * there's nothing to delete there.
456153323Srodrigc	 */
457153323Srodrigc	if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&
458153323Srodrigc	    level == cur->bc_nlevels - 2) {
459153323Srodrigc		if ((error = xfs_bmbt_killroot(cur))) {
460153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
461153323Srodrigc			goto error0;
462153323Srodrigc		}
463153323Srodrigc		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
464153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
465153323Srodrigc			goto error0;
466153323Srodrigc		}
467153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
468153323Srodrigc		*stat = 1;
469153323Srodrigc		return 0;
470153323Srodrigc	}
471153323Srodrigc	ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK);
472153323Srodrigc	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
473153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
474153323Srodrigc		goto error0;
475153323Srodrigc	}
476153323Srodrigc	bno = NULLFSBLOCK;
477153323Srodrigc	if (rbno != NULLFSBLOCK) {
478153323Srodrigc		i = xfs_btree_lastrec(tcur, level);
479153323Srodrigc		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
480153323Srodrigc		if ((error = xfs_bmbt_increment(tcur, level, &i))) {
481153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
482153323Srodrigc			goto error0;
483153323Srodrigc		}
484153323Srodrigc		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
485153323Srodrigc		i = xfs_btree_lastrec(tcur, level);
486153323Srodrigc		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
487153323Srodrigc		rbp = tcur->bc_bufs[level];
488153323Srodrigc		right = XFS_BUF_TO_BMBT_BLOCK(rbp);
489153323Srodrigc#ifdef DEBUG
490153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
491153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
492153323Srodrigc			goto error0;
493153323Srodrigc		}
494153323Srodrigc#endif
495159451Srodrigc		bno = be64_to_cpu(right->bb_leftsib);
496159451Srodrigc		if (be16_to_cpu(right->bb_numrecs) - 1 >=
497153323Srodrigc		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
498153323Srodrigc			if ((error = xfs_bmbt_lshift(tcur, level, &i))) {
499153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
500153323Srodrigc				goto error0;
501153323Srodrigc			}
502153323Srodrigc			if (i) {
503159451Srodrigc				ASSERT(be16_to_cpu(block->bb_numrecs) >=
504153323Srodrigc				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));
505153323Srodrigc				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
506153323Srodrigc				tcur = NULL;
507153323Srodrigc				if (level > 0) {
508153323Srodrigc					if ((error = xfs_bmbt_decrement(cur,
509153323Srodrigc							level, &i))) {
510153323Srodrigc						XFS_BMBT_TRACE_CURSOR(cur,
511153323Srodrigc							ERROR);
512153323Srodrigc						goto error0;
513153323Srodrigc					}
514153323Srodrigc				}
515153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
516153323Srodrigc				*stat = 1;
517153323Srodrigc				return 0;
518153323Srodrigc			}
519153323Srodrigc		}
520159451Srodrigc		rrecs = be16_to_cpu(right->bb_numrecs);
521153323Srodrigc		if (lbno != NULLFSBLOCK) {
522153323Srodrigc			i = xfs_btree_firstrec(tcur, level);
523153323Srodrigc			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
524153323Srodrigc			if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
525153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
526153323Srodrigc				goto error0;
527153323Srodrigc			}
528153323Srodrigc			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
529153323Srodrigc		}
530153323Srodrigc	}
531153323Srodrigc	if (lbno != NULLFSBLOCK) {
532153323Srodrigc		i = xfs_btree_firstrec(tcur, level);
533153323Srodrigc		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
534153323Srodrigc		/*
535153323Srodrigc		 * decrement to last in block
536153323Srodrigc		 */
537153323Srodrigc		if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
538153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
539153323Srodrigc			goto error0;
540153323Srodrigc		}
541153323Srodrigc		i = xfs_btree_firstrec(tcur, level);
542153323Srodrigc		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
543153323Srodrigc		lbp = tcur->bc_bufs[level];
544153323Srodrigc		left = XFS_BUF_TO_BMBT_BLOCK(lbp);
545153323Srodrigc#ifdef DEBUG
546153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
547153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
548153323Srodrigc			goto error0;
549153323Srodrigc		}
550153323Srodrigc#endif
551159451Srodrigc		bno = be64_to_cpu(left->bb_rightsib);
552159451Srodrigc		if (be16_to_cpu(left->bb_numrecs) - 1 >=
553153323Srodrigc		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
554153323Srodrigc			if ((error = xfs_bmbt_rshift(tcur, level, &i))) {
555153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
556153323Srodrigc				goto error0;
557153323Srodrigc			}
558153323Srodrigc			if (i) {
559159451Srodrigc				ASSERT(be16_to_cpu(block->bb_numrecs) >=
560153323Srodrigc				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));
561153323Srodrigc				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
562153323Srodrigc				tcur = NULL;
563153323Srodrigc				if (level == 0)
564153323Srodrigc					cur->bc_ptrs[0]++;
565153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
566153323Srodrigc				*stat = 1;
567153323Srodrigc				return 0;
568153323Srodrigc			}
569153323Srodrigc		}
570159451Srodrigc		lrecs = be16_to_cpu(left->bb_numrecs);
571153323Srodrigc	}
572153323Srodrigc	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
573153323Srodrigc	tcur = NULL;
574153323Srodrigc	mp = cur->bc_mp;
575153323Srodrigc	ASSERT(bno != NULLFSBLOCK);
576153323Srodrigc	if (lbno != NULLFSBLOCK &&
577159451Srodrigc	    lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
578153323Srodrigc		rbno = bno;
579153323Srodrigc		right = block;
580153323Srodrigc		rbp = bp;
581153323Srodrigc		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp,
582153323Srodrigc				XFS_BMAP_BTREE_REF))) {
583153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
584153323Srodrigc			goto error0;
585153323Srodrigc		}
586153323Srodrigc		left = XFS_BUF_TO_BMBT_BLOCK(lbp);
587153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
588153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
589153323Srodrigc			goto error0;
590153323Srodrigc		}
591153323Srodrigc	} else if (rbno != NULLFSBLOCK &&
592159451Srodrigc		   rrecs + be16_to_cpu(block->bb_numrecs) <=
593153323Srodrigc		   XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
594153323Srodrigc		lbno = bno;
595153323Srodrigc		left = block;
596153323Srodrigc		lbp = bp;
597153323Srodrigc		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp,
598153323Srodrigc				XFS_BMAP_BTREE_REF))) {
599153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
600153323Srodrigc			goto error0;
601153323Srodrigc		}
602153323Srodrigc		right = XFS_BUF_TO_BMBT_BLOCK(rbp);
603153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
604153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
605153323Srodrigc			goto error0;
606153323Srodrigc		}
607159451Srodrigc		lrecs = be16_to_cpu(left->bb_numrecs);
608153323Srodrigc	} else {
609153323Srodrigc		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
610153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
611153323Srodrigc			goto error0;
612153323Srodrigc		}
613153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
614153323Srodrigc		*stat = 1;
615153323Srodrigc		return 0;
616153323Srodrigc	}
617159451Srodrigc	numlrecs = be16_to_cpu(left->bb_numrecs);
618159451Srodrigc	numrrecs = be16_to_cpu(right->bb_numrecs);
619153323Srodrigc	if (level > 0) {
620153323Srodrigc		lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur);
621153323Srodrigc		lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur);
622153323Srodrigc		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
623153323Srodrigc		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
624153323Srodrigc#ifdef DEBUG
625153323Srodrigc		for (i = 0; i < numrrecs; i++) {
626153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
627153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
628153323Srodrigc				goto error0;
629153323Srodrigc			}
630153323Srodrigc		}
631153323Srodrigc#endif
632153323Srodrigc		memcpy(lkp, rkp, numrrecs * sizeof(*lkp));
633153323Srodrigc		memcpy(lpp, rpp, numrrecs * sizeof(*lpp));
634153323Srodrigc		xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
635153323Srodrigc		xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
636153323Srodrigc	} else {
637153323Srodrigc		lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur);
638153323Srodrigc		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
639153323Srodrigc		memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
640153323Srodrigc		xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
641153323Srodrigc	}
642159451Srodrigc	be16_add(&left->bb_numrecs, numrrecs);
643159451Srodrigc	left->bb_rightsib = right->bb_rightsib;
644153323Srodrigc	xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);
645159451Srodrigc	if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) {
646153323Srodrigc		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp,
647159451Srodrigc				be64_to_cpu(left->bb_rightsib),
648153323Srodrigc				0, &rrbp, XFS_BMAP_BTREE_REF))) {
649153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
650153323Srodrigc			goto error0;
651153323Srodrigc		}
652153323Srodrigc		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
653153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
654153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
655153323Srodrigc			goto error0;
656153323Srodrigc		}
657159451Srodrigc		rrblock->bb_leftsib = cpu_to_be64(lbno);
658153323Srodrigc		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
659153323Srodrigc	}
660153323Srodrigc	xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,
661153323Srodrigc		cur->bc_private.b.flist, mp);
662153323Srodrigc	cur->bc_private.b.ip->i_d.di_nblocks--;
663153323Srodrigc	xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
664153323Srodrigc	XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip,
665153323Srodrigc			XFS_TRANS_DQ_BCOUNT, -1L);
666153323Srodrigc	xfs_trans_binval(cur->bc_tp, rbp);
667153323Srodrigc	if (bp != lbp) {
668153323Srodrigc		cur->bc_bufs[level] = lbp;
669153323Srodrigc		cur->bc_ptrs[level] += lrecs;
670153323Srodrigc		cur->bc_ra[level] = 0;
671153323Srodrigc	} else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {
672153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
673153323Srodrigc		goto error0;
674153323Srodrigc	}
675153323Srodrigc	if (level > 0)
676153323Srodrigc		cur->bc_ptrs[level]--;
677153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
678153323Srodrigc	*stat = 2;
679153323Srodrigc	return 0;
680153323Srodrigc
681153323Srodrigcerror0:
682153323Srodrigc	if (tcur)
683153323Srodrigc		xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
684153323Srodrigc	return error;
685153323Srodrigc}
686153323Srodrigc
687159451Srodrigc#ifdef DEBUG
688153323Srodrigc/*
689153323Srodrigc * Get the data from the pointed-to record.
690153323Srodrigc */
691153323Srodrigcint
692153323Srodrigcxfs_bmbt_get_rec(
693153323Srodrigc	xfs_btree_cur_t		*cur,
694153323Srodrigc	xfs_fileoff_t		*off,
695153323Srodrigc	xfs_fsblock_t		*bno,
696153323Srodrigc	xfs_filblks_t		*len,
697153323Srodrigc	xfs_exntst_t		*state,
698153323Srodrigc	int			*stat)
699153323Srodrigc{
700153323Srodrigc	xfs_bmbt_block_t	*block;
701153323Srodrigc	xfs_buf_t		*bp;
702153323Srodrigc#ifdef DEBUG
703153323Srodrigc	int			error;
704153323Srodrigc#endif
705153323Srodrigc	int			ptr;
706153323Srodrigc	xfs_bmbt_rec_t		*rp;
707153323Srodrigc
708153323Srodrigc	block = xfs_bmbt_get_block(cur, 0, &bp);
709153323Srodrigc	ptr = cur->bc_ptrs[0];
710153323Srodrigc#ifdef DEBUG
711153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))
712153323Srodrigc		return error;
713153323Srodrigc#endif
714159451Srodrigc	if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
715153323Srodrigc		*stat = 0;
716153323Srodrigc		return 0;
717153323Srodrigc	}
718153323Srodrigc	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
719153323Srodrigc	*off = xfs_bmbt_disk_get_startoff(rp);
720153323Srodrigc	*bno = xfs_bmbt_disk_get_startblock(rp);
721153323Srodrigc	*len = xfs_bmbt_disk_get_blockcount(rp);
722153323Srodrigc	*state = xfs_bmbt_disk_get_state(rp);
723153323Srodrigc	*stat = 1;
724153323Srodrigc	return 0;
725153323Srodrigc}
726153323Srodrigc#endif
727153323Srodrigc
728153323Srodrigc/*
729153323Srodrigc * Insert one record/level.  Return information to the caller
730153323Srodrigc * allowing the next level up to proceed if necessary.
731153323Srodrigc */
732153323SrodrigcSTATIC int					/* error */
733153323Srodrigcxfs_bmbt_insrec(
734153323Srodrigc	xfs_btree_cur_t		*cur,
735153323Srodrigc	int			level,
736153323Srodrigc	xfs_fsblock_t		*bnop,
737153323Srodrigc	xfs_bmbt_rec_t		*recp,
738153323Srodrigc	xfs_btree_cur_t		**curp,
739153323Srodrigc	int			*stat)		/* no-go/done/continue */
740153323Srodrigc{
741153323Srodrigc	xfs_bmbt_block_t	*block;		/* bmap btree block */
742153323Srodrigc	xfs_buf_t		*bp;		/* buffer for block */
743153323Srodrigc	int			error;		/* error return value */
744153323Srodrigc#ifdef XFS_BMBT_TRACE
745153323Srodrigc	static char		fname[] = "xfs_bmbt_insrec";
746153323Srodrigc#endif
747153323Srodrigc	int			i;		/* loop index */
748153323Srodrigc	xfs_bmbt_key_t		key;		/* bmap btree key */
749153323Srodrigc	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
750153323Srodrigc	int			logflags;	/* inode logging flags */
751153323Srodrigc	xfs_fsblock_t		nbno;		/* new block number */
752153323Srodrigc	struct xfs_btree_cur	*ncur;		/* new btree cursor */
753153323Srodrigc	xfs_bmbt_key_t		nkey;		/* new btree key value */
754153323Srodrigc	xfs_bmbt_rec_t		nrec;		/* new record count */
755153323Srodrigc	int			optr;		/* old key/record index */
756153323Srodrigc	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
757153323Srodrigc	int			ptr;		/* key/record index */
758153323Srodrigc	xfs_bmbt_rec_t		*rp=NULL;	/* pointer to bmap btree rec */
759153323Srodrigc	int			numrecs;
760153323Srodrigc
761153323Srodrigc	ASSERT(level < cur->bc_nlevels);
762153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
763153323Srodrigc	XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
764153323Srodrigc	ncur = (xfs_btree_cur_t *)0;
765153323Srodrigc	INT_SET(key.br_startoff, ARCH_CONVERT,
766153323Srodrigc		xfs_bmbt_disk_get_startoff(recp));
767153323Srodrigc	optr = ptr = cur->bc_ptrs[level];
768153323Srodrigc	if (ptr == 0) {
769153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
770153323Srodrigc		*stat = 0;
771153323Srodrigc		return 0;
772153323Srodrigc	}
773153323Srodrigc	XFS_STATS_INC(xs_bmbt_insrec);
774153323Srodrigc	block = xfs_bmbt_get_block(cur, level, &bp);
775159451Srodrigc	numrecs = be16_to_cpu(block->bb_numrecs);
776170124Skan	nkey.br_startoff = 0;
777153323Srodrigc#ifdef DEBUG
778153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
779153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
780153323Srodrigc		return error;
781153323Srodrigc	}
782153323Srodrigc	if (ptr <= numrecs) {
783153323Srodrigc		if (level == 0) {
784153323Srodrigc			rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
785153323Srodrigc			xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp);
786153323Srodrigc		} else {
787153323Srodrigc			kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
788153323Srodrigc			xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp);
789153323Srodrigc		}
790153323Srodrigc	}
791153323Srodrigc#endif
792153323Srodrigc	nbno = NULLFSBLOCK;
793153323Srodrigc	if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
794153323Srodrigc		if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
795153323Srodrigc			/*
796153323Srodrigc			 * A root block, that can be made bigger.
797153323Srodrigc			 */
798153323Srodrigc			xfs_iroot_realloc(cur->bc_private.b.ip, 1,
799153323Srodrigc				cur->bc_private.b.whichfork);
800153323Srodrigc			block = xfs_bmbt_get_block(cur, level, &bp);
801153323Srodrigc		} else if (level == cur->bc_nlevels - 1) {
802153323Srodrigc			if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) ||
803153323Srodrigc			    *stat == 0) {
804153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
805153323Srodrigc				return error;
806153323Srodrigc			}
807153323Srodrigc			xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
808153323Srodrigc				logflags);
809153323Srodrigc			block = xfs_bmbt_get_block(cur, level, &bp);
810153323Srodrigc		} else {
811153323Srodrigc			if ((error = xfs_bmbt_rshift(cur, level, &i))) {
812153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
813153323Srodrigc				return error;
814153323Srodrigc			}
815153323Srodrigc			if (i) {
816153323Srodrigc				/* nothing */
817153323Srodrigc			} else {
818153323Srodrigc				if ((error = xfs_bmbt_lshift(cur, level, &i))) {
819153323Srodrigc					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
820153323Srodrigc					return error;
821153323Srodrigc				}
822153323Srodrigc				if (i) {
823153323Srodrigc					optr = ptr = cur->bc_ptrs[level];
824153323Srodrigc				} else {
825153323Srodrigc					if ((error = xfs_bmbt_split(cur, level,
826153323Srodrigc							&nbno, &nkey, &ncur,
827153323Srodrigc							&i))) {
828153323Srodrigc						XFS_BMBT_TRACE_CURSOR(cur,
829153323Srodrigc							ERROR);
830153323Srodrigc						return error;
831153323Srodrigc					}
832153323Srodrigc					if (i) {
833153323Srodrigc						block = xfs_bmbt_get_block(
834153323Srodrigc							    cur, level, &bp);
835153323Srodrigc#ifdef DEBUG
836153323Srodrigc						if ((error =
837153323Srodrigc						    xfs_btree_check_lblock(cur,
838153323Srodrigc							    block, level, bp))) {
839153323Srodrigc							XFS_BMBT_TRACE_CURSOR(
840153323Srodrigc								cur, ERROR);
841153323Srodrigc							return error;
842153323Srodrigc						}
843153323Srodrigc#endif
844153323Srodrigc						ptr = cur->bc_ptrs[level];
845153323Srodrigc						xfs_bmbt_disk_set_allf(&nrec,
846153323Srodrigc							nkey.br_startoff, 0, 0,
847153323Srodrigc							XFS_EXT_NORM);
848153323Srodrigc					} else {
849153323Srodrigc						XFS_BMBT_TRACE_CURSOR(cur,
850153323Srodrigc							EXIT);
851153323Srodrigc						*stat = 0;
852153323Srodrigc						return 0;
853153323Srodrigc					}
854153323Srodrigc				}
855153323Srodrigc			}
856153323Srodrigc		}
857153323Srodrigc	}
858159451Srodrigc	numrecs = be16_to_cpu(block->bb_numrecs);
859153323Srodrigc	if (level > 0) {
860153323Srodrigc		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
861153323Srodrigc		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
862153323Srodrigc#ifdef DEBUG
863153323Srodrigc		for (i = numrecs; i >= ptr; i--) {
864153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),
865153323Srodrigc					level))) {
866153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
867153323Srodrigc				return error;
868153323Srodrigc			}
869153323Srodrigc		}
870153323Srodrigc#endif
871153323Srodrigc		memmove(&kp[ptr], &kp[ptr - 1],
872153323Srodrigc			(numrecs - ptr + 1) * sizeof(*kp));
873153323Srodrigc		memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
874153323Srodrigc			(numrecs - ptr + 1) * sizeof(*pp));
875153323Srodrigc#ifdef DEBUG
876153323Srodrigc		if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,
877153323Srodrigc				level))) {
878153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
879153323Srodrigc			return error;
880153323Srodrigc		}
881153323Srodrigc#endif
882153323Srodrigc		kp[ptr - 1] = key;
883153323Srodrigc		INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
884153323Srodrigc		numrecs++;
885159451Srodrigc		block->bb_numrecs = cpu_to_be16(numrecs);
886153323Srodrigc		xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
887153323Srodrigc		xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs);
888153323Srodrigc	} else {
889153323Srodrigc		rp = XFS_BMAP_REC_IADDR(block, 1, cur);
890153323Srodrigc		memmove(&rp[ptr], &rp[ptr - 1],
891153323Srodrigc			(numrecs - ptr + 1) * sizeof(*rp));
892153323Srodrigc		rp[ptr - 1] = *recp;
893153323Srodrigc		numrecs++;
894159451Srodrigc		block->bb_numrecs = cpu_to_be16(numrecs);
895153323Srodrigc		xfs_bmbt_log_recs(cur, bp, ptr, numrecs);
896153323Srodrigc	}
897153323Srodrigc	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
898153323Srodrigc#ifdef DEBUG
899153323Srodrigc	if (ptr < numrecs) {
900153323Srodrigc		if (level == 0)
901153323Srodrigc			xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1,
902153323Srodrigc				rp + ptr);
903153323Srodrigc		else
904153323Srodrigc			xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1,
905153323Srodrigc				kp + ptr);
906153323Srodrigc	}
907153323Srodrigc#endif
908153323Srodrigc	if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) {
909153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
910153323Srodrigc		return error;
911153323Srodrigc	}
912153323Srodrigc	*bnop = nbno;
913153323Srodrigc	if (nbno != NULLFSBLOCK) {
914153323Srodrigc		*recp = nrec;
915153323Srodrigc		*curp = ncur;
916153323Srodrigc	}
917153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
918153323Srodrigc	*stat = 1;
919153323Srodrigc	return 0;
920153323Srodrigc}
921153323Srodrigc
922153323SrodrigcSTATIC int
923153323Srodrigcxfs_bmbt_killroot(
924153323Srodrigc	xfs_btree_cur_t		*cur)
925153323Srodrigc{
926153323Srodrigc	xfs_bmbt_block_t	*block;
927153323Srodrigc	xfs_bmbt_block_t	*cblock;
928153323Srodrigc	xfs_buf_t		*cbp;
929153323Srodrigc	xfs_bmbt_key_t		*ckp;
930153323Srodrigc	xfs_bmbt_ptr_t		*cpp;
931153323Srodrigc#ifdef DEBUG
932153323Srodrigc	int			error;
933153323Srodrigc#endif
934153323Srodrigc#ifdef XFS_BMBT_TRACE
935153323Srodrigc	static char		fname[] = "xfs_bmbt_killroot";
936153323Srodrigc#endif
937153323Srodrigc	int			i;
938153323Srodrigc	xfs_bmbt_key_t		*kp;
939153323Srodrigc	xfs_inode_t		*ip;
940153323Srodrigc	xfs_ifork_t		*ifp;
941153323Srodrigc	int			level;
942153323Srodrigc	xfs_bmbt_ptr_t		*pp;
943153323Srodrigc
944153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
945153323Srodrigc	level = cur->bc_nlevels - 1;
946153323Srodrigc	ASSERT(level >= 1);
947153323Srodrigc	/*
948153323Srodrigc	 * Don't deal with the root block needs to be a leaf case.
949153323Srodrigc	 * We're just going to turn the thing back into extents anyway.
950153323Srodrigc	 */
951153323Srodrigc	if (level == 1) {
952153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
953153323Srodrigc		return 0;
954153323Srodrigc	}
955153323Srodrigc	block = xfs_bmbt_get_block(cur, level, &cbp);
956153323Srodrigc	/*
957153323Srodrigc	 * Give up if the root has multiple children.
958153323Srodrigc	 */
959159451Srodrigc	if (be16_to_cpu(block->bb_numrecs) != 1) {
960153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
961153323Srodrigc		return 0;
962153323Srodrigc	}
963153323Srodrigc	/*
964153323Srodrigc	 * Only do this if the next level will fit.
965153323Srodrigc	 * Then the data must be copied up to the inode,
966153323Srodrigc	 * instead of freeing the root you free the next level.
967153323Srodrigc	 */
968153323Srodrigc	cbp = cur->bc_bufs[level - 1];
969153323Srodrigc	cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
970159451Srodrigc	if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
971153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
972153323Srodrigc		return 0;
973153323Srodrigc	}
974159451Srodrigc	ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO);
975159451Srodrigc	ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO);
976153323Srodrigc	ip = cur->bc_private.b.ip;
977153323Srodrigc	ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork);
978153323Srodrigc	ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) ==
979153323Srodrigc	       XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes));
980159451Srodrigc	i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur));
981153323Srodrigc	if (i) {
982153323Srodrigc		xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork);
983153323Srodrigc		block = ifp->if_broot;
984153323Srodrigc	}
985159451Srodrigc	be16_add(&block->bb_numrecs, i);
986159451Srodrigc	ASSERT(block->bb_numrecs == cblock->bb_numrecs);
987153323Srodrigc	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
988153323Srodrigc	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
989159451Srodrigc	memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp));
990153323Srodrigc	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
991153323Srodrigc	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
992153323Srodrigc#ifdef DEBUG
993159451Srodrigc	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
994153323Srodrigc		if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) {
995153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
996153323Srodrigc			return error;
997153323Srodrigc		}
998153323Srodrigc	}
999153323Srodrigc#endif
1000159451Srodrigc	memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp));
1001153323Srodrigc	xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1,
1002153323Srodrigc			cur->bc_private.b.flist, cur->bc_mp);
1003153323Srodrigc	ip->i_d.di_nblocks--;
1004153323Srodrigc	XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip,
1005153323Srodrigc			XFS_TRANS_DQ_BCOUNT, -1L);
1006153323Srodrigc	xfs_trans_binval(cur->bc_tp, cbp);
1007153323Srodrigc	cur->bc_bufs[level - 1] = NULL;
1008159451Srodrigc	be16_add(&block->bb_level, -1);
1009153323Srodrigc	xfs_trans_log_inode(cur->bc_tp, ip,
1010153323Srodrigc		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1011153323Srodrigc	cur->bc_nlevels--;
1012153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1013153323Srodrigc	return 0;
1014153323Srodrigc}
1015153323Srodrigc
1016153323Srodrigc/*
1017153323Srodrigc * Log key values from the btree block.
1018153323Srodrigc */
1019153323SrodrigcSTATIC void
1020153323Srodrigcxfs_bmbt_log_keys(
1021153323Srodrigc	xfs_btree_cur_t	*cur,
1022153323Srodrigc	xfs_buf_t	*bp,
1023153323Srodrigc	int		kfirst,
1024153323Srodrigc	int		klast)
1025153323Srodrigc{
1026153323Srodrigc#ifdef XFS_BMBT_TRACE
1027153323Srodrigc	static char	fname[] = "xfs_bmbt_log_keys";
1028153323Srodrigc#endif
1029153323Srodrigc	xfs_trans_t	*tp;
1030153323Srodrigc
1031153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1032153323Srodrigc	XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast);
1033153323Srodrigc	tp = cur->bc_tp;
1034153323Srodrigc	if (bp) {
1035153323Srodrigc		xfs_bmbt_block_t	*block;
1036153323Srodrigc		int			first;
1037153323Srodrigc		xfs_bmbt_key_t		*kp;
1038153323Srodrigc		int			last;
1039153323Srodrigc
1040153323Srodrigc		block = XFS_BUF_TO_BMBT_BLOCK(bp);
1041153323Srodrigc		kp = XFS_BMAP_KEY_DADDR(block, 1, cur);
1042153323Srodrigc		first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
1043153323Srodrigc		last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
1044153323Srodrigc		xfs_trans_log_buf(tp, bp, first, last);
1045153323Srodrigc	} else {
1046153323Srodrigc		xfs_inode_t		 *ip;
1047153323Srodrigc
1048153323Srodrigc		ip = cur->bc_private.b.ip;
1049153323Srodrigc		xfs_trans_log_inode(tp, ip,
1050153323Srodrigc			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1051153323Srodrigc	}
1052153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1053153323Srodrigc}
1054153323Srodrigc
1055153323Srodrigc/*
1056153323Srodrigc * Log pointer values from the btree block.
1057153323Srodrigc */
1058153323SrodrigcSTATIC void
1059153323Srodrigcxfs_bmbt_log_ptrs(
1060153323Srodrigc	xfs_btree_cur_t	*cur,
1061153323Srodrigc	xfs_buf_t	*bp,
1062153323Srodrigc	int		pfirst,
1063153323Srodrigc	int		plast)
1064153323Srodrigc{
1065153323Srodrigc#ifdef XFS_BMBT_TRACE
1066153323Srodrigc	static char	fname[] = "xfs_bmbt_log_ptrs";
1067153323Srodrigc#endif
1068153323Srodrigc	xfs_trans_t	*tp;
1069153323Srodrigc
1070153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1071153323Srodrigc	XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast);
1072153323Srodrigc	tp = cur->bc_tp;
1073153323Srodrigc	if (bp) {
1074153323Srodrigc		xfs_bmbt_block_t	*block;
1075153323Srodrigc		int			first;
1076153323Srodrigc		int			last;
1077153323Srodrigc		xfs_bmbt_ptr_t		*pp;
1078153323Srodrigc
1079153323Srodrigc		block = XFS_BUF_TO_BMBT_BLOCK(bp);
1080153323Srodrigc		pp = XFS_BMAP_PTR_DADDR(block, 1, cur);
1081153323Srodrigc		first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
1082153323Srodrigc		last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
1083153323Srodrigc		xfs_trans_log_buf(tp, bp, first, last);
1084153323Srodrigc	} else {
1085153323Srodrigc		xfs_inode_t		*ip;
1086153323Srodrigc
1087153323Srodrigc		ip = cur->bc_private.b.ip;
1088153323Srodrigc		xfs_trans_log_inode(tp, ip,
1089153323Srodrigc			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1090153323Srodrigc	}
1091153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1092153323Srodrigc}
1093153323Srodrigc
1094153323Srodrigc/*
1095153323Srodrigc * Lookup the record.  The cursor is made to point to it, based on dir.
1096153323Srodrigc */
1097153323SrodrigcSTATIC int				/* error */
1098153323Srodrigcxfs_bmbt_lookup(
1099153323Srodrigc	xfs_btree_cur_t		*cur,
1100153323Srodrigc	xfs_lookup_t		dir,
1101153323Srodrigc	int			*stat)		/* success/failure */
1102153323Srodrigc{
1103153323Srodrigc	xfs_bmbt_block_t	*block=NULL;
1104153323Srodrigc	xfs_buf_t		*bp;
1105153323Srodrigc	xfs_daddr_t		d;
1106153323Srodrigc	xfs_sfiloff_t		diff;
1107153323Srodrigc	int			error;		/* error return value */
1108153323Srodrigc#ifdef XFS_BMBT_TRACE
1109153323Srodrigc	static char	fname[] = "xfs_bmbt_lookup";
1110153323Srodrigc#endif
1111153323Srodrigc	xfs_fsblock_t		fsbno=0;
1112153323Srodrigc	int			high;
1113153323Srodrigc	int			i;
1114153323Srodrigc	int			keyno=0;
1115153323Srodrigc	xfs_bmbt_key_t		*kkbase=NULL;
1116153323Srodrigc	xfs_bmbt_key_t		*kkp;
1117153323Srodrigc	xfs_bmbt_rec_t		*krbase=NULL;
1118153323Srodrigc	xfs_bmbt_rec_t		*krp;
1119153323Srodrigc	int			level;
1120153323Srodrigc	int			low;
1121153323Srodrigc	xfs_mount_t		*mp;
1122153323Srodrigc	xfs_bmbt_ptr_t		*pp;
1123153323Srodrigc	xfs_bmbt_irec_t		*rp;
1124153323Srodrigc	xfs_fileoff_t		startoff;
1125153323Srodrigc	xfs_trans_t		*tp;
1126153323Srodrigc
1127153323Srodrigc	XFS_STATS_INC(xs_bmbt_lookup);
1128153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1129153323Srodrigc	XFS_BMBT_TRACE_ARGI(cur, (int)dir);
1130153323Srodrigc	tp = cur->bc_tp;
1131153323Srodrigc	mp = cur->bc_mp;
1132153323Srodrigc	rp = &cur->bc_rec.b;
1133153323Srodrigc	for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
1134153323Srodrigc		if (level < cur->bc_nlevels - 1) {
1135153323Srodrigc			d = XFS_FSB_TO_DADDR(mp, fsbno);
1136153323Srodrigc			bp = cur->bc_bufs[level];
1137153323Srodrigc			if (bp && XFS_BUF_ADDR(bp) != d)
1138153323Srodrigc				bp = (xfs_buf_t *)0;
1139153323Srodrigc			if (!bp) {
1140153323Srodrigc				if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
1141153323Srodrigc						0, &bp, XFS_BMAP_BTREE_REF))) {
1142153323Srodrigc					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1143153323Srodrigc					return error;
1144153323Srodrigc				}
1145153323Srodrigc				xfs_btree_setbuf(cur, level, bp);
1146153323Srodrigc				block = XFS_BUF_TO_BMBT_BLOCK(bp);
1147153323Srodrigc				if ((error = xfs_btree_check_lblock(cur, block,
1148153323Srodrigc						level, bp))) {
1149153323Srodrigc					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1150153323Srodrigc					return error;
1151153323Srodrigc				}
1152153323Srodrigc			} else
1153153323Srodrigc				block = XFS_BUF_TO_BMBT_BLOCK(bp);
1154153323Srodrigc		} else
1155153323Srodrigc			block = xfs_bmbt_get_block(cur, level, &bp);
1156153323Srodrigc		if (diff == 0)
1157153323Srodrigc			keyno = 1;
1158153323Srodrigc		else {
1159153323Srodrigc			if (level > 0)
1160153323Srodrigc				kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur);
1161153323Srodrigc			else
1162153323Srodrigc				krbase = XFS_BMAP_REC_IADDR(block, 1, cur);
1163153323Srodrigc			low = 1;
1164159451Srodrigc			if (!(high = be16_to_cpu(block->bb_numrecs))) {
1165153323Srodrigc				ASSERT(level == 0);
1166153323Srodrigc				cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
1167153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1168153323Srodrigc				*stat = 0;
1169153323Srodrigc				return 0;
1170153323Srodrigc			}
1171153323Srodrigc			while (low <= high) {
1172153323Srodrigc				XFS_STATS_INC(xs_bmbt_compare);
1173153323Srodrigc				keyno = (low + high) >> 1;
1174153323Srodrigc				if (level > 0) {
1175153323Srodrigc					kkp = kkbase + keyno - 1;
1176153323Srodrigc					startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT);
1177153323Srodrigc				} else {
1178153323Srodrigc					krp = krbase + keyno - 1;
1179153323Srodrigc					startoff = xfs_bmbt_disk_get_startoff(krp);
1180153323Srodrigc				}
1181153323Srodrigc				diff = (xfs_sfiloff_t)
1182153323Srodrigc						(startoff - rp->br_startoff);
1183153323Srodrigc				if (diff < 0)
1184153323Srodrigc					low = keyno + 1;
1185153323Srodrigc				else if (diff > 0)
1186153323Srodrigc					high = keyno - 1;
1187153323Srodrigc				else
1188153323Srodrigc					break;
1189153323Srodrigc			}
1190153323Srodrigc		}
1191153323Srodrigc		if (level > 0) {
1192153323Srodrigc			if (diff > 0 && --keyno < 1)
1193153323Srodrigc				keyno = 1;
1194153323Srodrigc			pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
1195153323Srodrigc#ifdef DEBUG
1196153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
1197153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1198153323Srodrigc				return error;
1199153323Srodrigc			}
1200153323Srodrigc#endif
1201153323Srodrigc			fsbno = INT_GET(*pp, ARCH_CONVERT);
1202153323Srodrigc			cur->bc_ptrs[level] = keyno;
1203153323Srodrigc		}
1204153323Srodrigc	}
1205153323Srodrigc	if (dir != XFS_LOOKUP_LE && diff < 0) {
1206153323Srodrigc		keyno++;
1207153323Srodrigc		/*
1208153323Srodrigc		 * If ge search and we went off the end of the block, but it's
1209153323Srodrigc		 * not the last block, we're in the wrong block.
1210153323Srodrigc		 */
1211159451Srodrigc		if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) &&
1212159451Srodrigc		    be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) {
1213153323Srodrigc			cur->bc_ptrs[0] = keyno;
1214153323Srodrigc			if ((error = xfs_bmbt_increment(cur, 0, &i))) {
1215153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1216153323Srodrigc				return error;
1217153323Srodrigc			}
1218153323Srodrigc			XFS_WANT_CORRUPTED_RETURN(i == 1);
1219153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1220153323Srodrigc			*stat = 1;
1221153323Srodrigc			return 0;
1222153323Srodrigc		}
1223153323Srodrigc	}
1224153323Srodrigc	else if (dir == XFS_LOOKUP_LE && diff > 0)
1225153323Srodrigc		keyno--;
1226153323Srodrigc	cur->bc_ptrs[0] = keyno;
1227159451Srodrigc	if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) {
1228153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1229153323Srodrigc		*stat = 0;
1230153323Srodrigc	} else {
1231153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1232153323Srodrigc		*stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
1233153323Srodrigc	}
1234153323Srodrigc	return 0;
1235153323Srodrigc}
1236153323Srodrigc
1237153323Srodrigc/*
1238153323Srodrigc * Move 1 record left from cur/level if possible.
1239153323Srodrigc * Update cur to reflect the new path.
1240153323Srodrigc */
1241153323SrodrigcSTATIC int					/* error */
1242153323Srodrigcxfs_bmbt_lshift(
1243153323Srodrigc	xfs_btree_cur_t		*cur,
1244153323Srodrigc	int			level,
1245153323Srodrigc	int			*stat)		/* success/failure */
1246153323Srodrigc{
1247153323Srodrigc	int			error;		/* error return value */
1248153323Srodrigc#ifdef XFS_BMBT_TRACE
1249153323Srodrigc	static char		fname[] = "xfs_bmbt_lshift";
1250153323Srodrigc#endif
1251153323Srodrigc#ifdef DEBUG
1252153323Srodrigc	int			i;		/* loop counter */
1253153323Srodrigc#endif
1254153323Srodrigc	xfs_bmbt_key_t		key;		/* bmap btree key */
1255153323Srodrigc	xfs_buf_t		*lbp;		/* left buffer pointer */
1256153323Srodrigc	xfs_bmbt_block_t	*left;		/* left btree block */
1257153323Srodrigc	xfs_bmbt_key_t		*lkp=NULL;	/* left btree key */
1258153323Srodrigc	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
1259153323Srodrigc	int			lrecs;		/* left record count */
1260153323Srodrigc	xfs_bmbt_rec_t		*lrp=NULL;	/* left record pointer */
1261153323Srodrigc	xfs_mount_t		*mp;		/* file system mount point */
1262153323Srodrigc	xfs_buf_t		*rbp;		/* right buffer pointer */
1263153323Srodrigc	xfs_bmbt_block_t	*right;		/* right btree block */
1264153323Srodrigc	xfs_bmbt_key_t		*rkp=NULL;	/* right btree key */
1265153323Srodrigc	xfs_bmbt_ptr_t		*rpp=NULL;	/* right address pointer */
1266153323Srodrigc	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */
1267153323Srodrigc	int			rrecs;		/* right record count */
1268153323Srodrigc
1269153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1270153323Srodrigc	XFS_BMBT_TRACE_ARGI(cur, level);
1271153323Srodrigc	if (level == cur->bc_nlevels - 1) {
1272153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1273153323Srodrigc		*stat = 0;
1274153323Srodrigc		return 0;
1275153323Srodrigc	}
1276153323Srodrigc	rbp = cur->bc_bufs[level];
1277153323Srodrigc	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1278153323Srodrigc#ifdef DEBUG
1279153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
1280153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1281153323Srodrigc		return error;
1282153323Srodrigc	}
1283153323Srodrigc#endif
1284159451Srodrigc	if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) {
1285153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1286153323Srodrigc		*stat = 0;
1287153323Srodrigc		return 0;
1288153323Srodrigc	}
1289153323Srodrigc	if (cur->bc_ptrs[level] <= 1) {
1290153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1291153323Srodrigc		*stat = 0;
1292153323Srodrigc		return 0;
1293153323Srodrigc	}
1294153323Srodrigc	mp = cur->bc_mp;
1295159451Srodrigc	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0,
1296153323Srodrigc			&lbp, XFS_BMAP_BTREE_REF))) {
1297153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1298153323Srodrigc		return error;
1299153323Srodrigc	}
1300153323Srodrigc	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1301153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
1302153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1303153323Srodrigc		return error;
1304153323Srodrigc	}
1305159451Srodrigc	if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
1306153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1307153323Srodrigc		*stat = 0;
1308153323Srodrigc		return 0;
1309153323Srodrigc	}
1310159451Srodrigc	lrecs = be16_to_cpu(left->bb_numrecs) + 1;
1311153323Srodrigc	if (level > 0) {
1312153323Srodrigc		lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur);
1313153323Srodrigc		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1314153323Srodrigc		*lkp = *rkp;
1315153323Srodrigc		xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs);
1316153323Srodrigc		lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
1317153323Srodrigc		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1318153323Srodrigc#ifdef DEBUG
1319153323Srodrigc		if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) {
1320153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1321153323Srodrigc			return error;
1322153323Srodrigc		}
1323153323Srodrigc#endif
1324153323Srodrigc		*lpp = *rpp; /* INT_: direct copy */
1325153323Srodrigc		xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
1326153323Srodrigc	} else {
1327153323Srodrigc		lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
1328153323Srodrigc		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1329153323Srodrigc		*lrp = *rrp;
1330153323Srodrigc		xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs);
1331153323Srodrigc	}
1332159451Srodrigc	left->bb_numrecs = cpu_to_be16(lrecs);
1333153323Srodrigc	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
1334153323Srodrigc#ifdef DEBUG
1335153323Srodrigc	if (level > 0)
1336153323Srodrigc		xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp);
1337153323Srodrigc	else
1338153323Srodrigc		xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp);
1339153323Srodrigc#endif
1340159451Srodrigc	rrecs = be16_to_cpu(right->bb_numrecs) - 1;
1341159451Srodrigc	right->bb_numrecs = cpu_to_be16(rrecs);
1342153323Srodrigc	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
1343153323Srodrigc	if (level > 0) {
1344153323Srodrigc#ifdef DEBUG
1345153323Srodrigc		for (i = 0; i < rrecs; i++) {
1346153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
1347153323Srodrigc					level))) {
1348153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1349153323Srodrigc				return error;
1350153323Srodrigc			}
1351153323Srodrigc		}
1352153323Srodrigc#endif
1353153323Srodrigc		memmove(rkp, rkp + 1, rrecs * sizeof(*rkp));
1354153323Srodrigc		memmove(rpp, rpp + 1, rrecs * sizeof(*rpp));
1355153323Srodrigc		xfs_bmbt_log_keys(cur, rbp, 1, rrecs);
1356153323Srodrigc		xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs);
1357153323Srodrigc	} else {
1358153323Srodrigc		memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
1359153323Srodrigc		xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
1360153323Srodrigc		INT_SET(key.br_startoff, ARCH_CONVERT,
1361153323Srodrigc			xfs_bmbt_disk_get_startoff(rrp));
1362153323Srodrigc		rkp = &key;
1363153323Srodrigc	}
1364153323Srodrigc	if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
1365153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1366153323Srodrigc		return error;
1367153323Srodrigc	}
1368153323Srodrigc	cur->bc_ptrs[level]--;
1369153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1370153323Srodrigc	*stat = 1;
1371153323Srodrigc	return 0;
1372153323Srodrigc}
1373153323Srodrigc
1374153323Srodrigc/*
1375153323Srodrigc * Move 1 record right from cur/level if possible.
1376153323Srodrigc * Update cur to reflect the new path.
1377153323Srodrigc */
1378153323SrodrigcSTATIC int					/* error */
1379153323Srodrigcxfs_bmbt_rshift(
1380153323Srodrigc	xfs_btree_cur_t		*cur,
1381153323Srodrigc	int			level,
1382153323Srodrigc	int			*stat)		/* success/failure */
1383153323Srodrigc{
1384153323Srodrigc	int			error;		/* error return value */
1385153323Srodrigc#ifdef XFS_BMBT_TRACE
1386153323Srodrigc	static char		fname[] = "xfs_bmbt_rshift";
1387153323Srodrigc#endif
1388153323Srodrigc	int			i;		/* loop counter */
1389153323Srodrigc	xfs_bmbt_key_t		key;		/* bmap btree key */
1390153323Srodrigc	xfs_buf_t		*lbp;		/* left buffer pointer */
1391153323Srodrigc	xfs_bmbt_block_t	*left;		/* left btree block */
1392153323Srodrigc	xfs_bmbt_key_t		*lkp;		/* left btree key */
1393153323Srodrigc	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
1394153323Srodrigc	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
1395153323Srodrigc	xfs_mount_t		*mp;		/* file system mount point */
1396153323Srodrigc	xfs_buf_t		*rbp;		/* right buffer pointer */
1397153323Srodrigc	xfs_bmbt_block_t	*right;		/* right btree block */
1398153323Srodrigc	xfs_bmbt_key_t		*rkp;		/* right btree key */
1399153323Srodrigc	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
1400153323Srodrigc	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */
1401153323Srodrigc	struct xfs_btree_cur	*tcur;		/* temporary btree cursor */
1402153323Srodrigc
1403153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1404153323Srodrigc	XFS_BMBT_TRACE_ARGI(cur, level);
1405153323Srodrigc	if (level == cur->bc_nlevels - 1) {
1406153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1407153323Srodrigc		*stat = 0;
1408153323Srodrigc		return 0;
1409153323Srodrigc	}
1410153323Srodrigc	lbp = cur->bc_bufs[level];
1411153323Srodrigc	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1412153323Srodrigc#ifdef DEBUG
1413153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
1414153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1415153323Srodrigc		return error;
1416153323Srodrigc	}
1417153323Srodrigc#endif
1418159451Srodrigc	if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) {
1419153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1420153323Srodrigc		*stat = 0;
1421153323Srodrigc		return 0;
1422153323Srodrigc	}
1423159451Srodrigc	if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) {
1424153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1425153323Srodrigc		*stat = 0;
1426153323Srodrigc		return 0;
1427153323Srodrigc	}
1428153323Srodrigc	mp = cur->bc_mp;
1429159451Srodrigc	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0,
1430153323Srodrigc			&rbp, XFS_BMAP_BTREE_REF))) {
1431153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1432153323Srodrigc		return error;
1433153323Srodrigc	}
1434153323Srodrigc	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1435153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
1436153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1437153323Srodrigc		return error;
1438153323Srodrigc	}
1439159451Srodrigc	if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
1440153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1441153323Srodrigc		*stat = 0;
1442153323Srodrigc		return 0;
1443153323Srodrigc	}
1444153323Srodrigc	if (level > 0) {
1445159451Srodrigc		lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1446159451Srodrigc		lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1447153323Srodrigc		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1448153323Srodrigc		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1449153323Srodrigc#ifdef DEBUG
1450159451Srodrigc		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
1451153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
1452153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1453153323Srodrigc				return error;
1454153323Srodrigc			}
1455153323Srodrigc		}
1456153323Srodrigc#endif
1457159451Srodrigc		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
1458159451Srodrigc		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
1459153323Srodrigc#ifdef DEBUG
1460153323Srodrigc		if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) {
1461153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1462153323Srodrigc			return error;
1463153323Srodrigc		}
1464153323Srodrigc#endif
1465153323Srodrigc		*rkp = *lkp;
1466153323Srodrigc		*rpp = *lpp; /* INT_: direct copy */
1467159451Srodrigc		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1468159451Srodrigc		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1469153323Srodrigc	} else {
1470159451Srodrigc		lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1471153323Srodrigc		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1472159451Srodrigc		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
1473153323Srodrigc		*rrp = *lrp;
1474159451Srodrigc		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1475153323Srodrigc		INT_SET(key.br_startoff, ARCH_CONVERT,
1476153323Srodrigc			xfs_bmbt_disk_get_startoff(rrp));
1477153323Srodrigc		rkp = &key;
1478153323Srodrigc	}
1479159451Srodrigc	be16_add(&left->bb_numrecs, -1);
1480153323Srodrigc	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
1481159451Srodrigc	be16_add(&right->bb_numrecs, 1);
1482153323Srodrigc#ifdef DEBUG
1483153323Srodrigc	if (level > 0)
1484153323Srodrigc		xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1);
1485153323Srodrigc	else
1486153323Srodrigc		xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1);
1487153323Srodrigc#endif
1488153323Srodrigc	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
1489153323Srodrigc	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
1490153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1491153323Srodrigc		return error;
1492153323Srodrigc	}
1493153323Srodrigc	i = xfs_btree_lastrec(tcur, level);
1494153323Srodrigc	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1495153323Srodrigc	if ((error = xfs_bmbt_increment(tcur, level, &i))) {
1496153323Srodrigc		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
1497153323Srodrigc		goto error1;
1498153323Srodrigc	}
1499153323Srodrigc	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1500153323Srodrigc	if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) {
1501153323Srodrigc		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
1502153323Srodrigc		goto error1;
1503153323Srodrigc	}
1504153323Srodrigc	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
1505153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1506153323Srodrigc	*stat = 1;
1507153323Srodrigc	return 0;
1508153323Srodrigcerror0:
1509153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1510153323Srodrigcerror1:
1511153323Srodrigc	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
1512153323Srodrigc	return error;
1513153323Srodrigc}
1514153323Srodrigc
1515153323Srodrigc/*
1516153323Srodrigc * Determine the extent state.
1517153323Srodrigc */
1518153323Srodrigc/* ARGSUSED */
1519153323SrodrigcSTATIC xfs_exntst_t
1520153323Srodrigcxfs_extent_state(
1521153323Srodrigc	xfs_filblks_t		blks,
1522153323Srodrigc	int			extent_flag)
1523153323Srodrigc{
1524153323Srodrigc	if (extent_flag) {
1525153323Srodrigc		ASSERT(blks != 0);	/* saved for DMIG */
1526153323Srodrigc		return XFS_EXT_UNWRITTEN;
1527153323Srodrigc	}
1528153323Srodrigc	return XFS_EXT_NORM;
1529153323Srodrigc}
1530153323Srodrigc
1531153323Srodrigc
1532153323Srodrigc/*
1533153323Srodrigc * Split cur/level block in half.
1534153323Srodrigc * Return new block number and its first record (to be inserted into parent).
1535153323Srodrigc */
1536153323SrodrigcSTATIC int					/* error */
1537153323Srodrigcxfs_bmbt_split(
1538153323Srodrigc	xfs_btree_cur_t		*cur,
1539153323Srodrigc	int			level,
1540153323Srodrigc	xfs_fsblock_t		*bnop,
1541153323Srodrigc	xfs_bmbt_key_t		*keyp,
1542153323Srodrigc	xfs_btree_cur_t		**curp,
1543153323Srodrigc	int			*stat)		/* success/failure */
1544153323Srodrigc{
1545153323Srodrigc	xfs_alloc_arg_t		args;		/* block allocation args */
1546153323Srodrigc	int			error;		/* error return value */
1547153323Srodrigc#ifdef XFS_BMBT_TRACE
1548153323Srodrigc	static char		fname[] = "xfs_bmbt_split";
1549153323Srodrigc#endif
1550153323Srodrigc	int			i;		/* loop counter */
1551153323Srodrigc	xfs_fsblock_t		lbno;		/* left sibling block number */
1552153323Srodrigc	xfs_buf_t		*lbp;		/* left buffer pointer */
1553153323Srodrigc	xfs_bmbt_block_t	*left;		/* left btree block */
1554153323Srodrigc	xfs_bmbt_key_t		*lkp;		/* left btree key */
1555153323Srodrigc	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
1556153323Srodrigc	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
1557153323Srodrigc	xfs_buf_t		*rbp;		/* right buffer pointer */
1558153323Srodrigc	xfs_bmbt_block_t	*right;		/* right btree block */
1559153323Srodrigc	xfs_bmbt_key_t		*rkp;		/* right btree key */
1560153323Srodrigc	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
1561153323Srodrigc	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */
1562153323Srodrigc	xfs_buf_t		*rrbp;		/* right-right buffer pointer */
1563153323Srodrigc	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
1564153323Srodrigc
1565153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1566153323Srodrigc	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp);
1567153323Srodrigc	args.tp = cur->bc_tp;
1568153323Srodrigc	args.mp = cur->bc_mp;
1569153323Srodrigc	lbp = cur->bc_bufs[level];
1570153323Srodrigc	lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
1571153323Srodrigc	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1572153323Srodrigc	args.fsbno = cur->bc_private.b.firstblock;
1573153323Srodrigc	if (args.fsbno == NULLFSBLOCK) {
1574153323Srodrigc		args.fsbno = lbno;
1575153323Srodrigc		args.type = XFS_ALLOCTYPE_START_BNO;
1576153323Srodrigc	} else if (cur->bc_private.b.flist->xbf_low)
1577153323Srodrigc		args.type = XFS_ALLOCTYPE_FIRST_AG;
1578153323Srodrigc	else
1579153323Srodrigc		args.type = XFS_ALLOCTYPE_NEAR_BNO;
1580153323Srodrigc	args.mod = args.minleft = args.alignment = args.total = args.isfl =
1581153323Srodrigc		args.userdata = args.minalignslop = 0;
1582153323Srodrigc	args.minlen = args.maxlen = args.prod = 1;
1583153323Srodrigc	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
1584153323Srodrigc	if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
1585153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1586153323Srodrigc		return XFS_ERROR(ENOSPC);
1587153323Srodrigc	}
1588153323Srodrigc	if ((error = xfs_alloc_vextent(&args))) {
1589153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1590153323Srodrigc		return error;
1591153323Srodrigc	}
1592153323Srodrigc	if (args.fsbno == NULLFSBLOCK) {
1593153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1594153323Srodrigc		*stat = 0;
1595153323Srodrigc		return 0;
1596153323Srodrigc	}
1597153323Srodrigc	ASSERT(args.len == 1);
1598153323Srodrigc	cur->bc_private.b.firstblock = args.fsbno;
1599153323Srodrigc	cur->bc_private.b.allocated++;
1600153323Srodrigc	cur->bc_private.b.ip->i_d.di_nblocks++;
1601153323Srodrigc	xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
1602153323Srodrigc	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
1603153323Srodrigc			XFS_TRANS_DQ_BCOUNT, 1L);
1604153323Srodrigc	rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0);
1605153323Srodrigc	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1606153323Srodrigc#ifdef DEBUG
1607153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) {
1608153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1609153323Srodrigc		return error;
1610153323Srodrigc	}
1611153323Srodrigc#endif
1612159451Srodrigc	right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
1613159451Srodrigc	right->bb_level = left->bb_level;
1614159451Srodrigc	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
1615159451Srodrigc	if ((be16_to_cpu(left->bb_numrecs) & 1) &&
1616159451Srodrigc	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
1617159451Srodrigc		be16_add(&right->bb_numrecs, 1);
1618159451Srodrigc	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
1619153323Srodrigc	if (level > 0) {
1620153323Srodrigc		lkp = XFS_BMAP_KEY_IADDR(left, i, cur);
1621153323Srodrigc		lpp = XFS_BMAP_PTR_IADDR(left, i, cur);
1622153323Srodrigc		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1623153323Srodrigc		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1624153323Srodrigc#ifdef DEBUG
1625159451Srodrigc		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
1626153323Srodrigc			if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) {
1627153323Srodrigc				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1628153323Srodrigc				return error;
1629153323Srodrigc			}
1630153323Srodrigc		}
1631153323Srodrigc#endif
1632159451Srodrigc		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
1633159451Srodrigc		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
1634159451Srodrigc		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1635159451Srodrigc		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1636153323Srodrigc		keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT);
1637153323Srodrigc	} else {
1638153323Srodrigc		lrp = XFS_BMAP_REC_IADDR(left, i, cur);
1639153323Srodrigc		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1640159451Srodrigc		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
1641159451Srodrigc		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1642153323Srodrigc		keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp);
1643153323Srodrigc	}
1644159451Srodrigc	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
1645159451Srodrigc	right->bb_rightsib = left->bb_rightsib;
1646159451Srodrigc	left->bb_rightsib = cpu_to_be64(args.fsbno);
1647159451Srodrigc	right->bb_leftsib = cpu_to_be64(lbno);
1648153323Srodrigc	xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS);
1649153323Srodrigc	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
1650159451Srodrigc	if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) {
1651153323Srodrigc		if ((error = xfs_btree_read_bufl(args.mp, args.tp,
1652159451Srodrigc				be64_to_cpu(right->bb_rightsib), 0, &rrbp,
1653153323Srodrigc				XFS_BMAP_BTREE_REF))) {
1654153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1655153323Srodrigc			return error;
1656153323Srodrigc		}
1657153323Srodrigc		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
1658153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
1659153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1660153323Srodrigc			return error;
1661153323Srodrigc		}
1662159451Srodrigc		rrblock->bb_leftsib = cpu_to_be64(args.fsbno);
1663153323Srodrigc		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
1664153323Srodrigc	}
1665159451Srodrigc	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {
1666153323Srodrigc		xfs_btree_setbuf(cur, level, rbp);
1667159451Srodrigc		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);
1668153323Srodrigc	}
1669153323Srodrigc	if (level + 1 < cur->bc_nlevels) {
1670153323Srodrigc		if ((error = xfs_btree_dup_cursor(cur, curp))) {
1671153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1672153323Srodrigc			return error;
1673153323Srodrigc		}
1674153323Srodrigc		(*curp)->bc_ptrs[level + 1]++;
1675153323Srodrigc	}
1676153323Srodrigc	*bnop = args.fsbno;
1677153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1678153323Srodrigc	*stat = 1;
1679153323Srodrigc	return 0;
1680153323Srodrigc}
1681153323Srodrigc
1682153323Srodrigc
1683153323Srodrigc/*
1684153323Srodrigc * Update keys for the record.
1685153323Srodrigc */
1686153323SrodrigcSTATIC int
1687153323Srodrigcxfs_bmbt_updkey(
1688153323Srodrigc	xfs_btree_cur_t		*cur,
1689153323Srodrigc	xfs_bmbt_key_t		*keyp,	/* on-disk format */
1690153323Srodrigc	int			level)
1691153323Srodrigc{
1692153323Srodrigc	xfs_bmbt_block_t	*block;
1693153323Srodrigc	xfs_buf_t		*bp;
1694153323Srodrigc#ifdef DEBUG
1695153323Srodrigc	int			error;
1696153323Srodrigc#endif
1697153323Srodrigc#ifdef XFS_BMBT_TRACE
1698153323Srodrigc	static char		fname[] = "xfs_bmbt_updkey";
1699153323Srodrigc#endif
1700153323Srodrigc	xfs_bmbt_key_t		*kp;
1701153323Srodrigc	int			ptr;
1702153323Srodrigc
1703153323Srodrigc	ASSERT(level >= 1);
1704153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1705153323Srodrigc	XFS_BMBT_TRACE_ARGIK(cur, level, keyp);
1706153323Srodrigc	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
1707153323Srodrigc		block = xfs_bmbt_get_block(cur, level, &bp);
1708153323Srodrigc#ifdef DEBUG
1709153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
1710153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1711153323Srodrigc			return error;
1712153323Srodrigc		}
1713153323Srodrigc#endif
1714153323Srodrigc		ptr = cur->bc_ptrs[level];
1715153323Srodrigc		kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
1716153323Srodrigc		*kp = *keyp;
1717153323Srodrigc		xfs_bmbt_log_keys(cur, bp, ptr, ptr);
1718153323Srodrigc	}
1719153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1720153323Srodrigc	return 0;
1721153323Srodrigc}
1722153323Srodrigc
1723153323Srodrigc/*
1724153323Srodrigc * Convert on-disk form of btree root to in-memory form.
1725153323Srodrigc */
1726153323Srodrigcvoid
1727153323Srodrigcxfs_bmdr_to_bmbt(
1728153323Srodrigc	xfs_bmdr_block_t	*dblock,
1729153323Srodrigc	int			dblocklen,
1730153323Srodrigc	xfs_bmbt_block_t	*rblock,
1731153323Srodrigc	int			rblocklen)
1732153323Srodrigc{
1733153323Srodrigc	int			dmxr;
1734153323Srodrigc	xfs_bmbt_key_t		*fkp;
1735153323Srodrigc	xfs_bmbt_ptr_t		*fpp;
1736153323Srodrigc	xfs_bmbt_key_t		*tkp;
1737153323Srodrigc	xfs_bmbt_ptr_t		*tpp;
1738153323Srodrigc
1739159451Srodrigc	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
1740159451Srodrigc	rblock->bb_level = dblock->bb_level;
1741159451Srodrigc	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
1742159451Srodrigc	rblock->bb_numrecs = dblock->bb_numrecs;
1743159451Srodrigc	rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
1744159451Srodrigc	rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
1745153323Srodrigc	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
1746153323Srodrigc	fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
1747153323Srodrigc	tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
1748153323Srodrigc	fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
1749153323Srodrigc	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
1750159451Srodrigc	dmxr = be16_to_cpu(dblock->bb_numrecs);
1751153323Srodrigc	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
1752153323Srodrigc	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
1753153323Srodrigc}
1754153323Srodrigc
1755153323Srodrigc/*
1756153323Srodrigc * Decrement cursor by one record at the level.
1757153323Srodrigc * For nonzero levels the leaf-ward information is untouched.
1758153323Srodrigc */
1759153323Srodrigcint						/* error */
1760153323Srodrigcxfs_bmbt_decrement(
1761153323Srodrigc	xfs_btree_cur_t		*cur,
1762153323Srodrigc	int			level,
1763153323Srodrigc	int			*stat)		/* success/failure */
1764153323Srodrigc{
1765153323Srodrigc	xfs_bmbt_block_t	*block;
1766153323Srodrigc	xfs_buf_t		*bp;
1767153323Srodrigc	int			error;		/* error return value */
1768153323Srodrigc#ifdef XFS_BMBT_TRACE
1769153323Srodrigc	static char		fname[] = "xfs_bmbt_decrement";
1770153323Srodrigc#endif
1771153323Srodrigc	xfs_fsblock_t		fsbno;
1772153323Srodrigc	int			lev;
1773153323Srodrigc	xfs_mount_t		*mp;
1774153323Srodrigc	xfs_trans_t		*tp;
1775153323Srodrigc
1776153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1777153323Srodrigc	XFS_BMBT_TRACE_ARGI(cur, level);
1778153323Srodrigc	ASSERT(level < cur->bc_nlevels);
1779153323Srodrigc	if (level < cur->bc_nlevels - 1)
1780153323Srodrigc		xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
1781153323Srodrigc	if (--cur->bc_ptrs[level] > 0) {
1782153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1783153323Srodrigc		*stat = 1;
1784153323Srodrigc		return 0;
1785153323Srodrigc	}
1786153323Srodrigc	block = xfs_bmbt_get_block(cur, level, &bp);
1787153323Srodrigc#ifdef DEBUG
1788153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
1789153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1790153323Srodrigc		return error;
1791153323Srodrigc	}
1792153323Srodrigc#endif
1793159451Srodrigc	if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) {
1794153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1795153323Srodrigc		*stat = 0;
1796153323Srodrigc		return 0;
1797153323Srodrigc	}
1798153323Srodrigc	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1799153323Srodrigc		if (--cur->bc_ptrs[lev] > 0)
1800153323Srodrigc			break;
1801153323Srodrigc		if (lev < cur->bc_nlevels - 1)
1802153323Srodrigc			xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
1803153323Srodrigc	}
1804153323Srodrigc	if (lev == cur->bc_nlevels) {
1805153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1806153323Srodrigc		*stat = 0;
1807153323Srodrigc		return 0;
1808153323Srodrigc	}
1809153323Srodrigc	tp = cur->bc_tp;
1810153323Srodrigc	mp = cur->bc_mp;
1811153323Srodrigc	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
1812153323Srodrigc		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
1813153323Srodrigc		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
1814153323Srodrigc				XFS_BMAP_BTREE_REF))) {
1815153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1816153323Srodrigc			return error;
1817153323Srodrigc		}
1818153323Srodrigc		lev--;
1819153323Srodrigc		xfs_btree_setbuf(cur, lev, bp);
1820153323Srodrigc		block = XFS_BUF_TO_BMBT_BLOCK(bp);
1821153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
1822153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1823153323Srodrigc			return error;
1824153323Srodrigc		}
1825159451Srodrigc		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);
1826153323Srodrigc	}
1827153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1828153323Srodrigc	*stat = 1;
1829153323Srodrigc	return 0;
1830153323Srodrigc}
1831153323Srodrigc
1832153323Srodrigc/*
1833153323Srodrigc * Delete the record pointed to by cur.
1834153323Srodrigc */
1835153323Srodrigcint					/* error */
1836153323Srodrigcxfs_bmbt_delete(
1837153323Srodrigc	xfs_btree_cur_t	*cur,
1838153323Srodrigc	int		*stat)		/* success/failure */
1839153323Srodrigc{
1840153323Srodrigc	int		error;		/* error return value */
1841153323Srodrigc#ifdef XFS_BMBT_TRACE
1842153323Srodrigc	static char	fname[] = "xfs_bmbt_delete";
1843153323Srodrigc#endif
1844153323Srodrigc	int		i;
1845153323Srodrigc	int		level;
1846153323Srodrigc
1847153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1848153323Srodrigc	for (level = 0, i = 2; i == 2; level++) {
1849153323Srodrigc		if ((error = xfs_bmbt_delrec(cur, level, &i))) {
1850153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1851153323Srodrigc			return error;
1852153323Srodrigc		}
1853153323Srodrigc	}
1854153323Srodrigc	if (i == 0) {
1855153323Srodrigc		for (level = 1; level < cur->bc_nlevels; level++) {
1856153323Srodrigc			if (cur->bc_ptrs[level] == 0) {
1857153323Srodrigc				if ((error = xfs_bmbt_decrement(cur, level,
1858153323Srodrigc						&i))) {
1859153323Srodrigc					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1860153323Srodrigc					return error;
1861153323Srodrigc				}
1862153323Srodrigc				break;
1863153323Srodrigc			}
1864153323Srodrigc		}
1865153323Srodrigc	}
1866153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1867153323Srodrigc	*stat = i;
1868153323Srodrigc	return 0;
1869153323Srodrigc}
1870153323Srodrigc
1871153323Srodrigc/*
1872153323Srodrigc * Convert a compressed bmap extent record to an uncompressed form.
1873153323Srodrigc * This code must be in sync with the routines xfs_bmbt_get_startoff,
1874153323Srodrigc * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
1875153323Srodrigc */
1876153323Srodrigc
1877153323SrodrigcSTATIC __inline__ void
1878153323Srodrigc__xfs_bmbt_get_all(
1879153323Srodrigc		__uint64_t l0,
1880153323Srodrigc		__uint64_t l1,
1881153323Srodrigc		xfs_bmbt_irec_t *s)
1882153323Srodrigc{
1883153323Srodrigc	int	ext_flag;
1884153323Srodrigc	xfs_exntst_t st;
1885153323Srodrigc
1886153323Srodrigc	ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
1887153323Srodrigc	s->br_startoff = ((xfs_fileoff_t)l0 &
1888153323Srodrigc			   XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1889153323Srodrigc#if XFS_BIG_BLKNOS
1890153323Srodrigc	s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |
1891153323Srodrigc			   (((xfs_fsblock_t)l1) >> 21);
1892153323Srodrigc#else
1893153323Srodrigc#ifdef DEBUG
1894153323Srodrigc	{
1895153323Srodrigc		xfs_dfsbno_t	b;
1896153323Srodrigc
1897153323Srodrigc		b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |
1898153323Srodrigc		    (((xfs_dfsbno_t)l1) >> 21);
1899153323Srodrigc		ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
1900153323Srodrigc		s->br_startblock = (xfs_fsblock_t)b;
1901153323Srodrigc	}
1902153323Srodrigc#else	/* !DEBUG */
1903153323Srodrigc	s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
1904153323Srodrigc#endif	/* DEBUG */
1905153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
1906153323Srodrigc	s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));
1907153323Srodrigc	/* This is xfs_extent_state() in-line */
1908153323Srodrigc	if (ext_flag) {
1909153323Srodrigc		ASSERT(s->br_blockcount != 0);	/* saved for DMIG */
1910153323Srodrigc		st = XFS_EXT_UNWRITTEN;
1911153323Srodrigc	} else
1912153323Srodrigc		st = XFS_EXT_NORM;
1913153323Srodrigc	s->br_state = st;
1914153323Srodrigc}
1915153323Srodrigc
1916153323Srodrigcvoid
1917153323Srodrigcxfs_bmbt_get_all(
1918153323Srodrigc	xfs_bmbt_rec_t	*r,
1919153323Srodrigc	xfs_bmbt_irec_t *s)
1920153323Srodrigc{
1921153323Srodrigc	__xfs_bmbt_get_all(r->l0, r->l1, s);
1922153323Srodrigc}
1923153323Srodrigc
1924153323Srodrigc/*
1925153323Srodrigc * Get the block pointer for the given level of the cursor.
1926153323Srodrigc * Fill in the buffer pointer, if applicable.
1927153323Srodrigc */
1928153323Srodrigcxfs_bmbt_block_t *
1929153323Srodrigcxfs_bmbt_get_block(
1930153323Srodrigc	xfs_btree_cur_t		*cur,
1931153323Srodrigc	int			level,
1932153323Srodrigc	xfs_buf_t		**bpp)
1933153323Srodrigc{
1934153323Srodrigc	xfs_ifork_t		*ifp;
1935153323Srodrigc	xfs_bmbt_block_t	*rval;
1936153323Srodrigc
1937153323Srodrigc	if (level < cur->bc_nlevels - 1) {
1938153323Srodrigc		*bpp = cur->bc_bufs[level];
1939153323Srodrigc		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
1940153323Srodrigc	} else {
1941159451Srodrigc		*bpp = NULL;
1942153323Srodrigc		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
1943153323Srodrigc			cur->bc_private.b.whichfork);
1944153323Srodrigc		rval = ifp->if_broot;
1945153323Srodrigc	}
1946153323Srodrigc	return rval;
1947153323Srodrigc}
1948153323Srodrigc
1949153323Srodrigc/*
1950153323Srodrigc * Extract the blockcount field from an in memory bmap extent record.
1951153323Srodrigc */
1952153323Srodrigcxfs_filblks_t
1953153323Srodrigcxfs_bmbt_get_blockcount(
1954153323Srodrigc	xfs_bmbt_rec_t	*r)
1955153323Srodrigc{
1956153323Srodrigc	return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
1957153323Srodrigc}
1958153323Srodrigc
1959153323Srodrigc/*
1960153323Srodrigc * Extract the startblock field from an in memory bmap extent record.
1961153323Srodrigc */
1962153323Srodrigcxfs_fsblock_t
1963153323Srodrigcxfs_bmbt_get_startblock(
1964153323Srodrigc	xfs_bmbt_rec_t	*r)
1965153323Srodrigc{
1966153323Srodrigc#if XFS_BIG_BLKNOS
1967153323Srodrigc	return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
1968153323Srodrigc	       (((xfs_fsblock_t)r->l1) >> 21);
1969153323Srodrigc#else
1970153323Srodrigc#ifdef DEBUG
1971153323Srodrigc	xfs_dfsbno_t	b;
1972153323Srodrigc
1973153323Srodrigc	b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |
1974153323Srodrigc	    (((xfs_dfsbno_t)r->l1) >> 21);
1975153323Srodrigc	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
1976153323Srodrigc	return (xfs_fsblock_t)b;
1977153323Srodrigc#else	/* !DEBUG */
1978153323Srodrigc	return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
1979153323Srodrigc#endif	/* DEBUG */
1980153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
1981153323Srodrigc}
1982153323Srodrigc
1983153323Srodrigc/*
1984153323Srodrigc * Extract the startoff field from an in memory bmap extent record.
1985153323Srodrigc */
1986153323Srodrigcxfs_fileoff_t
1987153323Srodrigcxfs_bmbt_get_startoff(
1988153323Srodrigc	xfs_bmbt_rec_t	*r)
1989153323Srodrigc{
1990153323Srodrigc	return ((xfs_fileoff_t)r->l0 &
1991153323Srodrigc		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1992153323Srodrigc}
1993153323Srodrigc
1994153323Srodrigcxfs_exntst_t
1995153323Srodrigcxfs_bmbt_get_state(
1996153323Srodrigc	xfs_bmbt_rec_t	*r)
1997153323Srodrigc{
1998153323Srodrigc	int	ext_flag;
1999153323Srodrigc
2000153323Srodrigc	ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
2001153323Srodrigc	return xfs_extent_state(xfs_bmbt_get_blockcount(r),
2002153323Srodrigc				ext_flag);
2003153323Srodrigc}
2004153323Srodrigc
2005159451Srodrigc#ifndef XFS_NATIVE_HOST
2006153323Srodrigc/* Endian flipping versions of the bmbt extraction functions */
2007153323Srodrigcvoid
2008153323Srodrigcxfs_bmbt_disk_get_all(
2009153323Srodrigc	xfs_bmbt_rec_t	*r,
2010153323Srodrigc	xfs_bmbt_irec_t *s)
2011153323Srodrigc{
2012153323Srodrigc	__uint64_t	l0, l1;
2013153323Srodrigc
2014153323Srodrigc	l0 = INT_GET(r->l0, ARCH_CONVERT);
2015153323Srodrigc	l1 = INT_GET(r->l1, ARCH_CONVERT);
2016153323Srodrigc
2017153323Srodrigc	__xfs_bmbt_get_all(l0, l1, s);
2018153323Srodrigc}
2019153323Srodrigc
2020153323Srodrigc/*
2021153323Srodrigc * Extract the blockcount field from an on disk bmap extent record.
2022153323Srodrigc */
2023153323Srodrigcxfs_filblks_t
2024153323Srodrigcxfs_bmbt_disk_get_blockcount(
2025153323Srodrigc	xfs_bmbt_rec_t	*r)
2026153323Srodrigc{
2027153323Srodrigc	return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
2028153323Srodrigc}
2029153323Srodrigc
2030153323Srodrigc/*
2031153323Srodrigc * Extract the startblock field from an on disk bmap extent record.
2032153323Srodrigc */
2033153323Srodrigcxfs_fsblock_t
2034153323Srodrigcxfs_bmbt_disk_get_startblock(
2035153323Srodrigc	xfs_bmbt_rec_t	*r)
2036153323Srodrigc{
2037153323Srodrigc#if XFS_BIG_BLKNOS
2038153323Srodrigc	return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
2039153323Srodrigc	       (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
2040153323Srodrigc#else
2041153323Srodrigc#ifdef DEBUG
2042153323Srodrigc	xfs_dfsbno_t	b;
2043153323Srodrigc
2044153323Srodrigc	b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
2045153323Srodrigc	    (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
2046153323Srodrigc	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
2047153323Srodrigc	return (xfs_fsblock_t)b;
2048153323Srodrigc#else	/* !DEBUG */
2049153323Srodrigc	return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
2050153323Srodrigc#endif	/* DEBUG */
2051153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
2052153323Srodrigc}
2053153323Srodrigc
2054153323Srodrigc/*
2055153323Srodrigc * Extract the startoff field from a disk format bmap extent record.
2056153323Srodrigc */
2057153323Srodrigcxfs_fileoff_t
2058153323Srodrigcxfs_bmbt_disk_get_startoff(
2059153323Srodrigc	xfs_bmbt_rec_t	*r)
2060153323Srodrigc{
2061153323Srodrigc	return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
2062153323Srodrigc		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
2063153323Srodrigc}
2064153323Srodrigc
2065153323Srodrigcxfs_exntst_t
2066153323Srodrigcxfs_bmbt_disk_get_state(
2067153323Srodrigc	xfs_bmbt_rec_t  *r)
2068153323Srodrigc{
2069153323Srodrigc	int	ext_flag;
2070153323Srodrigc
2071153323Srodrigc	ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN));
2072153323Srodrigc	return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
2073153323Srodrigc				ext_flag);
2074153323Srodrigc}
2075159451Srodrigc#endif /* XFS_NATIVE_HOST */
2076153323Srodrigc
2077153323Srodrigc
2078153323Srodrigc/*
2079153323Srodrigc * Increment cursor by one record at the level.
2080153323Srodrigc * For nonzero levels the leaf-ward information is untouched.
2081153323Srodrigc */
2082153323Srodrigcint						/* error */
2083153323Srodrigcxfs_bmbt_increment(
2084153323Srodrigc	xfs_btree_cur_t		*cur,
2085153323Srodrigc	int			level,
2086153323Srodrigc	int			*stat)		/* success/failure */
2087153323Srodrigc{
2088153323Srodrigc	xfs_bmbt_block_t	*block;
2089153323Srodrigc	xfs_buf_t		*bp;
2090153323Srodrigc	int			error;		/* error return value */
2091153323Srodrigc#ifdef XFS_BMBT_TRACE
2092153323Srodrigc	static char		fname[] = "xfs_bmbt_increment";
2093153323Srodrigc#endif
2094153323Srodrigc	xfs_fsblock_t		fsbno;
2095153323Srodrigc	int			lev;
2096153323Srodrigc	xfs_mount_t		*mp;
2097153323Srodrigc	xfs_trans_t		*tp;
2098153323Srodrigc
2099153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2100153323Srodrigc	XFS_BMBT_TRACE_ARGI(cur, level);
2101153323Srodrigc	ASSERT(level < cur->bc_nlevels);
2102153323Srodrigc	if (level < cur->bc_nlevels - 1)
2103153323Srodrigc		xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
2104153323Srodrigc	block = xfs_bmbt_get_block(cur, level, &bp);
2105153323Srodrigc#ifdef DEBUG
2106153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
2107153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2108153323Srodrigc		return error;
2109153323Srodrigc	}
2110153323Srodrigc#endif
2111159451Srodrigc	if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
2112153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2113153323Srodrigc		*stat = 1;
2114153323Srodrigc		return 0;
2115153323Srodrigc	}
2116159451Srodrigc	if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) {
2117153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2118153323Srodrigc		*stat = 0;
2119153323Srodrigc		return 0;
2120153323Srodrigc	}
2121153323Srodrigc	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
2122153323Srodrigc		block = xfs_bmbt_get_block(cur, lev, &bp);
2123153323Srodrigc#ifdef DEBUG
2124153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
2125153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2126153323Srodrigc			return error;
2127153323Srodrigc		}
2128153323Srodrigc#endif
2129159451Srodrigc		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
2130153323Srodrigc			break;
2131153323Srodrigc		if (lev < cur->bc_nlevels - 1)
2132153323Srodrigc			xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
2133153323Srodrigc	}
2134153323Srodrigc	if (lev == cur->bc_nlevels) {
2135153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2136153323Srodrigc		*stat = 0;
2137153323Srodrigc		return 0;
2138153323Srodrigc	}
2139153323Srodrigc	tp = cur->bc_tp;
2140153323Srodrigc	mp = cur->bc_mp;
2141153323Srodrigc	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
2142153323Srodrigc		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
2143153323Srodrigc		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
2144153323Srodrigc				XFS_BMAP_BTREE_REF))) {
2145153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2146153323Srodrigc			return error;
2147153323Srodrigc		}
2148153323Srodrigc		lev--;
2149153323Srodrigc		xfs_btree_setbuf(cur, lev, bp);
2150153323Srodrigc		block = XFS_BUF_TO_BMBT_BLOCK(bp);
2151153323Srodrigc		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
2152153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2153153323Srodrigc			return error;
2154153323Srodrigc		}
2155153323Srodrigc		cur->bc_ptrs[lev] = 1;
2156153323Srodrigc	}
2157153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2158153323Srodrigc	*stat = 1;
2159153323Srodrigc	return 0;
2160153323Srodrigc}
2161153323Srodrigc
2162153323Srodrigc/*
2163153323Srodrigc * Insert the current record at the point referenced by cur.
2164153323Srodrigc */
2165153323Srodrigcint					/* error */
2166153323Srodrigcxfs_bmbt_insert(
2167153323Srodrigc	xfs_btree_cur_t	*cur,
2168153323Srodrigc	int		*stat)		/* success/failure */
2169153323Srodrigc{
2170153323Srodrigc	int		error;		/* error return value */
2171153323Srodrigc#ifdef XFS_BMBT_TRACE
2172153323Srodrigc	static char	fname[] = "xfs_bmbt_insert";
2173153323Srodrigc#endif
2174153323Srodrigc	int		i;
2175153323Srodrigc	int		level;
2176153323Srodrigc	xfs_fsblock_t	nbno;
2177153323Srodrigc	xfs_btree_cur_t	*ncur;
2178153323Srodrigc	xfs_bmbt_rec_t	nrec;
2179153323Srodrigc	xfs_btree_cur_t	*pcur;
2180153323Srodrigc
2181153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2182153323Srodrigc	level = 0;
2183153323Srodrigc	nbno = NULLFSBLOCK;
2184153323Srodrigc	xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
2185153323Srodrigc	ncur = (xfs_btree_cur_t *)0;
2186153323Srodrigc	pcur = cur;
2187153323Srodrigc	do {
2188153323Srodrigc		if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
2189153323Srodrigc				&i))) {
2190153323Srodrigc			if (pcur != cur)
2191153323Srodrigc				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2192153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2193153323Srodrigc			return error;
2194153323Srodrigc		}
2195153323Srodrigc		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2196153323Srodrigc		if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
2197153323Srodrigc			cur->bc_nlevels = pcur->bc_nlevels;
2198153323Srodrigc			cur->bc_private.b.allocated +=
2199153323Srodrigc				pcur->bc_private.b.allocated;
2200153323Srodrigc			pcur->bc_private.b.allocated = 0;
2201153323Srodrigc			ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) ||
2202153323Srodrigc			       (cur->bc_private.b.ip->i_d.di_flags &
2203153323Srodrigc				XFS_DIFLAG_REALTIME));
2204153323Srodrigc			cur->bc_private.b.firstblock =
2205153323Srodrigc				pcur->bc_private.b.firstblock;
2206153323Srodrigc			ASSERT(cur->bc_private.b.flist ==
2207153323Srodrigc			       pcur->bc_private.b.flist);
2208153323Srodrigc			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2209153323Srodrigc		}
2210153323Srodrigc		if (ncur) {
2211153323Srodrigc			pcur = ncur;
2212153323Srodrigc			ncur = (xfs_btree_cur_t *)0;
2213153323Srodrigc		}
2214153323Srodrigc	} while (nbno != NULLFSBLOCK);
2215153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2216153323Srodrigc	*stat = i;
2217153323Srodrigc	return 0;
2218153323Srodrigcerror0:
2219153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2220153323Srodrigc	return error;
2221153323Srodrigc}
2222153323Srodrigc
2223153323Srodrigc/*
2224153323Srodrigc * Log fields from the btree block header.
2225153323Srodrigc */
2226153323Srodrigcvoid
2227153323Srodrigcxfs_bmbt_log_block(
2228153323Srodrigc	xfs_btree_cur_t		*cur,
2229153323Srodrigc	xfs_buf_t		*bp,
2230153323Srodrigc	int			fields)
2231153323Srodrigc{
2232153323Srodrigc	int			first;
2233153323Srodrigc#ifdef XFS_BMBT_TRACE
2234153323Srodrigc	static char		fname[] = "xfs_bmbt_log_block";
2235153323Srodrigc#endif
2236153323Srodrigc	int			last;
2237153323Srodrigc	xfs_trans_t		*tp;
2238153323Srodrigc	static const short	offsets[] = {
2239153323Srodrigc		offsetof(xfs_bmbt_block_t, bb_magic),
2240153323Srodrigc		offsetof(xfs_bmbt_block_t, bb_level),
2241153323Srodrigc		offsetof(xfs_bmbt_block_t, bb_numrecs),
2242153323Srodrigc		offsetof(xfs_bmbt_block_t, bb_leftsib),
2243153323Srodrigc		offsetof(xfs_bmbt_block_t, bb_rightsib),
2244153323Srodrigc		sizeof(xfs_bmbt_block_t)
2245153323Srodrigc	};
2246153323Srodrigc
2247153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2248153323Srodrigc	XFS_BMBT_TRACE_ARGBI(cur, bp, fields);
2249153323Srodrigc	tp = cur->bc_tp;
2250153323Srodrigc	if (bp) {
2251153323Srodrigc		xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first,
2252153323Srodrigc				  &last);
2253153323Srodrigc		xfs_trans_log_buf(tp, bp, first, last);
2254153323Srodrigc	} else
2255153323Srodrigc		xfs_trans_log_inode(tp, cur->bc_private.b.ip,
2256153323Srodrigc			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
2257153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2258153323Srodrigc}
2259153323Srodrigc
2260153323Srodrigc/*
2261153323Srodrigc * Log record values from the btree block.
2262153323Srodrigc */
2263153323Srodrigcvoid
2264153323Srodrigcxfs_bmbt_log_recs(
2265153323Srodrigc	xfs_btree_cur_t		*cur,
2266153323Srodrigc	xfs_buf_t		*bp,
2267153323Srodrigc	int			rfirst,
2268153323Srodrigc	int			rlast)
2269153323Srodrigc{
2270153323Srodrigc	xfs_bmbt_block_t	*block;
2271153323Srodrigc	int			first;
2272153323Srodrigc#ifdef XFS_BMBT_TRACE
2273153323Srodrigc	static char		fname[] = "xfs_bmbt_log_recs";
2274153323Srodrigc#endif
2275153323Srodrigc	int			last;
2276153323Srodrigc	xfs_bmbt_rec_t		*rp;
2277153323Srodrigc	xfs_trans_t		*tp;
2278153323Srodrigc
2279153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2280153323Srodrigc	XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
2281153323Srodrigc	ASSERT(bp);
2282153323Srodrigc	tp = cur->bc_tp;
2283153323Srodrigc	block = XFS_BUF_TO_BMBT_BLOCK(bp);
2284153323Srodrigc	rp = XFS_BMAP_REC_DADDR(block, 1, cur);
2285153323Srodrigc	first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
2286153323Srodrigc	last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
2287153323Srodrigc	xfs_trans_log_buf(tp, bp, first, last);
2288153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2289153323Srodrigc}
2290153323Srodrigc
2291153323Srodrigcint					/* error */
2292153323Srodrigcxfs_bmbt_lookup_eq(
2293153323Srodrigc	xfs_btree_cur_t	*cur,
2294153323Srodrigc	xfs_fileoff_t	off,
2295153323Srodrigc	xfs_fsblock_t	bno,
2296153323Srodrigc	xfs_filblks_t	len,
2297153323Srodrigc	int		*stat)		/* success/failure */
2298153323Srodrigc{
2299153323Srodrigc	cur->bc_rec.b.br_startoff = off;
2300153323Srodrigc	cur->bc_rec.b.br_startblock = bno;
2301153323Srodrigc	cur->bc_rec.b.br_blockcount = len;
2302153323Srodrigc	return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat);
2303153323Srodrigc}
2304153323Srodrigc
2305153323Srodrigcint					/* error */
2306153323Srodrigcxfs_bmbt_lookup_ge(
2307153323Srodrigc	xfs_btree_cur_t	*cur,
2308153323Srodrigc	xfs_fileoff_t	off,
2309153323Srodrigc	xfs_fsblock_t	bno,
2310153323Srodrigc	xfs_filblks_t	len,
2311153323Srodrigc	int		*stat)		/* success/failure */
2312153323Srodrigc{
2313153323Srodrigc	cur->bc_rec.b.br_startoff = off;
2314153323Srodrigc	cur->bc_rec.b.br_startblock = bno;
2315153323Srodrigc	cur->bc_rec.b.br_blockcount = len;
2316153323Srodrigc	return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
2317153323Srodrigc}
2318153323Srodrigc
2319153323Srodrigc/*
2320153323Srodrigc * Give the bmap btree a new root block.  Copy the old broot contents
2321153323Srodrigc * down into a real block and make the broot point to it.
2322153323Srodrigc */
2323153323Srodrigcint						/* error */
2324153323Srodrigcxfs_bmbt_newroot(
2325153323Srodrigc	xfs_btree_cur_t		*cur,		/* btree cursor */
2326153323Srodrigc	int			*logflags,	/* logging flags for inode */
2327153323Srodrigc	int			*stat)		/* return status - 0 fail */
2328153323Srodrigc{
2329153323Srodrigc	xfs_alloc_arg_t		args;		/* allocation arguments */
2330153323Srodrigc	xfs_bmbt_block_t	*block;		/* bmap btree block */
2331153323Srodrigc	xfs_buf_t		*bp;		/* buffer for block */
2332153323Srodrigc	xfs_bmbt_block_t	*cblock;	/* child btree block */
2333153323Srodrigc	xfs_bmbt_key_t		*ckp;		/* child key pointer */
2334153323Srodrigc	xfs_bmbt_ptr_t		*cpp;		/* child ptr pointer */
2335153323Srodrigc	int			error;		/* error return code */
2336153323Srodrigc#ifdef XFS_BMBT_TRACE
2337153323Srodrigc	static char		fname[] = "xfs_bmbt_newroot";
2338153323Srodrigc#endif
2339153323Srodrigc#ifdef DEBUG
2340153323Srodrigc	int			i;		/* loop counter */
2341153323Srodrigc#endif
2342153323Srodrigc	xfs_bmbt_key_t		*kp;		/* pointer to bmap btree key */
2343153323Srodrigc	int			level;		/* btree level */
2344153323Srodrigc	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
2345153323Srodrigc
2346153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2347153323Srodrigc	level = cur->bc_nlevels - 1;
2348153323Srodrigc	block = xfs_bmbt_get_block(cur, level, &bp);
2349153323Srodrigc	/*
2350153323Srodrigc	 * Copy the root into a real block.
2351153323Srodrigc	 */
2352153323Srodrigc	args.mp = cur->bc_mp;
2353153323Srodrigc	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
2354153323Srodrigc	args.tp = cur->bc_tp;
2355153323Srodrigc	args.fsbno = cur->bc_private.b.firstblock;
2356153323Srodrigc	args.mod = args.minleft = args.alignment = args.total = args.isfl =
2357153323Srodrigc		args.userdata = args.minalignslop = 0;
2358153323Srodrigc	args.minlen = args.maxlen = args.prod = 1;
2359153323Srodrigc	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
2360153323Srodrigc	if (args.fsbno == NULLFSBLOCK) {
2361153323Srodrigc#ifdef DEBUG
2362153323Srodrigc		if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
2363153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2364153323Srodrigc			return error;
2365153323Srodrigc		}
2366153323Srodrigc#endif
2367153323Srodrigc		args.fsbno = INT_GET(*pp, ARCH_CONVERT);
2368153323Srodrigc		args.type = XFS_ALLOCTYPE_START_BNO;
2369153323Srodrigc	} else if (args.wasdel)
2370153323Srodrigc		args.type = XFS_ALLOCTYPE_FIRST_AG;
2371153323Srodrigc	else
2372153323Srodrigc		args.type = XFS_ALLOCTYPE_NEAR_BNO;
2373153323Srodrigc	if ((error = xfs_alloc_vextent(&args))) {
2374153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2375153323Srodrigc		return error;
2376153323Srodrigc	}
2377153323Srodrigc	if (args.fsbno == NULLFSBLOCK) {
2378153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2379153323Srodrigc		*stat = 0;
2380153323Srodrigc		return 0;
2381153323Srodrigc	}
2382153323Srodrigc	ASSERT(args.len == 1);
2383153323Srodrigc	cur->bc_private.b.firstblock = args.fsbno;
2384153323Srodrigc	cur->bc_private.b.allocated++;
2385153323Srodrigc	cur->bc_private.b.ip->i_d.di_nblocks++;
2386153323Srodrigc	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
2387153323Srodrigc			  XFS_TRANS_DQ_BCOUNT, 1L);
2388153323Srodrigc	bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
2389153323Srodrigc	cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
2390153323Srodrigc	*cblock = *block;
2391159451Srodrigc	be16_add(&block->bb_level, 1);
2392159451Srodrigc	block->bb_numrecs = cpu_to_be16(1);
2393153323Srodrigc	cur->bc_nlevels++;
2394153323Srodrigc	cur->bc_ptrs[level + 1] = 1;
2395153323Srodrigc	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
2396153323Srodrigc	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
2397159451Srodrigc	memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp));
2398153323Srodrigc	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
2399153323Srodrigc#ifdef DEBUG
2400159451Srodrigc	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
2401153323Srodrigc		if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
2402153323Srodrigc			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2403153323Srodrigc			return error;
2404153323Srodrigc		}
2405153323Srodrigc	}
2406153323Srodrigc#endif
2407159451Srodrigc	memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
2408153323Srodrigc#ifdef DEBUG
2409153323Srodrigc	if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno,
2410153323Srodrigc			level))) {
2411153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2412153323Srodrigc		return error;
2413153323Srodrigc	}
2414153323Srodrigc#endif
2415153323Srodrigc	INT_SET(*pp, ARCH_CONVERT, args.fsbno);
2416159451Srodrigc	xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
2417153323Srodrigc		cur->bc_private.b.whichfork);
2418153323Srodrigc	xfs_btree_setbuf(cur, level, bp);
2419153323Srodrigc	/*
2420153323Srodrigc	 * Do all this logging at the end so that
2421153323Srodrigc	 * the root is at the right level.
2422153323Srodrigc	 */
2423153323Srodrigc	xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS);
2424159451Srodrigc	xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
2425159451Srodrigc	xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
2426153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2427153323Srodrigc	*logflags |=
2428153323Srodrigc		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
2429153323Srodrigc	*stat = 1;
2430153323Srodrigc	return 0;
2431153323Srodrigc}
2432153323Srodrigc
2433153323Srodrigc/*
2434153323Srodrigc * Set all the fields in a bmap extent record from the uncompressed form.
2435153323Srodrigc */
2436153323Srodrigcvoid
2437153323Srodrigcxfs_bmbt_set_all(
2438153323Srodrigc	xfs_bmbt_rec_t	*r,
2439153323Srodrigc	xfs_bmbt_irec_t	*s)
2440153323Srodrigc{
2441153323Srodrigc	int	extent_flag;
2442153323Srodrigc
2443153323Srodrigc	ASSERT((s->br_state == XFS_EXT_NORM) ||
2444153323Srodrigc		(s->br_state == XFS_EXT_UNWRITTEN));
2445153323Srodrigc	extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
2446153323Srodrigc	ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
2447153323Srodrigc	ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
2448153323Srodrigc#if XFS_BIG_BLKNOS
2449153323Srodrigc	ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
2450153323Srodrigc	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2451153323Srodrigc		 ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2452153323Srodrigc		 ((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
2453153323Srodrigc	r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2454153323Srodrigc		 ((xfs_bmbt_rec_base_t)s->br_blockcount &
2455153323Srodrigc		 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2456153323Srodrigc#else	/* !XFS_BIG_BLKNOS */
2457153323Srodrigc	if (ISNULLSTARTBLOCK(s->br_startblock)) {
2458153323Srodrigc		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2459153323Srodrigc			((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2460153323Srodrigc			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2461153323Srodrigc		r->l1 = XFS_MASK64HI(11) |
2462153323Srodrigc			  ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2463153323Srodrigc			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2464153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2465153323Srodrigc	} else {
2466153323Srodrigc		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2467153323Srodrigc			((xfs_bmbt_rec_base_t)s->br_startoff << 9);
2468153323Srodrigc		r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2469153323Srodrigc			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2470153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2471153323Srodrigc	}
2472153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
2473153323Srodrigc}
2474153323Srodrigc
2475153323Srodrigc/*
2476153323Srodrigc * Set all the fields in a bmap extent record from the arguments.
2477153323Srodrigc */
2478153323Srodrigcvoid
2479153323Srodrigcxfs_bmbt_set_allf(
2480153323Srodrigc	xfs_bmbt_rec_t	*r,
2481153323Srodrigc	xfs_fileoff_t	o,
2482153323Srodrigc	xfs_fsblock_t	b,
2483153323Srodrigc	xfs_filblks_t	c,
2484153323Srodrigc	xfs_exntst_t	v)
2485153323Srodrigc{
2486153323Srodrigc	int	extent_flag;
2487153323Srodrigc
2488153323Srodrigc	ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
2489153323Srodrigc	extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
2490153323Srodrigc	ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
2491153323Srodrigc	ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
2492153323Srodrigc#if XFS_BIG_BLKNOS
2493153323Srodrigc	ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
2494153323Srodrigc	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2495153323Srodrigc		((xfs_bmbt_rec_base_t)o << 9) |
2496153323Srodrigc		((xfs_bmbt_rec_base_t)b >> 43);
2497153323Srodrigc	r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
2498153323Srodrigc		((xfs_bmbt_rec_base_t)c &
2499153323Srodrigc		(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2500153323Srodrigc#else	/* !XFS_BIG_BLKNOS */
2501153323Srodrigc	if (ISNULLSTARTBLOCK(b)) {
2502153323Srodrigc		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2503153323Srodrigc			((xfs_bmbt_rec_base_t)o << 9) |
2504153323Srodrigc			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2505153323Srodrigc		r->l1 = XFS_MASK64HI(11) |
2506153323Srodrigc			  ((xfs_bmbt_rec_base_t)b << 21) |
2507153323Srodrigc			  ((xfs_bmbt_rec_base_t)c &
2508153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2509153323Srodrigc	} else {
2510153323Srodrigc		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2511153323Srodrigc			((xfs_bmbt_rec_base_t)o << 9);
2512153323Srodrigc		r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
2513153323Srodrigc			 ((xfs_bmbt_rec_base_t)c &
2514153323Srodrigc			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2515153323Srodrigc	}
2516153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
2517153323Srodrigc}
2518153323Srodrigc
2519159451Srodrigc#ifndef XFS_NATIVE_HOST
2520153323Srodrigc/*
2521153323Srodrigc * Set all the fields in a bmap extent record from the uncompressed form.
2522153323Srodrigc */
2523153323Srodrigcvoid
2524153323Srodrigcxfs_bmbt_disk_set_all(
2525153323Srodrigc	xfs_bmbt_rec_t	*r,
2526153323Srodrigc	xfs_bmbt_irec_t *s)
2527153323Srodrigc{
2528153323Srodrigc	int	extent_flag;
2529153323Srodrigc
2530153323Srodrigc	ASSERT((s->br_state == XFS_EXT_NORM) ||
2531153323Srodrigc		(s->br_state == XFS_EXT_UNWRITTEN));
2532153323Srodrigc	extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
2533153323Srodrigc	ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
2534153323Srodrigc	ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
2535153323Srodrigc#if XFS_BIG_BLKNOS
2536153323Srodrigc	ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
2537153323Srodrigc	INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2538153323Srodrigc		  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2539153323Srodrigc		  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
2540153323Srodrigc	INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2541153323Srodrigc		  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2542153323Srodrigc		   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2543153323Srodrigc#else	/* !XFS_BIG_BLKNOS */
2544153323Srodrigc	if (ISNULLSTARTBLOCK(s->br_startblock)) {
2545153323Srodrigc		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2546153323Srodrigc			((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2547153323Srodrigc			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2548153323Srodrigc		INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
2549153323Srodrigc			  ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2550153323Srodrigc			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2551153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2552153323Srodrigc	} else {
2553153323Srodrigc		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2554153323Srodrigc			((xfs_bmbt_rec_base_t)s->br_startoff << 9));
2555153323Srodrigc		INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2556153323Srodrigc			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2557153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2558153323Srodrigc	}
2559153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
2560153323Srodrigc}
2561153323Srodrigc
2562153323Srodrigc/*
2563153323Srodrigc * Set all the fields in a disk format bmap extent record from the arguments.
2564153323Srodrigc */
2565153323Srodrigcvoid
2566153323Srodrigcxfs_bmbt_disk_set_allf(
2567153323Srodrigc	xfs_bmbt_rec_t	*r,
2568153323Srodrigc	xfs_fileoff_t	o,
2569153323Srodrigc	xfs_fsblock_t	b,
2570153323Srodrigc	xfs_filblks_t	c,
2571153323Srodrigc	xfs_exntst_t	v)
2572153323Srodrigc{
2573153323Srodrigc	int	extent_flag;
2574153323Srodrigc
2575153323Srodrigc	ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
2576153323Srodrigc	extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
2577153323Srodrigc	ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
2578153323Srodrigc	ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
2579153323Srodrigc#if XFS_BIG_BLKNOS
2580153323Srodrigc	ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
2581153323Srodrigc	INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2582153323Srodrigc		((xfs_bmbt_rec_base_t)o << 9) |
2583153323Srodrigc		((xfs_bmbt_rec_base_t)b >> 43));
2584153323Srodrigc	INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
2585153323Srodrigc		  ((xfs_bmbt_rec_base_t)c &
2586153323Srodrigc		   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2587153323Srodrigc#else	/* !XFS_BIG_BLKNOS */
2588153323Srodrigc	if (ISNULLSTARTBLOCK(b)) {
2589153323Srodrigc		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2590153323Srodrigc			((xfs_bmbt_rec_base_t)o << 9) |
2591153323Srodrigc			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2592153323Srodrigc		INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
2593153323Srodrigc			  ((xfs_bmbt_rec_base_t)b << 21) |
2594153323Srodrigc			  ((xfs_bmbt_rec_base_t)c &
2595153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2596153323Srodrigc	} else {
2597153323Srodrigc		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2598153323Srodrigc			((xfs_bmbt_rec_base_t)o << 9));
2599153323Srodrigc		INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
2600153323Srodrigc			  ((xfs_bmbt_rec_base_t)c &
2601153323Srodrigc			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2602153323Srodrigc	}
2603153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
2604153323Srodrigc}
2605159451Srodrigc#endif /* XFS_NATIVE_HOST */
2606153323Srodrigc
2607153323Srodrigc/*
2608153323Srodrigc * Set the blockcount field in a bmap extent record.
2609153323Srodrigc */
2610153323Srodrigcvoid
2611153323Srodrigcxfs_bmbt_set_blockcount(
2612153323Srodrigc	xfs_bmbt_rec_t	*r,
2613153323Srodrigc	xfs_filblks_t	v)
2614153323Srodrigc{
2615153323Srodrigc	ASSERT((v & XFS_MASK64HI(43)) == 0);
2616153323Srodrigc	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) |
2617153323Srodrigc		  (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21));
2618153323Srodrigc}
2619153323Srodrigc
2620153323Srodrigc/*
2621153323Srodrigc * Set the startblock field in a bmap extent record.
2622153323Srodrigc */
2623153323Srodrigcvoid
2624153323Srodrigcxfs_bmbt_set_startblock(
2625153323Srodrigc	xfs_bmbt_rec_t	*r,
2626153323Srodrigc	xfs_fsblock_t	v)
2627153323Srodrigc{
2628153323Srodrigc#if XFS_BIG_BLKNOS
2629153323Srodrigc	ASSERT((v & XFS_MASK64HI(12)) == 0);
2630153323Srodrigc	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) |
2631153323Srodrigc		  (xfs_bmbt_rec_base_t)(v >> 43);
2632153323Srodrigc	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) |
2633153323Srodrigc		  (xfs_bmbt_rec_base_t)(v << 21);
2634153323Srodrigc#else	/* !XFS_BIG_BLKNOS */
2635153323Srodrigc	if (ISNULLSTARTBLOCK(v)) {
2636153323Srodrigc		r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2637153323Srodrigc		r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) |
2638153323Srodrigc			  ((xfs_bmbt_rec_base_t)v << 21) |
2639153323Srodrigc			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2640153323Srodrigc	} else {
2641153323Srodrigc		r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2642153323Srodrigc		r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
2643153323Srodrigc			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2644153323Srodrigc	}
2645153323Srodrigc#endif	/* XFS_BIG_BLKNOS */
2646153323Srodrigc}
2647153323Srodrigc
2648153323Srodrigc/*
2649153323Srodrigc * Set the startoff field in a bmap extent record.
2650153323Srodrigc */
2651153323Srodrigcvoid
2652153323Srodrigcxfs_bmbt_set_startoff(
2653153323Srodrigc	xfs_bmbt_rec_t	*r,
2654153323Srodrigc	xfs_fileoff_t	v)
2655153323Srodrigc{
2656153323Srodrigc	ASSERT((v & XFS_MASK64HI(9)) == 0);
2657153323Srodrigc	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) |
2658153323Srodrigc		((xfs_bmbt_rec_base_t)v << 9) |
2659153323Srodrigc		  (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2660153323Srodrigc}
2661153323Srodrigc
2662153323Srodrigc/*
2663153323Srodrigc * Set the extent state field in a bmap extent record.
2664153323Srodrigc */
2665153323Srodrigcvoid
2666153323Srodrigcxfs_bmbt_set_state(
2667153323Srodrigc	xfs_bmbt_rec_t	*r,
2668153323Srodrigc	xfs_exntst_t	v)
2669153323Srodrigc{
2670153323Srodrigc	ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
2671153323Srodrigc	if (v == XFS_EXT_NORM)
2672153323Srodrigc		r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN);
2673153323Srodrigc	else
2674153323Srodrigc		r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN);
2675153323Srodrigc}
2676153323Srodrigc
2677153323Srodrigc/*
2678153323Srodrigc * Convert in-memory form of btree root to on-disk form.
2679153323Srodrigc */
2680153323Srodrigcvoid
2681153323Srodrigcxfs_bmbt_to_bmdr(
2682153323Srodrigc	xfs_bmbt_block_t	*rblock,
2683153323Srodrigc	int			rblocklen,
2684153323Srodrigc	xfs_bmdr_block_t	*dblock,
2685153323Srodrigc	int			dblocklen)
2686153323Srodrigc{
2687153323Srodrigc	int			dmxr;
2688153323Srodrigc	xfs_bmbt_key_t		*fkp;
2689153323Srodrigc	xfs_bmbt_ptr_t		*fpp;
2690153323Srodrigc	xfs_bmbt_key_t		*tkp;
2691153323Srodrigc	xfs_bmbt_ptr_t		*tpp;
2692153323Srodrigc
2693159451Srodrigc	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
2694159451Srodrigc	ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
2695159451Srodrigc	ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO);
2696159451Srodrigc	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
2697159451Srodrigc	dblock->bb_level = rblock->bb_level;
2698159451Srodrigc	dblock->bb_numrecs = rblock->bb_numrecs;
2699153323Srodrigc	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
2700153323Srodrigc	fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
2701153323Srodrigc	tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
2702153323Srodrigc	fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
2703153323Srodrigc	tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
2704159451Srodrigc	dmxr = be16_to_cpu(dblock->bb_numrecs);
2705153323Srodrigc	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
2706153323Srodrigc	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
2707153323Srodrigc}
2708153323Srodrigc
2709153323Srodrigc/*
2710153323Srodrigc * Update the record to the passed values.
2711153323Srodrigc */
2712153323Srodrigcint
2713153323Srodrigcxfs_bmbt_update(
2714153323Srodrigc	xfs_btree_cur_t		*cur,
2715153323Srodrigc	xfs_fileoff_t		off,
2716153323Srodrigc	xfs_fsblock_t		bno,
2717153323Srodrigc	xfs_filblks_t		len,
2718153323Srodrigc	xfs_exntst_t		state)
2719153323Srodrigc{
2720153323Srodrigc	xfs_bmbt_block_t	*block;
2721153323Srodrigc	xfs_buf_t		*bp;
2722153323Srodrigc	int			error;
2723153323Srodrigc#ifdef XFS_BMBT_TRACE
2724153323Srodrigc	static char		fname[] = "xfs_bmbt_update";
2725153323Srodrigc#endif
2726153323Srodrigc	xfs_bmbt_key_t		key;
2727153323Srodrigc	int			ptr;
2728153323Srodrigc	xfs_bmbt_rec_t		*rp;
2729153323Srodrigc
2730153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2731153323Srodrigc	XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
2732153323Srodrigc		(xfs_dfilblks_t)len, (int)state);
2733153323Srodrigc	block = xfs_bmbt_get_block(cur, 0, &bp);
2734153323Srodrigc#ifdef DEBUG
2735153323Srodrigc	if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
2736153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2737153323Srodrigc		return error;
2738153323Srodrigc	}
2739153323Srodrigc#endif
2740153323Srodrigc	ptr = cur->bc_ptrs[0];
2741153323Srodrigc	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
2742153323Srodrigc	xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
2743153323Srodrigc	xfs_bmbt_log_recs(cur, bp, ptr, ptr);
2744153323Srodrigc	if (ptr > 1) {
2745153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2746153323Srodrigc		return 0;
2747153323Srodrigc	}
2748153323Srodrigc	INT_SET(key.br_startoff, ARCH_CONVERT, off);
2749153323Srodrigc	if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
2750153323Srodrigc		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2751153323Srodrigc		return error;
2752153323Srodrigc	}
2753153323Srodrigc	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2754153323Srodrigc	return 0;
2755153323Srodrigc}
2756153323Srodrigc
2757153323Srodrigc/*
2758159451Srodrigc * Check extent records, which have just been read, for
2759153323Srodrigc * any bit in the extent flag field. ASSERT on debug
2760153323Srodrigc * kernels, as this condition should not occur.
2761153323Srodrigc * Return an error condition (1) if any flags found,
2762153323Srodrigc * otherwise return 0.
2763153323Srodrigc */
2764153323Srodrigc
2765153323Srodrigcint
2766153323Srodrigcxfs_check_nostate_extents(
2767159451Srodrigc	xfs_ifork_t		*ifp,
2768159451Srodrigc	xfs_extnum_t		idx,
2769153323Srodrigc	xfs_extnum_t		num)
2770153323Srodrigc{
2771159451Srodrigc	xfs_bmbt_rec_t		*ep;
2772159451Srodrigc
2773159451Srodrigc	for (; num > 0; num--, idx++) {
2774159451Srodrigc		ep = xfs_iext_get_ext(ifp, idx);
2775153323Srodrigc		if ((ep->l0 >>
2776153323Srodrigc		     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
2777153323Srodrigc			ASSERT(0);
2778153323Srodrigc			return 1;
2779153323Srodrigc		}
2780153323Srodrigc	}
2781153323Srodrigc	return 0;
2782153323Srodrigc}
2783