1 /*
2  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_bit.h"
22 #include "xfs_log.h"
23 #include "xfs_inum.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_dir.h"
28 #include "xfs_dir2.h"
29 #include "xfs_dmapi.h"
30 #include "xfs_mount.h"
31 #include "xfs_bmap_btree.h"
32 #include "xfs_alloc_btree.h"
33 #include "xfs_ialloc_btree.h"
34 #include "xfs_dir_sf.h"
35 #include "xfs_dir2_sf.h"
36 #include "xfs_attr_sf.h"
37 #include "xfs_dinode.h"
38 #include "xfs_inode.h"
39 #include "xfs_inode_item.h"
40 #include "xfs_alloc.h"
41 #include "xfs_btree.h"
42 #include "xfs_ialloc.h"
43 #include "xfs_itable.h"
44 #include "xfs_bmap.h"
45 #include "xfs_error.h"
46 #include "xfs_quota.h"
47 
48 #if defined(XFS_BMBT_TRACE)
49 ktrace_t	*xfs_bmbt_trace_buf;
50 #endif
51 
52 /*
53  * Prototypes for internal btree functions.
54  */
55 
56 
57 STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *);
58 STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
59 STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
60 STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
61 STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *);
62 STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *,
63 		xfs_bmbt_key_t *, xfs_btree_cur_t **, int *);
64 STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int);
65 
66 
67 #if defined(XFS_BMBT_TRACE)
68 
69 static char	ARGS[] = "args";
70 static char	ENTRY[] = "entry";
71 static char	ERROR[] = "error";
72 #undef EXIT
73 static char	EXIT[] = "exit";
74 
75 /*
76  * Add a trace buffer entry for the arguments given to the routine,
77  * generic form.
78  */
79 STATIC void
xfs_bmbt_trace_enter(char * func,xfs_btree_cur_t * cur,char * s,int type,int line,__psunsigned_t a0,__psunsigned_t a1,__psunsigned_t a2,__psunsigned_t a3,__psunsigned_t a4,__psunsigned_t a5,__psunsigned_t a6,__psunsigned_t a7,__psunsigned_t a8,__psunsigned_t a9,__psunsigned_t a10)80 xfs_bmbt_trace_enter(
81 	char		*func,
82 	xfs_btree_cur_t	*cur,
83 	char		*s,
84 	int		type,
85 	int		line,
86 	__psunsigned_t	a0,
87 	__psunsigned_t	a1,
88 	__psunsigned_t	a2,
89 	__psunsigned_t	a3,
90 	__psunsigned_t	a4,
91 	__psunsigned_t	a5,
92 	__psunsigned_t	a6,
93 	__psunsigned_t	a7,
94 	__psunsigned_t	a8,
95 	__psunsigned_t	a9,
96 	__psunsigned_t	a10)
97 {
98 	xfs_inode_t	*ip;
99 	int		whichfork;
100 
101 	ip = cur->bc_private.b.ip;
102 	whichfork = cur->bc_private.b.whichfork;
103 	ktrace_enter(xfs_bmbt_trace_buf,
104 		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
105 		(void *)func, (void *)s, (void *)ip, (void *)cur,
106 		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
107 		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
108 		(void *)a8, (void *)a9, (void *)a10);
109 	ASSERT(ip->i_btrace);
110 	ktrace_enter(ip->i_btrace,
111 		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
112 		(void *)func, (void *)s, (void *)ip, (void *)cur,
113 		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
114 		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
115 		(void *)a8, (void *)a9, (void *)a10);
116 }
117 /*
118  * Add a trace buffer entry for arguments, for a buffer & 1 integer arg.
119  */
120 STATIC void
xfs_bmbt_trace_argbi(char * func,xfs_btree_cur_t * cur,xfs_buf_t * b,int i,int line)121 xfs_bmbt_trace_argbi(
122 	char		*func,
123 	xfs_btree_cur_t	*cur,
124 	xfs_buf_t	*b,
125 	int		i,
126 	int		line)
127 {
128 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line,
129 		(__psunsigned_t)b, i, 0, 0,
130 		0, 0, 0, 0,
131 		0, 0, 0);
132 }
133 
134 /*
135  * Add a trace buffer entry for arguments, for a buffer & 2 integer args.
136  */
137 STATIC void
xfs_bmbt_trace_argbii(char * func,xfs_btree_cur_t * cur,xfs_buf_t * b,int i0,int i1,int line)138 xfs_bmbt_trace_argbii(
139 	char		*func,
140 	xfs_btree_cur_t	*cur,
141 	xfs_buf_t	*b,
142 	int		i0,
143 	int		i1,
144 	int		line)
145 {
146 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line,
147 		(__psunsigned_t)b, i0, i1, 0,
148 		0, 0, 0, 0,
149 		0, 0, 0);
150 }
151 
152 /*
153  * Add a trace buffer entry for arguments, for 3 block-length args
154  * and an integer arg.
155  */
156 STATIC void
xfs_bmbt_trace_argfffi(char * func,xfs_btree_cur_t * cur,xfs_dfiloff_t o,xfs_dfsbno_t b,xfs_dfilblks_t i,int j,int line)157 xfs_bmbt_trace_argfffi(
158 	char			*func,
159 	xfs_btree_cur_t		*cur,
160 	xfs_dfiloff_t		o,
161 	xfs_dfsbno_t		b,
162 	xfs_dfilblks_t		i,
163 	int			j,
164 	int			line)
165 {
166 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line,
167 		o >> 32, (int)o, b >> 32, (int)b,
168 		i >> 32, (int)i, (int)j, 0,
169 		0, 0, 0);
170 }
171 
172 /*
173  * Add a trace buffer entry for arguments, for one integer arg.
174  */
175 STATIC void
xfs_bmbt_trace_argi(char * func,xfs_btree_cur_t * cur,int i,int line)176 xfs_bmbt_trace_argi(
177 	char		*func,
178 	xfs_btree_cur_t	*cur,
179 	int		i,
180 	int		line)
181 {
182 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line,
183 		i, 0, 0, 0,
184 		0, 0, 0, 0,
185 		0, 0, 0);
186 }
187 
188 /*
189  * Add a trace buffer entry for arguments, for int, fsblock, key.
190  */
191 STATIC void
xfs_bmbt_trace_argifk(char * func,xfs_btree_cur_t * cur,int i,xfs_fsblock_t f,xfs_bmbt_key_t * k,int line)192 xfs_bmbt_trace_argifk(
193 	char			*func,
194 	xfs_btree_cur_t		*cur,
195 	int			i,
196 	xfs_fsblock_t		f,
197 	xfs_bmbt_key_t		*k,
198 	int			line)
199 {
200 	xfs_dfsbno_t		d;
201 	xfs_dfiloff_t		o;
202 
203 	d = (xfs_dfsbno_t)f;
204 	o = INT_GET(k->br_startoff, ARCH_CONVERT);
205 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
206 		i, d >> 32, (int)d, o >> 32,
207 		(int)o, 0, 0, 0,
208 		0, 0, 0);
209 }
210 
211 /*
212  * Add a trace buffer entry for arguments, for int, fsblock, rec.
213  */
214 STATIC void
xfs_bmbt_trace_argifr(char * func,xfs_btree_cur_t * cur,int i,xfs_fsblock_t f,xfs_bmbt_rec_t * r,int line)215 xfs_bmbt_trace_argifr(
216 	char			*func,
217 	xfs_btree_cur_t		*cur,
218 	int			i,
219 	xfs_fsblock_t		f,
220 	xfs_bmbt_rec_t		*r,
221 	int			line)
222 {
223 	xfs_dfsbno_t		b;
224 	xfs_dfilblks_t		c;
225 	xfs_dfsbno_t		d;
226 	xfs_dfiloff_t		o;
227 	xfs_bmbt_irec_t		s;
228 
229 	d = (xfs_dfsbno_t)f;
230 	xfs_bmbt_disk_get_all(r, &s);
231 	o = (xfs_dfiloff_t)s.br_startoff;
232 	b = (xfs_dfsbno_t)s.br_startblock;
233 	c = s.br_blockcount;
234 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line,
235 		i, d >> 32, (int)d, o >> 32,
236 		(int)o, b >> 32, (int)b, c >> 32,
237 		(int)c, 0, 0);
238 }
239 
240 /*
241  * Add a trace buffer entry for arguments, for int, key.
242  */
243 STATIC void
xfs_bmbt_trace_argik(char * func,xfs_btree_cur_t * cur,int i,xfs_bmbt_key_t * k,int line)244 xfs_bmbt_trace_argik(
245 	char			*func,
246 	xfs_btree_cur_t		*cur,
247 	int			i,
248 	xfs_bmbt_key_t		*k,
249 	int			line)
250 {
251 	xfs_dfiloff_t		o;
252 
253 	o = INT_GET(k->br_startoff, ARCH_CONVERT);
254 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
255 		i, o >> 32, (int)o, 0,
256 		0, 0, 0, 0,
257 		0, 0, 0);
258 }
259 
260 /*
261  * Add a trace buffer entry for the cursor/operation.
262  */
263 STATIC void
xfs_bmbt_trace_cursor(char * func,xfs_btree_cur_t * cur,char * s,int line)264 xfs_bmbt_trace_cursor(
265 	char		*func,
266 	xfs_btree_cur_t	*cur,
267 	char		*s,
268 	int		line)
269 {
270 	xfs_bmbt_rec_t	r;
271 
272 	xfs_bmbt_set_all(&r, &cur->bc_rec.b);
273 	xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
274 		(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
275 		cur->bc_private.b.allocated,
276 		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),
277 		(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
278 		(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
279 		(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
280 		(cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]);
281 }
282 
283 #define	XFS_BMBT_TRACE_ARGBI(c,b,i)	\
284 	xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
285 #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)	\
286 	xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
287 #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)	\
288 	xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
289 #define	XFS_BMBT_TRACE_ARGI(c,i)	\
290 	xfs_bmbt_trace_argi(fname, c, i, __LINE__)
291 #define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)	\
292 	xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__)
293 #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
294 	xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
295 #define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
296 	xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
297 #define	XFS_BMBT_TRACE_CURSOR(c,s)	\
298 	xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
299 #else
300 #define	XFS_BMBT_TRACE_ARGBI(c,b,i)
301 #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
302 #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
303 #define	XFS_BMBT_TRACE_ARGI(c,i)
304 #define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)
305 #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
306 #define	XFS_BMBT_TRACE_ARGIK(c,i,k)
307 #define	XFS_BMBT_TRACE_CURSOR(c,s)
308 #endif	/* XFS_BMBT_TRACE */
309 
310 
311 /*
312  * Internal functions.
313  */
314 
315 /*
316  * Delete record pointed to by cur/level.
317  */
318 STATIC int					/* error */
xfs_bmbt_delrec(xfs_btree_cur_t * cur,int level,int * stat)319 xfs_bmbt_delrec(
320 	xfs_btree_cur_t		*cur,
321 	int			level,
322 	int			*stat)		/* success/failure */
323 {
324 	xfs_bmbt_block_t	*block;		/* bmap btree block */
325 	xfs_fsblock_t		bno;		/* fs-relative block number */
326 	xfs_buf_t		*bp;		/* buffer for block */
327 	int			error;		/* error return value */
328 #ifdef XFS_BMBT_TRACE
329 	static char		fname[] = "xfs_bmbt_delrec";
330 #endif
331 	int			i;		/* loop counter */
332 	int			j;		/* temp state */
333 	xfs_bmbt_key_t		key;		/* bmap btree key */
334 	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
335 	xfs_fsblock_t		lbno;		/* left sibling block number */
336 	xfs_buf_t		*lbp;		/* left buffer pointer */
337 	xfs_bmbt_block_t	*left;		/* left btree block */
338 	xfs_bmbt_key_t		*lkp;		/* left btree key */
339 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
340 	int			lrecs=0;	/* left record count */
341 	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
342 	xfs_mount_t		*mp;		/* file system mount point */
343 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
344 	int			ptr;		/* key/record index */
345 	xfs_fsblock_t		rbno;		/* right sibling block number */
346 	xfs_buf_t		*rbp;		/* right buffer pointer */
347 	xfs_bmbt_block_t	*right;		/* right btree block */
348 	xfs_bmbt_key_t		*rkp;		/* right btree key */
349 	xfs_bmbt_rec_t		*rp;		/* pointer to bmap btree rec */
350 	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
351 	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */
352 	xfs_buf_t		*rrbp;		/* right-right buffer pointer */
353 	int			rrecs=0;	/* right record count */
354 	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
355 	xfs_btree_cur_t		*tcur;		/* temporary btree cursor */
356 	int			numrecs;	/* temporary numrec count */
357 	int			numlrecs, numrrecs;
358 
359 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
360 	XFS_BMBT_TRACE_ARGI(cur, level);
361 	ptr = cur->bc_ptrs[level];
362 	tcur = (xfs_btree_cur_t *)0;
363 	if (ptr == 0) {
364 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
365 		*stat = 0;
366 		return 0;
367 	}
368 	block = xfs_bmbt_get_block(cur, level, &bp);
369 	numrecs = be16_to_cpu(block->bb_numrecs);
370 #ifdef DEBUG
371 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
372 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
373 		goto error0;
374 	}
375 #endif
376 	if (ptr > numrecs) {
377 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
378 		*stat = 0;
379 		return 0;
380 	}
381 	XFS_STATS_INC(xs_bmbt_delrec);
382 	if (level > 0) {
383 		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
384 		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
385 #ifdef DEBUG
386 		for (i = ptr; i < numrecs; i++) {
387 			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
388 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
389 				goto error0;
390 			}
391 		}
392 #endif
393 		if (ptr < numrecs) {
394 			memmove(&kp[ptr - 1], &kp[ptr],
395 				(numrecs - ptr) * sizeof(*kp));
396 			memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
397 				(numrecs - ptr) * sizeof(*pp));
398 			xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
399 			xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
400 		}
401 	} else {
402 		rp = XFS_BMAP_REC_IADDR(block, 1, cur);
403 		if (ptr < numrecs) {
404 			memmove(&rp[ptr - 1], &rp[ptr],
405 				(numrecs - ptr) * sizeof(*rp));
406 			xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
407 		}
408 		if (ptr == 1) {
409 			INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp));
410 			kp = &key;
411 		}
412 	}
413 	numrecs--;
414 	block->bb_numrecs = cpu_to_be16(numrecs);
415 	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
416 	/*
417 	 * We're at the root level.
418 	 * First, shrink the root block in-memory.
419 	 * Try to get rid of the next level down.
420 	 * If we can't then there's nothing left to do.
421 	 */
422 	if (level == cur->bc_nlevels - 1) {
423 		xfs_iroot_realloc(cur->bc_private.b.ip, -1,
424 			cur->bc_private.b.whichfork);
425 		if ((error = xfs_bmbt_killroot(cur))) {
426 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
427 			goto error0;
428 		}
429 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
430 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
431 			goto error0;
432 		}
433 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
434 		*stat = 1;
435 		return 0;
436 	}
437 	if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) {
438 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
439 		goto error0;
440 	}
441 	if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
442 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
443 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
444 			goto error0;
445 		}
446 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
447 		*stat = 1;
448 		return 0;
449 	}
450 	rbno = be64_to_cpu(block->bb_rightsib);
451 	lbno = be64_to_cpu(block->bb_leftsib);
452 	/*
453 	 * One child of root, need to get a chance to copy its contents
454 	 * into the root and delete it. Can't go up to next level,
455 	 * there's nothing to delete there.
456 	 */
457 	if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&
458 	    level == cur->bc_nlevels - 2) {
459 		if ((error = xfs_bmbt_killroot(cur))) {
460 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
461 			goto error0;
462 		}
463 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
464 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
465 			goto error0;
466 		}
467 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
468 		*stat = 1;
469 		return 0;
470 	}
471 	ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK);
472 	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
473 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
474 		goto error0;
475 	}
476 	bno = NULLFSBLOCK;
477 	if (rbno != NULLFSBLOCK) {
478 		i = xfs_btree_lastrec(tcur, level);
479 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
480 		if ((error = xfs_bmbt_increment(tcur, level, &i))) {
481 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
482 			goto error0;
483 		}
484 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
485 		i = xfs_btree_lastrec(tcur, level);
486 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
487 		rbp = tcur->bc_bufs[level];
488 		right = XFS_BUF_TO_BMBT_BLOCK(rbp);
489 #ifdef DEBUG
490 		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
491 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
492 			goto error0;
493 		}
494 #endif
495 		bno = be64_to_cpu(right->bb_leftsib);
496 		if (be16_to_cpu(right->bb_numrecs) - 1 >=
497 		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
498 			if ((error = xfs_bmbt_lshift(tcur, level, &i))) {
499 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
500 				goto error0;
501 			}
502 			if (i) {
503 				ASSERT(be16_to_cpu(block->bb_numrecs) >=
504 				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));
505 				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
506 				tcur = NULL;
507 				if (level > 0) {
508 					if ((error = xfs_bmbt_decrement(cur,
509 							level, &i))) {
510 						XFS_BMBT_TRACE_CURSOR(cur,
511 							ERROR);
512 						goto error0;
513 					}
514 				}
515 				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
516 				*stat = 1;
517 				return 0;
518 			}
519 		}
520 		rrecs = be16_to_cpu(right->bb_numrecs);
521 		if (lbno != NULLFSBLOCK) {
522 			i = xfs_btree_firstrec(tcur, level);
523 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
524 			if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
525 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
526 				goto error0;
527 			}
528 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
529 		}
530 	}
531 	if (lbno != NULLFSBLOCK) {
532 		i = xfs_btree_firstrec(tcur, level);
533 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
534 		/*
535 		 * decrement to last in block
536 		 */
537 		if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
538 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
539 			goto error0;
540 		}
541 		i = xfs_btree_firstrec(tcur, level);
542 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
543 		lbp = tcur->bc_bufs[level];
544 		left = XFS_BUF_TO_BMBT_BLOCK(lbp);
545 #ifdef DEBUG
546 		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
547 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
548 			goto error0;
549 		}
550 #endif
551 		bno = be64_to_cpu(left->bb_rightsib);
552 		if (be16_to_cpu(left->bb_numrecs) - 1 >=
553 		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
554 			if ((error = xfs_bmbt_rshift(tcur, level, &i))) {
555 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
556 				goto error0;
557 			}
558 			if (i) {
559 				ASSERT(be16_to_cpu(block->bb_numrecs) >=
560 				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));
561 				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
562 				tcur = NULL;
563 				if (level == 0)
564 					cur->bc_ptrs[0]++;
565 				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
566 				*stat = 1;
567 				return 0;
568 			}
569 		}
570 		lrecs = be16_to_cpu(left->bb_numrecs);
571 	}
572 	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
573 	tcur = NULL;
574 	mp = cur->bc_mp;
575 	ASSERT(bno != NULLFSBLOCK);
576 	if (lbno != NULLFSBLOCK &&
577 	    lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
578 		rbno = bno;
579 		right = block;
580 		rbp = bp;
581 		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp,
582 				XFS_BMAP_BTREE_REF))) {
583 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
584 			goto error0;
585 		}
586 		left = XFS_BUF_TO_BMBT_BLOCK(lbp);
587 		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
588 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
589 			goto error0;
590 		}
591 	} else if (rbno != NULLFSBLOCK &&
592 		   rrecs + be16_to_cpu(block->bb_numrecs) <=
593 		   XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
594 		lbno = bno;
595 		left = block;
596 		lbp = bp;
597 		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp,
598 				XFS_BMAP_BTREE_REF))) {
599 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
600 			goto error0;
601 		}
602 		right = XFS_BUF_TO_BMBT_BLOCK(rbp);
603 		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
604 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
605 			goto error0;
606 		}
607 		lrecs = be16_to_cpu(left->bb_numrecs);
608 	} else {
609 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
610 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
611 			goto error0;
612 		}
613 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
614 		*stat = 1;
615 		return 0;
616 	}
617 	numlrecs = be16_to_cpu(left->bb_numrecs);
618 	numrrecs = be16_to_cpu(right->bb_numrecs);
619 	if (level > 0) {
620 		lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur);
621 		lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur);
622 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
623 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
624 #ifdef DEBUG
625 		for (i = 0; i < numrrecs; i++) {
626 			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
627 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
628 				goto error0;
629 			}
630 		}
631 #endif
632 		memcpy(lkp, rkp, numrrecs * sizeof(*lkp));
633 		memcpy(lpp, rpp, numrrecs * sizeof(*lpp));
634 		xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
635 		xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
636 	} else {
637 		lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur);
638 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
639 		memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
640 		xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
641 	}
642 	be16_add(&left->bb_numrecs, numrrecs);
643 	left->bb_rightsib = right->bb_rightsib;
644 	xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);
645 	if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) {
646 		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp,
647 				be64_to_cpu(left->bb_rightsib),
648 				0, &rrbp, XFS_BMAP_BTREE_REF))) {
649 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
650 			goto error0;
651 		}
652 		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
653 		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
654 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
655 			goto error0;
656 		}
657 		rrblock->bb_leftsib = cpu_to_be64(lbno);
658 		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
659 	}
660 	xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,
661 		cur->bc_private.b.flist, mp);
662 	cur->bc_private.b.ip->i_d.di_nblocks--;
663 	xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
664 	XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip,
665 			XFS_TRANS_DQ_BCOUNT, -1L);
666 	xfs_trans_binval(cur->bc_tp, rbp);
667 	if (bp != lbp) {
668 		cur->bc_bufs[level] = lbp;
669 		cur->bc_ptrs[level] += lrecs;
670 		cur->bc_ra[level] = 0;
671 	} else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {
672 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
673 		goto error0;
674 	}
675 	if (level > 0)
676 		cur->bc_ptrs[level]--;
677 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
678 	*stat = 2;
679 	return 0;
680 
681 error0:
682 	if (tcur)
683 		xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
684 	return error;
685 }
686 
687 #ifdef DEBUG
688 /*
689  * Get the data from the pointed-to record.
690  */
691 int
xfs_bmbt_get_rec(xfs_btree_cur_t * cur,xfs_fileoff_t * off,xfs_fsblock_t * bno,xfs_filblks_t * len,xfs_exntst_t * state,int * stat)692 xfs_bmbt_get_rec(
693 	xfs_btree_cur_t		*cur,
694 	xfs_fileoff_t		*off,
695 	xfs_fsblock_t		*bno,
696 	xfs_filblks_t		*len,
697 	xfs_exntst_t		*state,
698 	int			*stat)
699 {
700 	xfs_bmbt_block_t	*block;
701 	xfs_buf_t		*bp;
702 #ifdef DEBUG
703 	int			error;
704 #endif
705 	int			ptr;
706 	xfs_bmbt_rec_t		*rp;
707 
708 	block = xfs_bmbt_get_block(cur, 0, &bp);
709 	ptr = cur->bc_ptrs[0];
710 #ifdef DEBUG
711 	if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))
712 		return error;
713 #endif
714 	if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
715 		*stat = 0;
716 		return 0;
717 	}
718 	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
719 	*off = xfs_bmbt_disk_get_startoff(rp);
720 	*bno = xfs_bmbt_disk_get_startblock(rp);
721 	*len = xfs_bmbt_disk_get_blockcount(rp);
722 	*state = xfs_bmbt_disk_get_state(rp);
723 	*stat = 1;
724 	return 0;
725 }
726 #endif
727 
728 /*
729  * Insert one record/level.  Return information to the caller
730  * allowing the next level up to proceed if necessary.
731  */
732 STATIC int					/* error */
xfs_bmbt_insrec(xfs_btree_cur_t * cur,int level,xfs_fsblock_t * bnop,xfs_bmbt_rec_t * recp,xfs_btree_cur_t ** curp,int * stat)733 xfs_bmbt_insrec(
734 	xfs_btree_cur_t		*cur,
735 	int			level,
736 	xfs_fsblock_t		*bnop,
737 	xfs_bmbt_rec_t		*recp,
738 	xfs_btree_cur_t		**curp,
739 	int			*stat)		/* no-go/done/continue */
740 {
741 	xfs_bmbt_block_t	*block;		/* bmap btree block */
742 	xfs_buf_t		*bp;		/* buffer for block */
743 	int			error;		/* error return value */
744 #ifdef XFS_BMBT_TRACE
745 	static char		fname[] = "xfs_bmbt_insrec";
746 #endif
747 	int			i;		/* loop index */
748 	xfs_bmbt_key_t		key;		/* bmap btree key */
749 	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
750 	int			logflags;	/* inode logging flags */
751 	xfs_fsblock_t		nbno;		/* new block number */
752 	struct xfs_btree_cur	*ncur;		/* new btree cursor */
753 	xfs_bmbt_key_t		nkey;		/* new btree key value */
754 	xfs_bmbt_rec_t		nrec;		/* new record count */
755 	int			optr;		/* old key/record index */
756 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
757 	int			ptr;		/* key/record index */
758 	xfs_bmbt_rec_t		*rp=NULL;	/* pointer to bmap btree rec */
759 	int			numrecs;
760 
761 	ASSERT(level < cur->bc_nlevels);
762 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
763 	XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
764 	ncur = (xfs_btree_cur_t *)0;
765 	INT_SET(key.br_startoff, ARCH_CONVERT,
766 		xfs_bmbt_disk_get_startoff(recp));
767 	optr = ptr = cur->bc_ptrs[level];
768 	if (ptr == 0) {
769 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
770 		*stat = 0;
771 		return 0;
772 	}
773 	XFS_STATS_INC(xs_bmbt_insrec);
774 	block = xfs_bmbt_get_block(cur, level, &bp);
775 	numrecs = be16_to_cpu(block->bb_numrecs);
776 	nkey.br_startoff = 0;
777 #ifdef DEBUG
778 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
779 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
780 		return error;
781 	}
782 	if (ptr <= numrecs) {
783 		if (level == 0) {
784 			rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
785 			xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp);
786 		} else {
787 			kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
788 			xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp);
789 		}
790 	}
791 #endif
792 	nbno = NULLFSBLOCK;
793 	if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
794 		if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
795 			/*
796 			 * A root block, that can be made bigger.
797 			 */
798 			xfs_iroot_realloc(cur->bc_private.b.ip, 1,
799 				cur->bc_private.b.whichfork);
800 			block = xfs_bmbt_get_block(cur, level, &bp);
801 		} else if (level == cur->bc_nlevels - 1) {
802 			if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) ||
803 			    *stat == 0) {
804 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
805 				return error;
806 			}
807 			xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
808 				logflags);
809 			block = xfs_bmbt_get_block(cur, level, &bp);
810 		} else {
811 			if ((error = xfs_bmbt_rshift(cur, level, &i))) {
812 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
813 				return error;
814 			}
815 			if (i) {
816 				/* nothing */
817 			} else {
818 				if ((error = xfs_bmbt_lshift(cur, level, &i))) {
819 					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
820 					return error;
821 				}
822 				if (i) {
823 					optr = ptr = cur->bc_ptrs[level];
824 				} else {
825 					if ((error = xfs_bmbt_split(cur, level,
826 							&nbno, &nkey, &ncur,
827 							&i))) {
828 						XFS_BMBT_TRACE_CURSOR(cur,
829 							ERROR);
830 						return error;
831 					}
832 					if (i) {
833 						block = xfs_bmbt_get_block(
834 							    cur, level, &bp);
835 #ifdef DEBUG
836 						if ((error =
837 						    xfs_btree_check_lblock(cur,
838 							    block, level, bp))) {
839 							XFS_BMBT_TRACE_CURSOR(
840 								cur, ERROR);
841 							return error;
842 						}
843 #endif
844 						ptr = cur->bc_ptrs[level];
845 						xfs_bmbt_disk_set_allf(&nrec,
846 							nkey.br_startoff, 0, 0,
847 							XFS_EXT_NORM);
848 					} else {
849 						XFS_BMBT_TRACE_CURSOR(cur,
850 							EXIT);
851 						*stat = 0;
852 						return 0;
853 					}
854 				}
855 			}
856 		}
857 	}
858 	numrecs = be16_to_cpu(block->bb_numrecs);
859 	if (level > 0) {
860 		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
861 		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
862 #ifdef DEBUG
863 		for (i = numrecs; i >= ptr; i--) {
864 			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),
865 					level))) {
866 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
867 				return error;
868 			}
869 		}
870 #endif
871 		memmove(&kp[ptr], &kp[ptr - 1],
872 			(numrecs - ptr + 1) * sizeof(*kp));
873 		memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
874 			(numrecs - ptr + 1) * sizeof(*pp));
875 #ifdef DEBUG
876 		if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,
877 				level))) {
878 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
879 			return error;
880 		}
881 #endif
882 		kp[ptr - 1] = key;
883 		INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
884 		numrecs++;
885 		block->bb_numrecs = cpu_to_be16(numrecs);
886 		xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
887 		xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs);
888 	} else {
889 		rp = XFS_BMAP_REC_IADDR(block, 1, cur);
890 		memmove(&rp[ptr], &rp[ptr - 1],
891 			(numrecs - ptr + 1) * sizeof(*rp));
892 		rp[ptr - 1] = *recp;
893 		numrecs++;
894 		block->bb_numrecs = cpu_to_be16(numrecs);
895 		xfs_bmbt_log_recs(cur, bp, ptr, numrecs);
896 	}
897 	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
898 #ifdef DEBUG
899 	if (ptr < numrecs) {
900 		if (level == 0)
901 			xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1,
902 				rp + ptr);
903 		else
904 			xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1,
905 				kp + ptr);
906 	}
907 #endif
908 	if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) {
909 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
910 		return error;
911 	}
912 	*bnop = nbno;
913 	if (nbno != NULLFSBLOCK) {
914 		*recp = nrec;
915 		*curp = ncur;
916 	}
917 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
918 	*stat = 1;
919 	return 0;
920 }
921 
922 STATIC int
xfs_bmbt_killroot(xfs_btree_cur_t * cur)923 xfs_bmbt_killroot(
924 	xfs_btree_cur_t		*cur)
925 {
926 	xfs_bmbt_block_t	*block;
927 	xfs_bmbt_block_t	*cblock;
928 	xfs_buf_t		*cbp;
929 	xfs_bmbt_key_t		*ckp;
930 	xfs_bmbt_ptr_t		*cpp;
931 #ifdef DEBUG
932 	int			error;
933 #endif
934 #ifdef XFS_BMBT_TRACE
935 	static char		fname[] = "xfs_bmbt_killroot";
936 #endif
937 	int			i;
938 	xfs_bmbt_key_t		*kp;
939 	xfs_inode_t		*ip;
940 	xfs_ifork_t		*ifp;
941 	int			level;
942 	xfs_bmbt_ptr_t		*pp;
943 
944 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
945 	level = cur->bc_nlevels - 1;
946 	ASSERT(level >= 1);
947 	/*
948 	 * Don't deal with the root block needs to be a leaf case.
949 	 * We're just going to turn the thing back into extents anyway.
950 	 */
951 	if (level == 1) {
952 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
953 		return 0;
954 	}
955 	block = xfs_bmbt_get_block(cur, level, &cbp);
956 	/*
957 	 * Give up if the root has multiple children.
958 	 */
959 	if (be16_to_cpu(block->bb_numrecs) != 1) {
960 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
961 		return 0;
962 	}
963 	/*
964 	 * Only do this if the next level will fit.
965 	 * Then the data must be copied up to the inode,
966 	 * instead of freeing the root you free the next level.
967 	 */
968 	cbp = cur->bc_bufs[level - 1];
969 	cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
970 	if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
971 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
972 		return 0;
973 	}
974 	ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO);
975 	ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO);
976 	ip = cur->bc_private.b.ip;
977 	ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork);
978 	ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) ==
979 	       XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes));
980 	i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur));
981 	if (i) {
982 		xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork);
983 		block = ifp->if_broot;
984 	}
985 	be16_add(&block->bb_numrecs, i);
986 	ASSERT(block->bb_numrecs == cblock->bb_numrecs);
987 	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
988 	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
989 	memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp));
990 	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
991 	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
992 #ifdef DEBUG
993 	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
994 		if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) {
995 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
996 			return error;
997 		}
998 	}
999 #endif
1000 	memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp));
1001 	xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1,
1002 			cur->bc_private.b.flist, cur->bc_mp);
1003 	ip->i_d.di_nblocks--;
1004 	XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip,
1005 			XFS_TRANS_DQ_BCOUNT, -1L);
1006 	xfs_trans_binval(cur->bc_tp, cbp);
1007 	cur->bc_bufs[level - 1] = NULL;
1008 	be16_add(&block->bb_level, -1);
1009 	xfs_trans_log_inode(cur->bc_tp, ip,
1010 		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1011 	cur->bc_nlevels--;
1012 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1013 	return 0;
1014 }
1015 
1016 /*
1017  * Log key values from the btree block.
1018  */
1019 STATIC void
xfs_bmbt_log_keys(xfs_btree_cur_t * cur,xfs_buf_t * bp,int kfirst,int klast)1020 xfs_bmbt_log_keys(
1021 	xfs_btree_cur_t	*cur,
1022 	xfs_buf_t	*bp,
1023 	int		kfirst,
1024 	int		klast)
1025 {
1026 #ifdef XFS_BMBT_TRACE
1027 	static char	fname[] = "xfs_bmbt_log_keys";
1028 #endif
1029 	xfs_trans_t	*tp;
1030 
1031 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1032 	XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast);
1033 	tp = cur->bc_tp;
1034 	if (bp) {
1035 		xfs_bmbt_block_t	*block;
1036 		int			first;
1037 		xfs_bmbt_key_t		*kp;
1038 		int			last;
1039 
1040 		block = XFS_BUF_TO_BMBT_BLOCK(bp);
1041 		kp = XFS_BMAP_KEY_DADDR(block, 1, cur);
1042 		first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
1043 		last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
1044 		xfs_trans_log_buf(tp, bp, first, last);
1045 	} else {
1046 		xfs_inode_t		 *ip;
1047 
1048 		ip = cur->bc_private.b.ip;
1049 		xfs_trans_log_inode(tp, ip,
1050 			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1051 	}
1052 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1053 }
1054 
1055 /*
1056  * Log pointer values from the btree block.
1057  */
1058 STATIC void
xfs_bmbt_log_ptrs(xfs_btree_cur_t * cur,xfs_buf_t * bp,int pfirst,int plast)1059 xfs_bmbt_log_ptrs(
1060 	xfs_btree_cur_t	*cur,
1061 	xfs_buf_t	*bp,
1062 	int		pfirst,
1063 	int		plast)
1064 {
1065 #ifdef XFS_BMBT_TRACE
1066 	static char	fname[] = "xfs_bmbt_log_ptrs";
1067 #endif
1068 	xfs_trans_t	*tp;
1069 
1070 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1071 	XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast);
1072 	tp = cur->bc_tp;
1073 	if (bp) {
1074 		xfs_bmbt_block_t	*block;
1075 		int			first;
1076 		int			last;
1077 		xfs_bmbt_ptr_t		*pp;
1078 
1079 		block = XFS_BUF_TO_BMBT_BLOCK(bp);
1080 		pp = XFS_BMAP_PTR_DADDR(block, 1, cur);
1081 		first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
1082 		last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
1083 		xfs_trans_log_buf(tp, bp, first, last);
1084 	} else {
1085 		xfs_inode_t		*ip;
1086 
1087 		ip = cur->bc_private.b.ip;
1088 		xfs_trans_log_inode(tp, ip,
1089 			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1090 	}
1091 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1092 }
1093 
1094 /*
1095  * Lookup the record.  The cursor is made to point to it, based on dir.
1096  */
1097 STATIC int				/* error */
xfs_bmbt_lookup(xfs_btree_cur_t * cur,xfs_lookup_t dir,int * stat)1098 xfs_bmbt_lookup(
1099 	xfs_btree_cur_t		*cur,
1100 	xfs_lookup_t		dir,
1101 	int			*stat)		/* success/failure */
1102 {
1103 	xfs_bmbt_block_t	*block=NULL;
1104 	xfs_buf_t		*bp;
1105 	xfs_daddr_t		d;
1106 	xfs_sfiloff_t		diff;
1107 	int			error;		/* error return value */
1108 #ifdef XFS_BMBT_TRACE
1109 	static char	fname[] = "xfs_bmbt_lookup";
1110 #endif
1111 	xfs_fsblock_t		fsbno=0;
1112 	int			high;
1113 	int			i;
1114 	int			keyno=0;
1115 	xfs_bmbt_key_t		*kkbase=NULL;
1116 	xfs_bmbt_key_t		*kkp;
1117 	xfs_bmbt_rec_t		*krbase=NULL;
1118 	xfs_bmbt_rec_t		*krp;
1119 	int			level;
1120 	int			low;
1121 	xfs_mount_t		*mp;
1122 	xfs_bmbt_ptr_t		*pp;
1123 	xfs_bmbt_irec_t		*rp;
1124 	xfs_fileoff_t		startoff;
1125 	xfs_trans_t		*tp;
1126 
1127 	XFS_STATS_INC(xs_bmbt_lookup);
1128 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1129 	XFS_BMBT_TRACE_ARGI(cur, (int)dir);
1130 	tp = cur->bc_tp;
1131 	mp = cur->bc_mp;
1132 	rp = &cur->bc_rec.b;
1133 	for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
1134 		if (level < cur->bc_nlevels - 1) {
1135 			d = XFS_FSB_TO_DADDR(mp, fsbno);
1136 			bp = cur->bc_bufs[level];
1137 			if (bp && XFS_BUF_ADDR(bp) != d)
1138 				bp = (xfs_buf_t *)0;
1139 			if (!bp) {
1140 				if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
1141 						0, &bp, XFS_BMAP_BTREE_REF))) {
1142 					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1143 					return error;
1144 				}
1145 				xfs_btree_setbuf(cur, level, bp);
1146 				block = XFS_BUF_TO_BMBT_BLOCK(bp);
1147 				if ((error = xfs_btree_check_lblock(cur, block,
1148 						level, bp))) {
1149 					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1150 					return error;
1151 				}
1152 			} else
1153 				block = XFS_BUF_TO_BMBT_BLOCK(bp);
1154 		} else
1155 			block = xfs_bmbt_get_block(cur, level, &bp);
1156 		if (diff == 0)
1157 			keyno = 1;
1158 		else {
1159 			if (level > 0)
1160 				kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur);
1161 			else
1162 				krbase = XFS_BMAP_REC_IADDR(block, 1, cur);
1163 			low = 1;
1164 			if (!(high = be16_to_cpu(block->bb_numrecs))) {
1165 				ASSERT(level == 0);
1166 				cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
1167 				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1168 				*stat = 0;
1169 				return 0;
1170 			}
1171 			while (low <= high) {
1172 				XFS_STATS_INC(xs_bmbt_compare);
1173 				keyno = (low + high) >> 1;
1174 				if (level > 0) {
1175 					kkp = kkbase + keyno - 1;
1176 					startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT);
1177 				} else {
1178 					krp = krbase + keyno - 1;
1179 					startoff = xfs_bmbt_disk_get_startoff(krp);
1180 				}
1181 				diff = (xfs_sfiloff_t)
1182 						(startoff - rp->br_startoff);
1183 				if (diff < 0)
1184 					low = keyno + 1;
1185 				else if (diff > 0)
1186 					high = keyno - 1;
1187 				else
1188 					break;
1189 			}
1190 		}
1191 		if (level > 0) {
1192 			if (diff > 0 && --keyno < 1)
1193 				keyno = 1;
1194 			pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
1195 #ifdef DEBUG
1196 			if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
1197 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1198 				return error;
1199 			}
1200 #endif
1201 			fsbno = INT_GET(*pp, ARCH_CONVERT);
1202 			cur->bc_ptrs[level] = keyno;
1203 		}
1204 	}
1205 	if (dir != XFS_LOOKUP_LE && diff < 0) {
1206 		keyno++;
1207 		/*
1208 		 * If ge search and we went off the end of the block, but it's
1209 		 * not the last block, we're in the wrong block.
1210 		 */
1211 		if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) &&
1212 		    be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) {
1213 			cur->bc_ptrs[0] = keyno;
1214 			if ((error = xfs_bmbt_increment(cur, 0, &i))) {
1215 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1216 				return error;
1217 			}
1218 			XFS_WANT_CORRUPTED_RETURN(i == 1);
1219 			XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1220 			*stat = 1;
1221 			return 0;
1222 		}
1223 	}
1224 	else if (dir == XFS_LOOKUP_LE && diff > 0)
1225 		keyno--;
1226 	cur->bc_ptrs[0] = keyno;
1227 	if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) {
1228 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1229 		*stat = 0;
1230 	} else {
1231 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1232 		*stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
1233 	}
1234 	return 0;
1235 }
1236 
1237 /*
1238  * Move 1 record left from cur/level if possible.
1239  * Update cur to reflect the new path.
1240  */
1241 STATIC int					/* error */
xfs_bmbt_lshift(xfs_btree_cur_t * cur,int level,int * stat)1242 xfs_bmbt_lshift(
1243 	xfs_btree_cur_t		*cur,
1244 	int			level,
1245 	int			*stat)		/* success/failure */
1246 {
1247 	int			error;		/* error return value */
1248 #ifdef XFS_BMBT_TRACE
1249 	static char		fname[] = "xfs_bmbt_lshift";
1250 #endif
1251 #ifdef DEBUG
1252 	int			i;		/* loop counter */
1253 #endif
1254 	xfs_bmbt_key_t		key;		/* bmap btree key */
1255 	xfs_buf_t		*lbp;		/* left buffer pointer */
1256 	xfs_bmbt_block_t	*left;		/* left btree block */
1257 	xfs_bmbt_key_t		*lkp=NULL;	/* left btree key */
1258 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
1259 	int			lrecs;		/* left record count */
1260 	xfs_bmbt_rec_t		*lrp=NULL;	/* left record pointer */
1261 	xfs_mount_t		*mp;		/* file system mount point */
1262 	xfs_buf_t		*rbp;		/* right buffer pointer */
1263 	xfs_bmbt_block_t	*right;		/* right btree block */
1264 	xfs_bmbt_key_t		*rkp=NULL;	/* right btree key */
1265 	xfs_bmbt_ptr_t		*rpp=NULL;	/* right address pointer */
1266 	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */
1267 	int			rrecs;		/* right record count */
1268 
1269 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1270 	XFS_BMBT_TRACE_ARGI(cur, level);
1271 	if (level == cur->bc_nlevels - 1) {
1272 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1273 		*stat = 0;
1274 		return 0;
1275 	}
1276 	rbp = cur->bc_bufs[level];
1277 	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1278 #ifdef DEBUG
1279 	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
1280 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1281 		return error;
1282 	}
1283 #endif
1284 	if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) {
1285 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1286 		*stat = 0;
1287 		return 0;
1288 	}
1289 	if (cur->bc_ptrs[level] <= 1) {
1290 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1291 		*stat = 0;
1292 		return 0;
1293 	}
1294 	mp = cur->bc_mp;
1295 	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0,
1296 			&lbp, XFS_BMAP_BTREE_REF))) {
1297 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1298 		return error;
1299 	}
1300 	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1301 	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
1302 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1303 		return error;
1304 	}
1305 	if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
1306 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1307 		*stat = 0;
1308 		return 0;
1309 	}
1310 	lrecs = be16_to_cpu(left->bb_numrecs) + 1;
1311 	if (level > 0) {
1312 		lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur);
1313 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1314 		*lkp = *rkp;
1315 		xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs);
1316 		lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
1317 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1318 #ifdef DEBUG
1319 		if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) {
1320 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1321 			return error;
1322 		}
1323 #endif
1324 		*lpp = *rpp; /* INT_: direct copy */
1325 		xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
1326 	} else {
1327 		lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
1328 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1329 		*lrp = *rrp;
1330 		xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs);
1331 	}
1332 	left->bb_numrecs = cpu_to_be16(lrecs);
1333 	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
1334 #ifdef DEBUG
1335 	if (level > 0)
1336 		xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp);
1337 	else
1338 		xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp);
1339 #endif
1340 	rrecs = be16_to_cpu(right->bb_numrecs) - 1;
1341 	right->bb_numrecs = cpu_to_be16(rrecs);
1342 	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
1343 	if (level > 0) {
1344 #ifdef DEBUG
1345 		for (i = 0; i < rrecs; i++) {
1346 			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
1347 					level))) {
1348 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1349 				return error;
1350 			}
1351 		}
1352 #endif
1353 		memmove(rkp, rkp + 1, rrecs * sizeof(*rkp));
1354 		memmove(rpp, rpp + 1, rrecs * sizeof(*rpp));
1355 		xfs_bmbt_log_keys(cur, rbp, 1, rrecs);
1356 		xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs);
1357 	} else {
1358 		memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
1359 		xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
1360 		INT_SET(key.br_startoff, ARCH_CONVERT,
1361 			xfs_bmbt_disk_get_startoff(rrp));
1362 		rkp = &key;
1363 	}
1364 	if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
1365 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1366 		return error;
1367 	}
1368 	cur->bc_ptrs[level]--;
1369 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1370 	*stat = 1;
1371 	return 0;
1372 }
1373 
1374 /*
1375  * Move 1 record right from cur/level if possible.
1376  * Update cur to reflect the new path.
1377  */
1378 STATIC int					/* error */
xfs_bmbt_rshift(xfs_btree_cur_t * cur,int level,int * stat)1379 xfs_bmbt_rshift(
1380 	xfs_btree_cur_t		*cur,
1381 	int			level,
1382 	int			*stat)		/* success/failure */
1383 {
1384 	int			error;		/* error return value */
1385 #ifdef XFS_BMBT_TRACE
1386 	static char		fname[] = "xfs_bmbt_rshift";
1387 #endif
1388 	int			i;		/* loop counter */
1389 	xfs_bmbt_key_t		key;		/* bmap btree key */
1390 	xfs_buf_t		*lbp;		/* left buffer pointer */
1391 	xfs_bmbt_block_t	*left;		/* left btree block */
1392 	xfs_bmbt_key_t		*lkp;		/* left btree key */
1393 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
1394 	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
1395 	xfs_mount_t		*mp;		/* file system mount point */
1396 	xfs_buf_t		*rbp;		/* right buffer pointer */
1397 	xfs_bmbt_block_t	*right;		/* right btree block */
1398 	xfs_bmbt_key_t		*rkp;		/* right btree key */
1399 	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
1400 	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */
1401 	struct xfs_btree_cur	*tcur;		/* temporary btree cursor */
1402 
1403 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1404 	XFS_BMBT_TRACE_ARGI(cur, level);
1405 	if (level == cur->bc_nlevels - 1) {
1406 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1407 		*stat = 0;
1408 		return 0;
1409 	}
1410 	lbp = cur->bc_bufs[level];
1411 	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1412 #ifdef DEBUG
1413 	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
1414 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1415 		return error;
1416 	}
1417 #endif
1418 	if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) {
1419 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1420 		*stat = 0;
1421 		return 0;
1422 	}
1423 	if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) {
1424 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1425 		*stat = 0;
1426 		return 0;
1427 	}
1428 	mp = cur->bc_mp;
1429 	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0,
1430 			&rbp, XFS_BMAP_BTREE_REF))) {
1431 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1432 		return error;
1433 	}
1434 	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1435 	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
1436 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1437 		return error;
1438 	}
1439 	if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
1440 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1441 		*stat = 0;
1442 		return 0;
1443 	}
1444 	if (level > 0) {
1445 		lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1446 		lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1447 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1448 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1449 #ifdef DEBUG
1450 		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
1451 			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
1452 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1453 				return error;
1454 			}
1455 		}
1456 #endif
1457 		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
1458 		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
1459 #ifdef DEBUG
1460 		if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) {
1461 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1462 			return error;
1463 		}
1464 #endif
1465 		*rkp = *lkp;
1466 		*rpp = *lpp; /* INT_: direct copy */
1467 		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1468 		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1469 	} else {
1470 		lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1471 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1472 		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
1473 		*rrp = *lrp;
1474 		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1475 		INT_SET(key.br_startoff, ARCH_CONVERT,
1476 			xfs_bmbt_disk_get_startoff(rrp));
1477 		rkp = &key;
1478 	}
1479 	be16_add(&left->bb_numrecs, -1);
1480 	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
1481 	be16_add(&right->bb_numrecs, 1);
1482 #ifdef DEBUG
1483 	if (level > 0)
1484 		xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1);
1485 	else
1486 		xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1);
1487 #endif
1488 	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
1489 	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
1490 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1491 		return error;
1492 	}
1493 	i = xfs_btree_lastrec(tcur, level);
1494 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1495 	if ((error = xfs_bmbt_increment(tcur, level, &i))) {
1496 		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
1497 		goto error1;
1498 	}
1499 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1500 	if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) {
1501 		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
1502 		goto error1;
1503 	}
1504 	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
1505 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1506 	*stat = 1;
1507 	return 0;
1508 error0:
1509 	XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1510 error1:
1511 	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
1512 	return error;
1513 }
1514 
1515 /*
1516  * Determine the extent state.
1517  */
1518 /* ARGSUSED */
1519 STATIC xfs_exntst_t
xfs_extent_state(xfs_filblks_t blks,int extent_flag)1520 xfs_extent_state(
1521 	xfs_filblks_t		blks,
1522 	int			extent_flag)
1523 {
1524 	if (extent_flag) {
1525 		ASSERT(blks != 0);	/* saved for DMIG */
1526 		return XFS_EXT_UNWRITTEN;
1527 	}
1528 	return XFS_EXT_NORM;
1529 }
1530 
1531 
1532 /*
1533  * Split cur/level block in half.
1534  * Return new block number and its first record (to be inserted into parent).
1535  */
1536 STATIC int					/* error */
xfs_bmbt_split(xfs_btree_cur_t * cur,int level,xfs_fsblock_t * bnop,xfs_bmbt_key_t * keyp,xfs_btree_cur_t ** curp,int * stat)1537 xfs_bmbt_split(
1538 	xfs_btree_cur_t		*cur,
1539 	int			level,
1540 	xfs_fsblock_t		*bnop,
1541 	xfs_bmbt_key_t		*keyp,
1542 	xfs_btree_cur_t		**curp,
1543 	int			*stat)		/* success/failure */
1544 {
1545 	xfs_alloc_arg_t		args;		/* block allocation args */
1546 	int			error;		/* error return value */
1547 #ifdef XFS_BMBT_TRACE
1548 	static char		fname[] = "xfs_bmbt_split";
1549 #endif
1550 	int			i;		/* loop counter */
1551 	xfs_fsblock_t		lbno;		/* left sibling block number */
1552 	xfs_buf_t		*lbp;		/* left buffer pointer */
1553 	xfs_bmbt_block_t	*left;		/* left btree block */
1554 	xfs_bmbt_key_t		*lkp;		/* left btree key */
1555 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
1556 	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
1557 	xfs_buf_t		*rbp;		/* right buffer pointer */
1558 	xfs_bmbt_block_t	*right;		/* right btree block */
1559 	xfs_bmbt_key_t		*rkp;		/* right btree key */
1560 	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
1561 	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */
1562 	xfs_buf_t		*rrbp;		/* right-right buffer pointer */
1563 	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
1564 
1565 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1566 	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp);
1567 	args.tp = cur->bc_tp;
1568 	args.mp = cur->bc_mp;
1569 	lbp = cur->bc_bufs[level];
1570 	lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
1571 	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1572 	args.fsbno = cur->bc_private.b.firstblock;
1573 	if (args.fsbno == NULLFSBLOCK) {
1574 		args.fsbno = lbno;
1575 		args.type = XFS_ALLOCTYPE_START_BNO;
1576 	} else if (cur->bc_private.b.flist->xbf_low)
1577 		args.type = XFS_ALLOCTYPE_FIRST_AG;
1578 	else
1579 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
1580 	args.mod = args.minleft = args.alignment = args.total = args.isfl =
1581 		args.userdata = args.minalignslop = 0;
1582 	args.minlen = args.maxlen = args.prod = 1;
1583 	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
1584 	if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
1585 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1586 		return XFS_ERROR(ENOSPC);
1587 	}
1588 	if ((error = xfs_alloc_vextent(&args))) {
1589 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1590 		return error;
1591 	}
1592 	if (args.fsbno == NULLFSBLOCK) {
1593 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1594 		*stat = 0;
1595 		return 0;
1596 	}
1597 	ASSERT(args.len == 1);
1598 	cur->bc_private.b.firstblock = args.fsbno;
1599 	cur->bc_private.b.allocated++;
1600 	cur->bc_private.b.ip->i_d.di_nblocks++;
1601 	xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
1602 	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
1603 			XFS_TRANS_DQ_BCOUNT, 1L);
1604 	rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0);
1605 	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1606 #ifdef DEBUG
1607 	if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) {
1608 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1609 		return error;
1610 	}
1611 #endif
1612 	right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
1613 	right->bb_level = left->bb_level;
1614 	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
1615 	if ((be16_to_cpu(left->bb_numrecs) & 1) &&
1616 	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
1617 		be16_add(&right->bb_numrecs, 1);
1618 	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
1619 	if (level > 0) {
1620 		lkp = XFS_BMAP_KEY_IADDR(left, i, cur);
1621 		lpp = XFS_BMAP_PTR_IADDR(left, i, cur);
1622 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1623 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1624 #ifdef DEBUG
1625 		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
1626 			if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) {
1627 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1628 				return error;
1629 			}
1630 		}
1631 #endif
1632 		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
1633 		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
1634 		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1635 		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1636 		keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT);
1637 	} else {
1638 		lrp = XFS_BMAP_REC_IADDR(left, i, cur);
1639 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1640 		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
1641 		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1642 		keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp);
1643 	}
1644 	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
1645 	right->bb_rightsib = left->bb_rightsib;
1646 	left->bb_rightsib = cpu_to_be64(args.fsbno);
1647 	right->bb_leftsib = cpu_to_be64(lbno);
1648 	xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS);
1649 	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
1650 	if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) {
1651 		if ((error = xfs_btree_read_bufl(args.mp, args.tp,
1652 				be64_to_cpu(right->bb_rightsib), 0, &rrbp,
1653 				XFS_BMAP_BTREE_REF))) {
1654 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1655 			return error;
1656 		}
1657 		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
1658 		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
1659 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1660 			return error;
1661 		}
1662 		rrblock->bb_leftsib = cpu_to_be64(args.fsbno);
1663 		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
1664 	}
1665 	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {
1666 		xfs_btree_setbuf(cur, level, rbp);
1667 		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);
1668 	}
1669 	if (level + 1 < cur->bc_nlevels) {
1670 		if ((error = xfs_btree_dup_cursor(cur, curp))) {
1671 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1672 			return error;
1673 		}
1674 		(*curp)->bc_ptrs[level + 1]++;
1675 	}
1676 	*bnop = args.fsbno;
1677 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1678 	*stat = 1;
1679 	return 0;
1680 }
1681 
1682 
1683 /*
1684  * Update keys for the record.
1685  */
1686 STATIC int
xfs_bmbt_updkey(xfs_btree_cur_t * cur,xfs_bmbt_key_t * keyp,int level)1687 xfs_bmbt_updkey(
1688 	xfs_btree_cur_t		*cur,
1689 	xfs_bmbt_key_t		*keyp,	/* on-disk format */
1690 	int			level)
1691 {
1692 	xfs_bmbt_block_t	*block;
1693 	xfs_buf_t		*bp;
1694 #ifdef DEBUG
1695 	int			error;
1696 #endif
1697 #ifdef XFS_BMBT_TRACE
1698 	static char		fname[] = "xfs_bmbt_updkey";
1699 #endif
1700 	xfs_bmbt_key_t		*kp;
1701 	int			ptr;
1702 
1703 	ASSERT(level >= 1);
1704 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1705 	XFS_BMBT_TRACE_ARGIK(cur, level, keyp);
1706 	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
1707 		block = xfs_bmbt_get_block(cur, level, &bp);
1708 #ifdef DEBUG
1709 		if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
1710 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1711 			return error;
1712 		}
1713 #endif
1714 		ptr = cur->bc_ptrs[level];
1715 		kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
1716 		*kp = *keyp;
1717 		xfs_bmbt_log_keys(cur, bp, ptr, ptr);
1718 	}
1719 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1720 	return 0;
1721 }
1722 
1723 /*
1724  * Convert on-disk form of btree root to in-memory form.
1725  */
1726 void
xfs_bmdr_to_bmbt(xfs_bmdr_block_t * dblock,int dblocklen,xfs_bmbt_block_t * rblock,int rblocklen)1727 xfs_bmdr_to_bmbt(
1728 	xfs_bmdr_block_t	*dblock,
1729 	int			dblocklen,
1730 	xfs_bmbt_block_t	*rblock,
1731 	int			rblocklen)
1732 {
1733 	int			dmxr;
1734 	xfs_bmbt_key_t		*fkp;
1735 	xfs_bmbt_ptr_t		*fpp;
1736 	xfs_bmbt_key_t		*tkp;
1737 	xfs_bmbt_ptr_t		*tpp;
1738 
1739 	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
1740 	rblock->bb_level = dblock->bb_level;
1741 	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
1742 	rblock->bb_numrecs = dblock->bb_numrecs;
1743 	rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
1744 	rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
1745 	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
1746 	fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
1747 	tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
1748 	fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
1749 	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
1750 	dmxr = be16_to_cpu(dblock->bb_numrecs);
1751 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
1752 	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
1753 }
1754 
1755 /*
1756  * Decrement cursor by one record at the level.
1757  * For nonzero levels the leaf-ward information is untouched.
1758  */
1759 int						/* error */
xfs_bmbt_decrement(xfs_btree_cur_t * cur,int level,int * stat)1760 xfs_bmbt_decrement(
1761 	xfs_btree_cur_t		*cur,
1762 	int			level,
1763 	int			*stat)		/* success/failure */
1764 {
1765 	xfs_bmbt_block_t	*block;
1766 	xfs_buf_t		*bp;
1767 	int			error;		/* error return value */
1768 #ifdef XFS_BMBT_TRACE
1769 	static char		fname[] = "xfs_bmbt_decrement";
1770 #endif
1771 	xfs_fsblock_t		fsbno;
1772 	int			lev;
1773 	xfs_mount_t		*mp;
1774 	xfs_trans_t		*tp;
1775 
1776 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1777 	XFS_BMBT_TRACE_ARGI(cur, level);
1778 	ASSERT(level < cur->bc_nlevels);
1779 	if (level < cur->bc_nlevels - 1)
1780 		xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
1781 	if (--cur->bc_ptrs[level] > 0) {
1782 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1783 		*stat = 1;
1784 		return 0;
1785 	}
1786 	block = xfs_bmbt_get_block(cur, level, &bp);
1787 #ifdef DEBUG
1788 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
1789 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1790 		return error;
1791 	}
1792 #endif
1793 	if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) {
1794 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1795 		*stat = 0;
1796 		return 0;
1797 	}
1798 	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1799 		if (--cur->bc_ptrs[lev] > 0)
1800 			break;
1801 		if (lev < cur->bc_nlevels - 1)
1802 			xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
1803 	}
1804 	if (lev == cur->bc_nlevels) {
1805 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1806 		*stat = 0;
1807 		return 0;
1808 	}
1809 	tp = cur->bc_tp;
1810 	mp = cur->bc_mp;
1811 	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
1812 		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
1813 		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
1814 				XFS_BMAP_BTREE_REF))) {
1815 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1816 			return error;
1817 		}
1818 		lev--;
1819 		xfs_btree_setbuf(cur, lev, bp);
1820 		block = XFS_BUF_TO_BMBT_BLOCK(bp);
1821 		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
1822 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1823 			return error;
1824 		}
1825 		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);
1826 	}
1827 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1828 	*stat = 1;
1829 	return 0;
1830 }
1831 
1832 /*
1833  * Delete the record pointed to by cur.
1834  */
1835 int					/* error */
xfs_bmbt_delete(xfs_btree_cur_t * cur,int * stat)1836 xfs_bmbt_delete(
1837 	xfs_btree_cur_t	*cur,
1838 	int		*stat)		/* success/failure */
1839 {
1840 	int		error;		/* error return value */
1841 #ifdef XFS_BMBT_TRACE
1842 	static char	fname[] = "xfs_bmbt_delete";
1843 #endif
1844 	int		i;
1845 	int		level;
1846 
1847 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1848 	for (level = 0, i = 2; i == 2; level++) {
1849 		if ((error = xfs_bmbt_delrec(cur, level, &i))) {
1850 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1851 			return error;
1852 		}
1853 	}
1854 	if (i == 0) {
1855 		for (level = 1; level < cur->bc_nlevels; level++) {
1856 			if (cur->bc_ptrs[level] == 0) {
1857 				if ((error = xfs_bmbt_decrement(cur, level,
1858 						&i))) {
1859 					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1860 					return error;
1861 				}
1862 				break;
1863 			}
1864 		}
1865 	}
1866 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1867 	*stat = i;
1868 	return 0;
1869 }
1870 
1871 /*
1872  * Convert a compressed bmap extent record to an uncompressed form.
1873  * This code must be in sync with the routines xfs_bmbt_get_startoff,
1874  * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
1875  */
1876 
1877 STATIC __inline__ void
__xfs_bmbt_get_all(__uint64_t l0,__uint64_t l1,xfs_bmbt_irec_t * s)1878 __xfs_bmbt_get_all(
1879 		__uint64_t l0,
1880 		__uint64_t l1,
1881 		xfs_bmbt_irec_t *s)
1882 {
1883 	int	ext_flag;
1884 	xfs_exntst_t st;
1885 
1886 	ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
1887 	s->br_startoff = ((xfs_fileoff_t)l0 &
1888 			   XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1889 #if XFS_BIG_BLKNOS
1890 	s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |
1891 			   (((xfs_fsblock_t)l1) >> 21);
1892 #else
1893 #ifdef DEBUG
1894 	{
1895 		xfs_dfsbno_t	b;
1896 
1897 		b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |
1898 		    (((xfs_dfsbno_t)l1) >> 21);
1899 		ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
1900 		s->br_startblock = (xfs_fsblock_t)b;
1901 	}
1902 #else	/* !DEBUG */
1903 	s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
1904 #endif	/* DEBUG */
1905 #endif	/* XFS_BIG_BLKNOS */
1906 	s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));
1907 	/* This is xfs_extent_state() in-line */
1908 	if (ext_flag) {
1909 		ASSERT(s->br_blockcount != 0);	/* saved for DMIG */
1910 		st = XFS_EXT_UNWRITTEN;
1911 	} else
1912 		st = XFS_EXT_NORM;
1913 	s->br_state = st;
1914 }
1915 
1916 void
xfs_bmbt_get_all(xfs_bmbt_rec_t * r,xfs_bmbt_irec_t * s)1917 xfs_bmbt_get_all(
1918 	xfs_bmbt_rec_t	*r,
1919 	xfs_bmbt_irec_t *s)
1920 {
1921 	__xfs_bmbt_get_all(r->l0, r->l1, s);
1922 }
1923 
1924 /*
1925  * Get the block pointer for the given level of the cursor.
1926  * Fill in the buffer pointer, if applicable.
1927  */
1928 xfs_bmbt_block_t *
xfs_bmbt_get_block(xfs_btree_cur_t * cur,int level,xfs_buf_t ** bpp)1929 xfs_bmbt_get_block(
1930 	xfs_btree_cur_t		*cur,
1931 	int			level,
1932 	xfs_buf_t		**bpp)
1933 {
1934 	xfs_ifork_t		*ifp;
1935 	xfs_bmbt_block_t	*rval;
1936 
1937 	if (level < cur->bc_nlevels - 1) {
1938 		*bpp = cur->bc_bufs[level];
1939 		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
1940 	} else {
1941 		*bpp = NULL;
1942 		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
1943 			cur->bc_private.b.whichfork);
1944 		rval = ifp->if_broot;
1945 	}
1946 	return rval;
1947 }
1948 
1949 /*
1950  * Extract the blockcount field from an in memory bmap extent record.
1951  */
1952 xfs_filblks_t
xfs_bmbt_get_blockcount(xfs_bmbt_rec_t * r)1953 xfs_bmbt_get_blockcount(
1954 	xfs_bmbt_rec_t	*r)
1955 {
1956 	return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
1957 }
1958 
1959 /*
1960  * Extract the startblock field from an in memory bmap extent record.
1961  */
1962 xfs_fsblock_t
xfs_bmbt_get_startblock(xfs_bmbt_rec_t * r)1963 xfs_bmbt_get_startblock(
1964 	xfs_bmbt_rec_t	*r)
1965 {
1966 #if XFS_BIG_BLKNOS
1967 	return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
1968 	       (((xfs_fsblock_t)r->l1) >> 21);
1969 #else
1970 #ifdef DEBUG
1971 	xfs_dfsbno_t	b;
1972 
1973 	b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |
1974 	    (((xfs_dfsbno_t)r->l1) >> 21);
1975 	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
1976 	return (xfs_fsblock_t)b;
1977 #else	/* !DEBUG */
1978 	return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
1979 #endif	/* DEBUG */
1980 #endif	/* XFS_BIG_BLKNOS */
1981 }
1982 
1983 /*
1984  * Extract the startoff field from an in memory bmap extent record.
1985  */
1986 xfs_fileoff_t
xfs_bmbt_get_startoff(xfs_bmbt_rec_t * r)1987 xfs_bmbt_get_startoff(
1988 	xfs_bmbt_rec_t	*r)
1989 {
1990 	return ((xfs_fileoff_t)r->l0 &
1991 		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1992 }
1993 
1994 xfs_exntst_t
xfs_bmbt_get_state(xfs_bmbt_rec_t * r)1995 xfs_bmbt_get_state(
1996 	xfs_bmbt_rec_t	*r)
1997 {
1998 	int	ext_flag;
1999 
2000 	ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
2001 	return xfs_extent_state(xfs_bmbt_get_blockcount(r),
2002 				ext_flag);
2003 }
2004 
2005 #ifndef XFS_NATIVE_HOST
2006 /* Endian flipping versions of the bmbt extraction functions */
2007 void
xfs_bmbt_disk_get_all(xfs_bmbt_rec_t * r,xfs_bmbt_irec_t * s)2008 xfs_bmbt_disk_get_all(
2009 	xfs_bmbt_rec_t	*r,
2010 	xfs_bmbt_irec_t *s)
2011 {
2012 	__uint64_t	l0, l1;
2013 
2014 	l0 = INT_GET(r->l0, ARCH_CONVERT);
2015 	l1 = INT_GET(r->l1, ARCH_CONVERT);
2016 
2017 	__xfs_bmbt_get_all(l0, l1, s);
2018 }
2019 
2020 /*
2021  * Extract the blockcount field from an on disk bmap extent record.
2022  */
2023 xfs_filblks_t
xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t * r)2024 xfs_bmbt_disk_get_blockcount(
2025 	xfs_bmbt_rec_t	*r)
2026 {
2027 	return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
2028 }
2029 
2030 /*
2031  * Extract the startblock field from an on disk bmap extent record.
2032  */
2033 xfs_fsblock_t
xfs_bmbt_disk_get_startblock(xfs_bmbt_rec_t * r)2034 xfs_bmbt_disk_get_startblock(
2035 	xfs_bmbt_rec_t	*r)
2036 {
2037 #if XFS_BIG_BLKNOS
2038 	return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
2039 	       (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
2040 #else
2041 #ifdef DEBUG
2042 	xfs_dfsbno_t	b;
2043 
2044 	b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
2045 	    (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
2046 	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
2047 	return (xfs_fsblock_t)b;
2048 #else	/* !DEBUG */
2049 	return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
2050 #endif	/* DEBUG */
2051 #endif	/* XFS_BIG_BLKNOS */
2052 }
2053 
2054 /*
2055  * Extract the startoff field from a disk format bmap extent record.
2056  */
2057 xfs_fileoff_t
xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t * r)2058 xfs_bmbt_disk_get_startoff(
2059 	xfs_bmbt_rec_t	*r)
2060 {
2061 	return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
2062 		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
2063 }
2064 
2065 xfs_exntst_t
xfs_bmbt_disk_get_state(xfs_bmbt_rec_t * r)2066 xfs_bmbt_disk_get_state(
2067 	xfs_bmbt_rec_t  *r)
2068 {
2069 	int	ext_flag;
2070 
2071 	ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN));
2072 	return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
2073 				ext_flag);
2074 }
2075 #endif /* XFS_NATIVE_HOST */
2076 
2077 
2078 /*
2079  * Increment cursor by one record at the level.
2080  * For nonzero levels the leaf-ward information is untouched.
2081  */
2082 int						/* error */
xfs_bmbt_increment(xfs_btree_cur_t * cur,int level,int * stat)2083 xfs_bmbt_increment(
2084 	xfs_btree_cur_t		*cur,
2085 	int			level,
2086 	int			*stat)		/* success/failure */
2087 {
2088 	xfs_bmbt_block_t	*block;
2089 	xfs_buf_t		*bp;
2090 	int			error;		/* error return value */
2091 #ifdef XFS_BMBT_TRACE
2092 	static char		fname[] = "xfs_bmbt_increment";
2093 #endif
2094 	xfs_fsblock_t		fsbno;
2095 	int			lev;
2096 	xfs_mount_t		*mp;
2097 	xfs_trans_t		*tp;
2098 
2099 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2100 	XFS_BMBT_TRACE_ARGI(cur, level);
2101 	ASSERT(level < cur->bc_nlevels);
2102 	if (level < cur->bc_nlevels - 1)
2103 		xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
2104 	block = xfs_bmbt_get_block(cur, level, &bp);
2105 #ifdef DEBUG
2106 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
2107 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2108 		return error;
2109 	}
2110 #endif
2111 	if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
2112 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2113 		*stat = 1;
2114 		return 0;
2115 	}
2116 	if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) {
2117 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2118 		*stat = 0;
2119 		return 0;
2120 	}
2121 	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
2122 		block = xfs_bmbt_get_block(cur, lev, &bp);
2123 #ifdef DEBUG
2124 		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
2125 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2126 			return error;
2127 		}
2128 #endif
2129 		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
2130 			break;
2131 		if (lev < cur->bc_nlevels - 1)
2132 			xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
2133 	}
2134 	if (lev == cur->bc_nlevels) {
2135 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2136 		*stat = 0;
2137 		return 0;
2138 	}
2139 	tp = cur->bc_tp;
2140 	mp = cur->bc_mp;
2141 	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
2142 		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
2143 		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
2144 				XFS_BMAP_BTREE_REF))) {
2145 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2146 			return error;
2147 		}
2148 		lev--;
2149 		xfs_btree_setbuf(cur, lev, bp);
2150 		block = XFS_BUF_TO_BMBT_BLOCK(bp);
2151 		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
2152 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2153 			return error;
2154 		}
2155 		cur->bc_ptrs[lev] = 1;
2156 	}
2157 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2158 	*stat = 1;
2159 	return 0;
2160 }
2161 
2162 /*
2163  * Insert the current record at the point referenced by cur.
2164  */
2165 int					/* error */
xfs_bmbt_insert(xfs_btree_cur_t * cur,int * stat)2166 xfs_bmbt_insert(
2167 	xfs_btree_cur_t	*cur,
2168 	int		*stat)		/* success/failure */
2169 {
2170 	int		error;		/* error return value */
2171 #ifdef XFS_BMBT_TRACE
2172 	static char	fname[] = "xfs_bmbt_insert";
2173 #endif
2174 	int		i;
2175 	int		level;
2176 	xfs_fsblock_t	nbno;
2177 	xfs_btree_cur_t	*ncur;
2178 	xfs_bmbt_rec_t	nrec;
2179 	xfs_btree_cur_t	*pcur;
2180 
2181 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2182 	level = 0;
2183 	nbno = NULLFSBLOCK;
2184 	xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
2185 	ncur = (xfs_btree_cur_t *)0;
2186 	pcur = cur;
2187 	do {
2188 		if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
2189 				&i))) {
2190 			if (pcur != cur)
2191 				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2192 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2193 			return error;
2194 		}
2195 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2196 		if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
2197 			cur->bc_nlevels = pcur->bc_nlevels;
2198 			cur->bc_private.b.allocated +=
2199 				pcur->bc_private.b.allocated;
2200 			pcur->bc_private.b.allocated = 0;
2201 			ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) ||
2202 			       (cur->bc_private.b.ip->i_d.di_flags &
2203 				XFS_DIFLAG_REALTIME));
2204 			cur->bc_private.b.firstblock =
2205 				pcur->bc_private.b.firstblock;
2206 			ASSERT(cur->bc_private.b.flist ==
2207 			       pcur->bc_private.b.flist);
2208 			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2209 		}
2210 		if (ncur) {
2211 			pcur = ncur;
2212 			ncur = (xfs_btree_cur_t *)0;
2213 		}
2214 	} while (nbno != NULLFSBLOCK);
2215 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2216 	*stat = i;
2217 	return 0;
2218 error0:
2219 	XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2220 	return error;
2221 }
2222 
2223 /*
2224  * Log fields from the btree block header.
2225  */
2226 void
xfs_bmbt_log_block(xfs_btree_cur_t * cur,xfs_buf_t * bp,int fields)2227 xfs_bmbt_log_block(
2228 	xfs_btree_cur_t		*cur,
2229 	xfs_buf_t		*bp,
2230 	int			fields)
2231 {
2232 	int			first;
2233 #ifdef XFS_BMBT_TRACE
2234 	static char		fname[] = "xfs_bmbt_log_block";
2235 #endif
2236 	int			last;
2237 	xfs_trans_t		*tp;
2238 	static const short	offsets[] = {
2239 		offsetof(xfs_bmbt_block_t, bb_magic),
2240 		offsetof(xfs_bmbt_block_t, bb_level),
2241 		offsetof(xfs_bmbt_block_t, bb_numrecs),
2242 		offsetof(xfs_bmbt_block_t, bb_leftsib),
2243 		offsetof(xfs_bmbt_block_t, bb_rightsib),
2244 		sizeof(xfs_bmbt_block_t)
2245 	};
2246 
2247 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2248 	XFS_BMBT_TRACE_ARGBI(cur, bp, fields);
2249 	tp = cur->bc_tp;
2250 	if (bp) {
2251 		xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first,
2252 				  &last);
2253 		xfs_trans_log_buf(tp, bp, first, last);
2254 	} else
2255 		xfs_trans_log_inode(tp, cur->bc_private.b.ip,
2256 			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
2257 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2258 }
2259 
2260 /*
2261  * Log record values from the btree block.
2262  */
2263 void
xfs_bmbt_log_recs(xfs_btree_cur_t * cur,xfs_buf_t * bp,int rfirst,int rlast)2264 xfs_bmbt_log_recs(
2265 	xfs_btree_cur_t		*cur,
2266 	xfs_buf_t		*bp,
2267 	int			rfirst,
2268 	int			rlast)
2269 {
2270 	xfs_bmbt_block_t	*block;
2271 	int			first;
2272 #ifdef XFS_BMBT_TRACE
2273 	static char		fname[] = "xfs_bmbt_log_recs";
2274 #endif
2275 	int			last;
2276 	xfs_bmbt_rec_t		*rp;
2277 	xfs_trans_t		*tp;
2278 
2279 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2280 	XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
2281 	ASSERT(bp);
2282 	tp = cur->bc_tp;
2283 	block = XFS_BUF_TO_BMBT_BLOCK(bp);
2284 	rp = XFS_BMAP_REC_DADDR(block, 1, cur);
2285 	first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
2286 	last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
2287 	xfs_trans_log_buf(tp, bp, first, last);
2288 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2289 }
2290 
2291 int					/* error */
xfs_bmbt_lookup_eq(xfs_btree_cur_t * cur,xfs_fileoff_t off,xfs_fsblock_t bno,xfs_filblks_t len,int * stat)2292 xfs_bmbt_lookup_eq(
2293 	xfs_btree_cur_t	*cur,
2294 	xfs_fileoff_t	off,
2295 	xfs_fsblock_t	bno,
2296 	xfs_filblks_t	len,
2297 	int		*stat)		/* success/failure */
2298 {
2299 	cur->bc_rec.b.br_startoff = off;
2300 	cur->bc_rec.b.br_startblock = bno;
2301 	cur->bc_rec.b.br_blockcount = len;
2302 	return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat);
2303 }
2304 
2305 int					/* error */
xfs_bmbt_lookup_ge(xfs_btree_cur_t * cur,xfs_fileoff_t off,xfs_fsblock_t bno,xfs_filblks_t len,int * stat)2306 xfs_bmbt_lookup_ge(
2307 	xfs_btree_cur_t	*cur,
2308 	xfs_fileoff_t	off,
2309 	xfs_fsblock_t	bno,
2310 	xfs_filblks_t	len,
2311 	int		*stat)		/* success/failure */
2312 {
2313 	cur->bc_rec.b.br_startoff = off;
2314 	cur->bc_rec.b.br_startblock = bno;
2315 	cur->bc_rec.b.br_blockcount = len;
2316 	return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
2317 }
2318 
2319 /*
2320  * Give the bmap btree a new root block.  Copy the old broot contents
2321  * down into a real block and make the broot point to it.
2322  */
2323 int						/* error */
xfs_bmbt_newroot(xfs_btree_cur_t * cur,int * logflags,int * stat)2324 xfs_bmbt_newroot(
2325 	xfs_btree_cur_t		*cur,		/* btree cursor */
2326 	int			*logflags,	/* logging flags for inode */
2327 	int			*stat)		/* return status - 0 fail */
2328 {
2329 	xfs_alloc_arg_t		args;		/* allocation arguments */
2330 	xfs_bmbt_block_t	*block;		/* bmap btree block */
2331 	xfs_buf_t		*bp;		/* buffer for block */
2332 	xfs_bmbt_block_t	*cblock;	/* child btree block */
2333 	xfs_bmbt_key_t		*ckp;		/* child key pointer */
2334 	xfs_bmbt_ptr_t		*cpp;		/* child ptr pointer */
2335 	int			error;		/* error return code */
2336 #ifdef XFS_BMBT_TRACE
2337 	static char		fname[] = "xfs_bmbt_newroot";
2338 #endif
2339 #ifdef DEBUG
2340 	int			i;		/* loop counter */
2341 #endif
2342 	xfs_bmbt_key_t		*kp;		/* pointer to bmap btree key */
2343 	int			level;		/* btree level */
2344 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
2345 
2346 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2347 	level = cur->bc_nlevels - 1;
2348 	block = xfs_bmbt_get_block(cur, level, &bp);
2349 	/*
2350 	 * Copy the root into a real block.
2351 	 */
2352 	args.mp = cur->bc_mp;
2353 	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
2354 	args.tp = cur->bc_tp;
2355 	args.fsbno = cur->bc_private.b.firstblock;
2356 	args.mod = args.minleft = args.alignment = args.total = args.isfl =
2357 		args.userdata = args.minalignslop = 0;
2358 	args.minlen = args.maxlen = args.prod = 1;
2359 	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
2360 	if (args.fsbno == NULLFSBLOCK) {
2361 #ifdef DEBUG
2362 		if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
2363 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2364 			return error;
2365 		}
2366 #endif
2367 		args.fsbno = INT_GET(*pp, ARCH_CONVERT);
2368 		args.type = XFS_ALLOCTYPE_START_BNO;
2369 	} else if (args.wasdel)
2370 		args.type = XFS_ALLOCTYPE_FIRST_AG;
2371 	else
2372 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
2373 	if ((error = xfs_alloc_vextent(&args))) {
2374 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2375 		return error;
2376 	}
2377 	if (args.fsbno == NULLFSBLOCK) {
2378 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2379 		*stat = 0;
2380 		return 0;
2381 	}
2382 	ASSERT(args.len == 1);
2383 	cur->bc_private.b.firstblock = args.fsbno;
2384 	cur->bc_private.b.allocated++;
2385 	cur->bc_private.b.ip->i_d.di_nblocks++;
2386 	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
2387 			  XFS_TRANS_DQ_BCOUNT, 1L);
2388 	bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
2389 	cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
2390 	*cblock = *block;
2391 	be16_add(&block->bb_level, 1);
2392 	block->bb_numrecs = cpu_to_be16(1);
2393 	cur->bc_nlevels++;
2394 	cur->bc_ptrs[level + 1] = 1;
2395 	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
2396 	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
2397 	memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp));
2398 	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
2399 #ifdef DEBUG
2400 	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
2401 		if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
2402 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2403 			return error;
2404 		}
2405 	}
2406 #endif
2407 	memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
2408 #ifdef DEBUG
2409 	if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno,
2410 			level))) {
2411 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2412 		return error;
2413 	}
2414 #endif
2415 	INT_SET(*pp, ARCH_CONVERT, args.fsbno);
2416 	xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
2417 		cur->bc_private.b.whichfork);
2418 	xfs_btree_setbuf(cur, level, bp);
2419 	/*
2420 	 * Do all this logging at the end so that
2421 	 * the root is at the right level.
2422 	 */
2423 	xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS);
2424 	xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
2425 	xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
2426 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2427 	*logflags |=
2428 		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
2429 	*stat = 1;
2430 	return 0;
2431 }
2432 
2433 /*
2434  * Set all the fields in a bmap extent record from the uncompressed form.
2435  */
2436 void
xfs_bmbt_set_all(xfs_bmbt_rec_t * r,xfs_bmbt_irec_t * s)2437 xfs_bmbt_set_all(
2438 	xfs_bmbt_rec_t	*r,
2439 	xfs_bmbt_irec_t	*s)
2440 {
2441 	int	extent_flag;
2442 
2443 	ASSERT((s->br_state == XFS_EXT_NORM) ||
2444 		(s->br_state == XFS_EXT_UNWRITTEN));
2445 	extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
2446 	ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
2447 	ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
2448 #if XFS_BIG_BLKNOS
2449 	ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
2450 	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2451 		 ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2452 		 ((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
2453 	r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2454 		 ((xfs_bmbt_rec_base_t)s->br_blockcount &
2455 		 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2456 #else	/* !XFS_BIG_BLKNOS */
2457 	if (ISNULLSTARTBLOCK(s->br_startblock)) {
2458 		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2459 			((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2460 			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2461 		r->l1 = XFS_MASK64HI(11) |
2462 			  ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2463 			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2464 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2465 	} else {
2466 		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2467 			((xfs_bmbt_rec_base_t)s->br_startoff << 9);
2468 		r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2469 			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2470 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2471 	}
2472 #endif	/* XFS_BIG_BLKNOS */
2473 }
2474 
2475 /*
2476  * Set all the fields in a bmap extent record from the arguments.
2477  */
2478 void
xfs_bmbt_set_allf(xfs_bmbt_rec_t * r,xfs_fileoff_t o,xfs_fsblock_t b,xfs_filblks_t c,xfs_exntst_t v)2479 xfs_bmbt_set_allf(
2480 	xfs_bmbt_rec_t	*r,
2481 	xfs_fileoff_t	o,
2482 	xfs_fsblock_t	b,
2483 	xfs_filblks_t	c,
2484 	xfs_exntst_t	v)
2485 {
2486 	int	extent_flag;
2487 
2488 	ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
2489 	extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
2490 	ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
2491 	ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
2492 #if XFS_BIG_BLKNOS
2493 	ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
2494 	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2495 		((xfs_bmbt_rec_base_t)o << 9) |
2496 		((xfs_bmbt_rec_base_t)b >> 43);
2497 	r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
2498 		((xfs_bmbt_rec_base_t)c &
2499 		(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2500 #else	/* !XFS_BIG_BLKNOS */
2501 	if (ISNULLSTARTBLOCK(b)) {
2502 		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2503 			((xfs_bmbt_rec_base_t)o << 9) |
2504 			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2505 		r->l1 = XFS_MASK64HI(11) |
2506 			  ((xfs_bmbt_rec_base_t)b << 21) |
2507 			  ((xfs_bmbt_rec_base_t)c &
2508 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2509 	} else {
2510 		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2511 			((xfs_bmbt_rec_base_t)o << 9);
2512 		r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
2513 			 ((xfs_bmbt_rec_base_t)c &
2514 			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2515 	}
2516 #endif	/* XFS_BIG_BLKNOS */
2517 }
2518 
2519 #ifndef XFS_NATIVE_HOST
2520 /*
2521  * Set all the fields in a bmap extent record from the uncompressed form.
2522  */
2523 void
xfs_bmbt_disk_set_all(xfs_bmbt_rec_t * r,xfs_bmbt_irec_t * s)2524 xfs_bmbt_disk_set_all(
2525 	xfs_bmbt_rec_t	*r,
2526 	xfs_bmbt_irec_t *s)
2527 {
2528 	int	extent_flag;
2529 
2530 	ASSERT((s->br_state == XFS_EXT_NORM) ||
2531 		(s->br_state == XFS_EXT_UNWRITTEN));
2532 	extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
2533 	ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
2534 	ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
2535 #if XFS_BIG_BLKNOS
2536 	ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
2537 	INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2538 		  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2539 		  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
2540 	INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2541 		  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2542 		   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2543 #else	/* !XFS_BIG_BLKNOS */
2544 	if (ISNULLSTARTBLOCK(s->br_startblock)) {
2545 		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2546 			((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2547 			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2548 		INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
2549 			  ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2550 			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2551 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2552 	} else {
2553 		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2554 			((xfs_bmbt_rec_base_t)s->br_startoff << 9));
2555 		INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2556 			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2557 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2558 	}
2559 #endif	/* XFS_BIG_BLKNOS */
2560 }
2561 
2562 /*
2563  * Set all the fields in a disk format bmap extent record from the arguments.
2564  */
2565 void
xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t * r,xfs_fileoff_t o,xfs_fsblock_t b,xfs_filblks_t c,xfs_exntst_t v)2566 xfs_bmbt_disk_set_allf(
2567 	xfs_bmbt_rec_t	*r,
2568 	xfs_fileoff_t	o,
2569 	xfs_fsblock_t	b,
2570 	xfs_filblks_t	c,
2571 	xfs_exntst_t	v)
2572 {
2573 	int	extent_flag;
2574 
2575 	ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
2576 	extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
2577 	ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
2578 	ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
2579 #if XFS_BIG_BLKNOS
2580 	ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
2581 	INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2582 		((xfs_bmbt_rec_base_t)o << 9) |
2583 		((xfs_bmbt_rec_base_t)b >> 43));
2584 	INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
2585 		  ((xfs_bmbt_rec_base_t)c &
2586 		   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2587 #else	/* !XFS_BIG_BLKNOS */
2588 	if (ISNULLSTARTBLOCK(b)) {
2589 		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2590 			((xfs_bmbt_rec_base_t)o << 9) |
2591 			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2592 		INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
2593 			  ((xfs_bmbt_rec_base_t)b << 21) |
2594 			  ((xfs_bmbt_rec_base_t)c &
2595 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2596 	} else {
2597 		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2598 			((xfs_bmbt_rec_base_t)o << 9));
2599 		INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
2600 			  ((xfs_bmbt_rec_base_t)c &
2601 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2602 	}
2603 #endif	/* XFS_BIG_BLKNOS */
2604 }
2605 #endif /* XFS_NATIVE_HOST */
2606 
2607 /*
2608  * Set the blockcount field in a bmap extent record.
2609  */
2610 void
xfs_bmbt_set_blockcount(xfs_bmbt_rec_t * r,xfs_filblks_t v)2611 xfs_bmbt_set_blockcount(
2612 	xfs_bmbt_rec_t	*r,
2613 	xfs_filblks_t	v)
2614 {
2615 	ASSERT((v & XFS_MASK64HI(43)) == 0);
2616 	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) |
2617 		  (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21));
2618 }
2619 
2620 /*
2621  * Set the startblock field in a bmap extent record.
2622  */
2623 void
xfs_bmbt_set_startblock(xfs_bmbt_rec_t * r,xfs_fsblock_t v)2624 xfs_bmbt_set_startblock(
2625 	xfs_bmbt_rec_t	*r,
2626 	xfs_fsblock_t	v)
2627 {
2628 #if XFS_BIG_BLKNOS
2629 	ASSERT((v & XFS_MASK64HI(12)) == 0);
2630 	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) |
2631 		  (xfs_bmbt_rec_base_t)(v >> 43);
2632 	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) |
2633 		  (xfs_bmbt_rec_base_t)(v << 21);
2634 #else	/* !XFS_BIG_BLKNOS */
2635 	if (ISNULLSTARTBLOCK(v)) {
2636 		r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2637 		r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) |
2638 			  ((xfs_bmbt_rec_base_t)v << 21) |
2639 			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2640 	} else {
2641 		r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2642 		r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
2643 			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2644 	}
2645 #endif	/* XFS_BIG_BLKNOS */
2646 }
2647 
2648 /*
2649  * Set the startoff field in a bmap extent record.
2650  */
2651 void
xfs_bmbt_set_startoff(xfs_bmbt_rec_t * r,xfs_fileoff_t v)2652 xfs_bmbt_set_startoff(
2653 	xfs_bmbt_rec_t	*r,
2654 	xfs_fileoff_t	v)
2655 {
2656 	ASSERT((v & XFS_MASK64HI(9)) == 0);
2657 	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) |
2658 		((xfs_bmbt_rec_base_t)v << 9) |
2659 		  (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2660 }
2661 
2662 /*
2663  * Set the extent state field in a bmap extent record.
2664  */
2665 void
xfs_bmbt_set_state(xfs_bmbt_rec_t * r,xfs_exntst_t v)2666 xfs_bmbt_set_state(
2667 	xfs_bmbt_rec_t	*r,
2668 	xfs_exntst_t	v)
2669 {
2670 	ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
2671 	if (v == XFS_EXT_NORM)
2672 		r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN);
2673 	else
2674 		r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN);
2675 }
2676 
2677 /*
2678  * Convert in-memory form of btree root to on-disk form.
2679  */
2680 void
xfs_bmbt_to_bmdr(xfs_bmbt_block_t * rblock,int rblocklen,xfs_bmdr_block_t * dblock,int dblocklen)2681 xfs_bmbt_to_bmdr(
2682 	xfs_bmbt_block_t	*rblock,
2683 	int			rblocklen,
2684 	xfs_bmdr_block_t	*dblock,
2685 	int			dblocklen)
2686 {
2687 	int			dmxr;
2688 	xfs_bmbt_key_t		*fkp;
2689 	xfs_bmbt_ptr_t		*fpp;
2690 	xfs_bmbt_key_t		*tkp;
2691 	xfs_bmbt_ptr_t		*tpp;
2692 
2693 	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
2694 	ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
2695 	ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO);
2696 	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
2697 	dblock->bb_level = rblock->bb_level;
2698 	dblock->bb_numrecs = rblock->bb_numrecs;
2699 	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
2700 	fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
2701 	tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
2702 	fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
2703 	tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
2704 	dmxr = be16_to_cpu(dblock->bb_numrecs);
2705 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
2706 	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
2707 }
2708 
2709 /*
2710  * Update the record to the passed values.
2711  */
2712 int
xfs_bmbt_update(xfs_btree_cur_t * cur,xfs_fileoff_t off,xfs_fsblock_t bno,xfs_filblks_t len,xfs_exntst_t state)2713 xfs_bmbt_update(
2714 	xfs_btree_cur_t		*cur,
2715 	xfs_fileoff_t		off,
2716 	xfs_fsblock_t		bno,
2717 	xfs_filblks_t		len,
2718 	xfs_exntst_t		state)
2719 {
2720 	xfs_bmbt_block_t	*block;
2721 	xfs_buf_t		*bp;
2722 	int			error;
2723 #ifdef XFS_BMBT_TRACE
2724 	static char		fname[] = "xfs_bmbt_update";
2725 #endif
2726 	xfs_bmbt_key_t		key;
2727 	int			ptr;
2728 	xfs_bmbt_rec_t		*rp;
2729 
2730 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2731 	XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
2732 		(xfs_dfilblks_t)len, (int)state);
2733 	block = xfs_bmbt_get_block(cur, 0, &bp);
2734 #ifdef DEBUG
2735 	if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
2736 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2737 		return error;
2738 	}
2739 #endif
2740 	ptr = cur->bc_ptrs[0];
2741 	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
2742 	xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
2743 	xfs_bmbt_log_recs(cur, bp, ptr, ptr);
2744 	if (ptr > 1) {
2745 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2746 		return 0;
2747 	}
2748 	INT_SET(key.br_startoff, ARCH_CONVERT, off);
2749 	if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
2750 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2751 		return error;
2752 	}
2753 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2754 	return 0;
2755 }
2756 
2757 /*
2758  * Check extent records, which have just been read, for
2759  * any bit in the extent flag field. ASSERT on debug
2760  * kernels, as this condition should not occur.
2761  * Return an error condition (1) if any flags found,
2762  * otherwise return 0.
2763  */
2764 
2765 int
xfs_check_nostate_extents(xfs_ifork_t * ifp,xfs_extnum_t idx,xfs_extnum_t num)2766 xfs_check_nostate_extents(
2767 	xfs_ifork_t		*ifp,
2768 	xfs_extnum_t		idx,
2769 	xfs_extnum_t		num)
2770 {
2771 	xfs_bmbt_rec_t		*ep;
2772 
2773 	for (; num > 0; num--, idx++) {
2774 		ep = xfs_iext_get_ext(ifp, idx);
2775 		if ((ep->l0 >>
2776 		     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
2777 			ASSERT(0);
2778 			return 1;
2779 		}
2780 	}
2781 	return 0;
2782 }
2783