| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:58:39 +11:00
										 |  |  |  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 
					
						
							|  |  |  |  * All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-02 14:58:39 +11:00
										 |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License as | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * published by the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-02 14:58:39 +11:00
										 |  |  |  * This program is distributed in the hope that it would be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-02 14:58:39 +11:00
										 |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | #include "xfs.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_fs.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_types.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_bit.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_log.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_inum.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_trans.h"
 | 
					
						
							|  |  |  | #include "xfs_sb.h"
 | 
					
						
							|  |  |  | #include "xfs_ag.h"
 | 
					
						
							|  |  |  | #include "xfs_dir2.h"
 | 
					
						
							|  |  |  | #include "xfs_dmapi.h"
 | 
					
						
							|  |  |  | #include "xfs_mount.h"
 | 
					
						
							|  |  |  | #include "xfs_bmap_btree.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_alloc_btree.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_ialloc_btree.h"
 | 
					
						
							|  |  |  | #include "xfs_dir2_sf.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_attr_sf.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_dinode.h"
 | 
					
						
							|  |  |  | #include "xfs_inode.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_inode_item.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_alloc.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-02 14:38:42 +11:00
										 |  |  | #include "xfs_btree.h"
 | 
					
						
							|  |  |  | #include "xfs_ialloc.h"
 | 
					
						
							|  |  |  | #include "xfs_itable.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "xfs_bmap.h"
 | 
					
						
							|  |  |  | #include "xfs_error.h"
 | 
					
						
							|  |  |  | #include "xfs_quota.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(XFS_BMBT_TRACE)
 | 
					
						
							|  |  |  | ktrace_t	*xfs_bmbt_trace_buf; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Prototypes for internal btree functions. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); | 
					
						
							|  |  |  | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 
					
						
							|  |  |  | STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 
					
						
							|  |  |  | STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); | 
					
						
							|  |  |  | STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *); | 
					
						
							|  |  |  | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 		__uint64_t *, xfs_btree_cur_t **, int *); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(XFS_BMBT_TRACE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char	ARGS[] = "args"; | 
					
						
							|  |  |  | static char	ENTRY[] = "entry"; | 
					
						
							|  |  |  | static char	ERROR[] = "error"; | 
					
						
							|  |  |  | #undef EXIT
 | 
					
						
							|  |  |  | static char	EXIT[] = "exit"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for the arguments given to the routine, | 
					
						
							|  |  |  |  * generic form. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_enter( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char	*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_inode_t	*ip; | 
					
						
							|  |  |  | 	int		whichfork; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ip = cur->bc_private.b.ip; | 
					
						
							|  |  |  | 	whichfork = cur->bc_private.b.whichfork; | 
					
						
							|  |  |  | 	ktrace_enter(xfs_bmbt_trace_buf, | 
					
						
							|  |  |  | 		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | 
					
						
							|  |  |  | 		(void *)func, (void *)s, (void *)ip, (void *)cur, | 
					
						
							|  |  |  | 		(void *)a0, (void *)a1, (void *)a2, (void *)a3, | 
					
						
							|  |  |  | 		(void *)a4, (void *)a5, (void *)a6, (void *)a7, | 
					
						
							|  |  |  | 		(void *)a8, (void *)a9, (void *)a10); | 
					
						
							|  |  |  | 	ASSERT(ip->i_btrace); | 
					
						
							|  |  |  | 	ktrace_enter(ip->i_btrace, | 
					
						
							|  |  |  | 		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | 
					
						
							|  |  |  | 		(void *)func, (void *)s, (void *)ip, (void *)cur, | 
					
						
							|  |  |  | 		(void *)a0, (void *)a1, (void *)a2, (void *)a3, | 
					
						
							|  |  |  | 		(void *)a4, (void *)a5, (void *)a6, (void *)a7, | 
					
						
							|  |  |  | 		(void *)a8, (void *)a9, (void *)a10); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for a buffer & 1 integer arg. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argbi( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char	*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	xfs_buf_t	*b, | 
					
						
							|  |  |  | 	int		i, | 
					
						
							|  |  |  | 	int		line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line, | 
					
						
							|  |  |  | 		(__psunsigned_t)b, i, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for a buffer & 2 integer args. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argbii( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char	*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	xfs_buf_t	*b, | 
					
						
							|  |  |  | 	int		i0, | 
					
						
							|  |  |  | 	int		i1, | 
					
						
							|  |  |  | 	int		line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line, | 
					
						
							|  |  |  | 		(__psunsigned_t)b, i0, i1, 0, | 
					
						
							|  |  |  | 		0, 0, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for 3 block-length args | 
					
						
							|  |  |  |  * and an integer arg. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argfffi( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char		*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	xfs_dfiloff_t		o, | 
					
						
							|  |  |  | 	xfs_dfsbno_t		b, | 
					
						
							|  |  |  | 	xfs_dfilblks_t		i, | 
					
						
							|  |  |  | 	int			j, | 
					
						
							|  |  |  | 	int			line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line, | 
					
						
							|  |  |  | 		o >> 32, (int)o, b >> 32, (int)b, | 
					
						
							|  |  |  | 		i >> 32, (int)i, (int)j, 0, | 
					
						
							|  |  |  | 		0, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for one integer arg. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argi( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char	*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	int		i, | 
					
						
							|  |  |  | 	int		line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line, | 
					
						
							|  |  |  | 		i, 0, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for int, fsblock, key. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argifk( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char		*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			i, | 
					
						
							|  |  |  | 	xfs_fsblock_t		f, | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	xfs_dfiloff_t		o, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	int			line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 		i, (xfs_dfsbno_t)f >> 32, (int)f, o >> 32, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		(int)o, 0, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for int, fsblock, rec. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argifr( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char		*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			i, | 
					
						
							|  |  |  | 	xfs_fsblock_t		f, | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*r, | 
					
						
							|  |  |  | 	int			line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_dfsbno_t		b; | 
					
						
							|  |  |  | 	xfs_dfilblks_t		c; | 
					
						
							|  |  |  | 	xfs_dfsbno_t		d; | 
					
						
							|  |  |  | 	xfs_dfiloff_t		o; | 
					
						
							|  |  |  | 	xfs_bmbt_irec_t		s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d = (xfs_dfsbno_t)f; | 
					
						
							|  |  |  | 	xfs_bmbt_disk_get_all(r, &s); | 
					
						
							|  |  |  | 	o = (xfs_dfiloff_t)s.br_startoff; | 
					
						
							|  |  |  | 	b = (xfs_dfsbno_t)s.br_startblock; | 
					
						
							|  |  |  | 	c = s.br_blockcount; | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line, | 
					
						
							|  |  |  | 		i, d >> 32, (int)d, o >> 32, | 
					
						
							|  |  |  | 		(int)o, b >> 32, (int)b, c >> 32, | 
					
						
							|  |  |  | 		(int)c, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for arguments, for int, key. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_argik( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char		*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			i, | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*k, | 
					
						
							|  |  |  | 	int			line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_dfiloff_t		o; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	o = be64_to_cpu(k->br_startoff); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, | 
					
						
							|  |  |  | 		i, o >> 32, (int)o, 0, | 
					
						
							|  |  |  | 		0, 0, 0, 0, | 
					
						
							|  |  |  | 		0, 0, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add a trace buffer entry for the cursor/operation. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_trace_cursor( | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	const char	*func, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	char		*s, | 
					
						
							|  |  |  | 	int		line) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t	r; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	xfs_bmbt_set_all(&r, &cur->bc_rec.b); | 
					
						
							|  |  |  | 	xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line, | 
					
						
							|  |  |  | 		(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) | | 
					
						
							|  |  |  | 		cur->bc_private.b.allocated, | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 		r.l0 >> 32, (int)r.l0, | 
					
						
							|  |  |  | 		r.l1 >> 32, (int)r.l1, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1], | 
					
						
							|  |  |  | 		(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3], | 
					
						
							|  |  |  | 		(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1], | 
					
						
							|  |  |  | 		(cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_ARGBI(c,b,i)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGI(c,i)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__) | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGIFK(c,i,f,s)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_CURSOR(c,s)	\
 | 
					
						
							| 
									
										
										
										
											2007-07-11 11:09:47 +10:00
										 |  |  | 	xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_ARGBI(c,b,i)
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_ARGI(c,i)
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGIFK(c,i,f,s)
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_ARGIK(c,i,k)
 | 
					
						
							|  |  |  | #define	XFS_BMBT_TRACE_CURSOR(c,s)
 | 
					
						
							|  |  |  | #endif	/* XFS_BMBT_TRACE */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Internal functions. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Delete record pointed to by cur/level. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC int					/* error */ | 
					
						
							|  |  |  | xfs_bmbt_delrec( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block;		/* bmap btree block */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		bno;		/* fs-relative block number */ | 
					
						
							|  |  |  | 	xfs_buf_t		*bp;		/* buffer for block */ | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	int			i;		/* loop counter */ | 
					
						
							|  |  |  | 	int			j;		/* temp state */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		key;		/* bmap btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		lbno;		/* left sibling block number */ | 
					
						
							|  |  |  | 	xfs_buf_t		*lbp;		/* left buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*left;		/* left btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*lkp;		/* left btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */ | 
					
						
							|  |  |  | 	int			lrecs=0;	/* left record count */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*lrp;		/* left record pointer */ | 
					
						
							|  |  |  | 	xfs_mount_t		*mp;		/* file system mount point */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */ | 
					
						
							|  |  |  | 	int			ptr;		/* key/record index */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		rbno;		/* right sibling block number */ | 
					
						
							|  |  |  | 	xfs_buf_t		*rbp;		/* right buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*right;		/* right btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*rkp;		/* right btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rp;		/* pointer to bmap btree rec */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */ | 
					
						
							|  |  |  | 	xfs_buf_t		*rrbp;		/* right-right buffer pointer */ | 
					
						
							|  |  |  | 	int			rrecs=0;	/* right record count */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rrp;		/* right record pointer */ | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*tcur;		/* temporary btree cursor */ | 
					
						
							|  |  |  | 	int			numrecs;	/* temporary numrec count */ | 
					
						
							|  |  |  | 	int			numlrecs, numrrecs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGI(cur, level); | 
					
						
							|  |  |  | 	ptr = cur->bc_ptrs[level]; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:40 +10:00
										 |  |  | 	tcur = NULL; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ptr == 0) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	numrecs = be16_to_cpu(block->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		goto error0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (ptr > numrecs) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_STATS_INC(xs_bmbt_delrec); | 
					
						
							|  |  |  | 	if (level > 0) { | 
					
						
							|  |  |  | 		kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 		pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		for (i = ptr; i < numrecs; i++) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				goto error0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		if (ptr < numrecs) { | 
					
						
							|  |  |  | 			memmove(&kp[ptr - 1], &kp[ptr], | 
					
						
							|  |  |  | 				(numrecs - ptr) * sizeof(*kp)); | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:11 +10:00
										 |  |  | 			memmove(&pp[ptr - 1], &pp[ptr], | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				(numrecs - ptr) * sizeof(*pp)); | 
					
						
							|  |  |  | 			xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1); | 
					
						
							|  |  |  | 			xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		rp = XFS_BMAP_REC_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 		if (ptr < numrecs) { | 
					
						
							|  |  |  | 			memmove(&rp[ptr - 1], &rp[ptr], | 
					
						
							|  |  |  | 				(numrecs - ptr) * sizeof(*rp)); | 
					
						
							|  |  |  | 			xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (ptr == 1) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 			key.br_startoff = | 
					
						
							|  |  |  | 				cpu_to_be64(xfs_bmbt_disk_get_startoff(rp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			kp = &key; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	numrecs--; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	block->bb_numrecs = cpu_to_be16(numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * We're at the root level. | 
					
						
							|  |  |  | 	 * First, shrink the root block in-memory. | 
					
						
							|  |  |  | 	 * Try to get rid of the next level down. | 
					
						
							|  |  |  | 	 * If we can't then there's nothing left to do. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (level == cur->bc_nlevels - 1) { | 
					
						
							|  |  |  | 		xfs_iroot_realloc(cur->bc_private.b.ip, -1, | 
					
						
							|  |  |  | 			cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 		if ((error = xfs_bmbt_killroot(cur))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		goto error0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 
					
						
							|  |  |  | 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	rbno = be64_to_cpu(block->bb_rightsib); | 
					
						
							|  |  |  | 	lbno = be64_to_cpu(block->bb_leftsib); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * One child of root, need to get a chance to copy its contents | 
					
						
							|  |  |  | 	 * into the root and delete it. Can't go up to next level, | 
					
						
							|  |  |  | 	 * there's nothing to delete there. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && | 
					
						
							|  |  |  | 	    level == cur->bc_nlevels - 2) { | 
					
						
							|  |  |  | 		if ((error = xfs_bmbt_killroot(cur))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK); | 
					
						
							|  |  |  | 	if ((error = xfs_btree_dup_cursor(cur, &tcur))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		goto error0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	bno = NULLFSBLOCK; | 
					
						
							|  |  |  | 	if (rbno != NULLFSBLOCK) { | 
					
						
							|  |  |  | 		i = xfs_btree_lastrec(tcur, level); | 
					
						
							|  |  |  | 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		if ((error = xfs_bmbt_increment(tcur, level, &i))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		i = xfs_btree_lastrec(tcur, level); | 
					
						
							|  |  |  | 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		rbp = tcur->bc_bufs[level]; | 
					
						
							|  |  |  | 		right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		bno = be64_to_cpu(right->bb_leftsib); | 
					
						
							|  |  |  | 		if (be16_to_cpu(right->bb_numrecs) - 1 >= | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 
					
						
							|  |  |  | 			if ((error = xfs_bmbt_lshift(tcur, level, &i))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				goto error0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (i) { | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 				ASSERT(be16_to_cpu(block->bb_numrecs) >= | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				       XFS_BMAP_BLOCK_IMINRECS(level, tcur)); | 
					
						
							|  |  |  | 				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 
					
						
							|  |  |  | 				tcur = NULL; | 
					
						
							|  |  |  | 				if (level > 0) { | 
					
						
							|  |  |  | 					if ((error = xfs_bmbt_decrement(cur, | 
					
						
							|  |  |  | 							level, &i))) { | 
					
						
							|  |  |  | 						XFS_BMBT_TRACE_CURSOR(cur, | 
					
						
							|  |  |  | 							ERROR); | 
					
						
							|  |  |  | 						goto error0; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 				*stat = 1; | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		rrecs = be16_to_cpu(right->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if (lbno != NULLFSBLOCK) { | 
					
						
							|  |  |  | 			i = xfs_btree_firstrec(tcur, level); | 
					
						
							|  |  |  | 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 			if ((error = xfs_bmbt_decrement(tcur, level, &i))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				goto error0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lbno != NULLFSBLOCK) { | 
					
						
							|  |  |  | 		i = xfs_btree_firstrec(tcur, level); | 
					
						
							|  |  |  | 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * decrement to last in block | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if ((error = xfs_bmbt_decrement(tcur, level, &i))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		i = xfs_btree_firstrec(tcur, level); | 
					
						
							|  |  |  | 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		lbp = tcur->bc_bufs[level]; | 
					
						
							|  |  |  | 		left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		bno = be64_to_cpu(left->bb_rightsib); | 
					
						
							|  |  |  | 		if (be16_to_cpu(left->bb_numrecs) - 1 >= | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 
					
						
							|  |  |  | 			if ((error = xfs_bmbt_rshift(tcur, level, &i))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				goto error0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (i) { | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 				ASSERT(be16_to_cpu(block->bb_numrecs) >= | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				       XFS_BMAP_BLOCK_IMINRECS(level, tcur)); | 
					
						
							|  |  |  | 				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 
					
						
							|  |  |  | 				tcur = NULL; | 
					
						
							|  |  |  | 				if (level == 0) | 
					
						
							|  |  |  | 					cur->bc_ptrs[0]++; | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 				*stat = 1; | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		lrecs = be16_to_cpu(left->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 
					
						
							|  |  |  | 	tcur = NULL; | 
					
						
							|  |  |  | 	mp = cur->bc_mp; | 
					
						
							|  |  |  | 	ASSERT(bno != NULLFSBLOCK); | 
					
						
							|  |  |  | 	if (lbno != NULLFSBLOCK && | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	    lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		rbno = bno; | 
					
						
							|  |  |  | 		right = block; | 
					
						
							|  |  |  | 		rbp = bp; | 
					
						
							|  |  |  | 		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp, | 
					
						
							|  |  |  | 				XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if (rbno != NULLFSBLOCK && | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		   rrecs + be16_to_cpu(block->bb_numrecs) <= | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		   XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 
					
						
							|  |  |  | 		lbno = bno; | 
					
						
							|  |  |  | 		left = block; | 
					
						
							|  |  |  | 		lbp = bp; | 
					
						
							|  |  |  | 		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp, | 
					
						
							|  |  |  | 				XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		lrecs = be16_to_cpu(left->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	numlrecs = be16_to_cpu(left->bb_numrecs); | 
					
						
							|  |  |  | 	numrrecs = be16_to_cpu(right->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (level > 0) { | 
					
						
							|  |  |  | 		lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur); | 
					
						
							|  |  |  | 		lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur); | 
					
						
							|  |  |  | 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | 
					
						
							|  |  |  | 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		for (i = 0; i < numrrecs; i++) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				goto error0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		memcpy(lkp, rkp, numrrecs * sizeof(*lkp)); | 
					
						
							|  |  |  | 		memcpy(lpp, rpp, numrrecs * sizeof(*lpp)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | 
					
						
							|  |  |  | 		xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur); | 
					
						
							|  |  |  | 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | 
					
						
							|  |  |  | 		memcpy(lrp, rrp, numrrecs * sizeof(*lrp)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&left->bb_numrecs, numrrecs); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	left->bb_rightsib = right->bb_rightsib; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 				be64_to_cpu(left->bb_rightsib), | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				0, &rrbp, XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			goto error0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		rrblock->bb_leftsib = cpu_to_be64(lbno); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, | 
					
						
							|  |  |  | 		cur->bc_private.b.flist, mp); | 
					
						
							|  |  |  | 	cur->bc_private.b.ip->i_d.di_nblocks--; | 
					
						
							|  |  |  | 	xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | 
					
						
							|  |  |  | 	XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, | 
					
						
							|  |  |  | 			XFS_TRANS_DQ_BCOUNT, -1L); | 
					
						
							|  |  |  | 	xfs_trans_binval(cur->bc_tp, rbp); | 
					
						
							|  |  |  | 	if (bp != lbp) { | 
					
						
							|  |  |  | 		cur->bc_bufs[level] = lbp; | 
					
						
							|  |  |  | 		cur->bc_ptrs[level] += lrecs; | 
					
						
							|  |  |  | 		cur->bc_ra[level] = 0; | 
					
						
							|  |  |  | 	} else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		goto error0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (level > 0) | 
					
						
							|  |  |  | 		cur->bc_ptrs[level]--; | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 2; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error0: | 
					
						
							|  |  |  | 	if (tcur) | 
					
						
							|  |  |  | 		xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | 
					
						
							|  |  |  | 	return error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Insert one record/level.  Return information to the caller | 
					
						
							|  |  |  |  * allowing the next level up to proceed if necessary. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 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)		/* no-go/done/continue */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block;		/* bmap btree block */ | 
					
						
							|  |  |  | 	xfs_buf_t		*bp;		/* buffer for block */ | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	int			i;		/* loop index */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		key;		/* bmap btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */ | 
					
						
							|  |  |  | 	int			logflags;	/* inode logging flags */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		nbno;		/* new block number */ | 
					
						
							|  |  |  | 	struct xfs_btree_cur	*ncur;		/* new btree cursor */ | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	__uint64_t		startoff;	/* new btree key value */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_rec_t		nrec;		/* new record count */ | 
					
						
							|  |  |  | 	int			optr;		/* old key/record index */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */ | 
					
						
							|  |  |  | 	int			ptr;		/* key/record index */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rp=NULL;	/* pointer to bmap btree rec */ | 
					
						
							|  |  |  | 	int			numrecs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASSERT(level < cur->bc_nlevels); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:40 +10:00
										 |  |  | 	ncur = NULL; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	optr = ptr = cur->bc_ptrs[level]; | 
					
						
							|  |  |  | 	if (ptr == 0) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_STATS_INC(xs_bmbt_insrec); | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	numrecs = be16_to_cpu(block->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ptr <= numrecs) { | 
					
						
							|  |  |  | 		if (level == 0) { | 
					
						
							|  |  |  | 			rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | 
					
						
							|  |  |  | 			xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); | 
					
						
							|  |  |  | 			xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	nbno = NULLFSBLOCK; | 
					
						
							|  |  |  | 	if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 
					
						
							|  |  |  | 		if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | 
					
						
							|  |  |  | 			/*
 | 
					
						
							|  |  |  | 			 * A root block, that can be made bigger. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			xfs_iroot_realloc(cur->bc_private.b.ip, 1, | 
					
						
							|  |  |  | 				cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 			block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | 		} else if (level == cur->bc_nlevels - 1) { | 
					
						
							|  |  |  | 			if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || | 
					
						
							|  |  |  | 			    *stat == 0) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | 
					
						
							|  |  |  | 				logflags); | 
					
						
							|  |  |  | 			block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if ((error = xfs_bmbt_rshift(cur, level, &i))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (i) { | 
					
						
							|  |  |  | 				/* nothing */ | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				if ((error = xfs_bmbt_lshift(cur, level, &i))) { | 
					
						
							|  |  |  | 					XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 					return error; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (i) { | 
					
						
							|  |  |  | 					optr = ptr = cur->bc_ptrs[level]; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if ((error = xfs_bmbt_split(cur, level, | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 							&nbno, &startoff, &ncur, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 							&i))) { | 
					
						
							|  |  |  | 						XFS_BMBT_TRACE_CURSOR(cur, | 
					
						
							|  |  |  | 							ERROR); | 
					
						
							|  |  |  | 						return error; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (i) { | 
					
						
							|  |  |  | 						block = xfs_bmbt_get_block( | 
					
						
							|  |  |  | 							    cur, level, &bp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 						if ((error = | 
					
						
							|  |  |  | 						    xfs_btree_check_lblock(cur, | 
					
						
							|  |  |  | 							    block, level, bp))) { | 
					
						
							|  |  |  | 							XFS_BMBT_TRACE_CURSOR( | 
					
						
							|  |  |  | 								cur, ERROR); | 
					
						
							|  |  |  | 							return error; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 						ptr = cur->bc_ptrs[level]; | 
					
						
							|  |  |  | 						xfs_bmbt_disk_set_allf(&nrec, | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 							startoff, 0, 0, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 							XFS_EXT_NORM); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						XFS_BMBT_TRACE_CURSOR(cur, | 
					
						
							|  |  |  | 							EXIT); | 
					
						
							|  |  |  | 						*stat = 0; | 
					
						
							|  |  |  | 						return 0; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	numrecs = be16_to_cpu(block->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (level > 0) { | 
					
						
							|  |  |  | 		kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 		pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		for (i = numrecs; i >= ptr; i--) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1], | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 					level))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		memmove(&kp[ptr], &kp[ptr - 1], | 
					
						
							|  |  |  | 			(numrecs - ptr + 1) * sizeof(*kp)); | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:11 +10:00
										 |  |  | 		memmove(&pp[ptr], &pp[ptr - 1], | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			(numrecs - ptr + 1) * sizeof(*pp)); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 		if ((error = xfs_btree_check_lptr(cur, *bnop, level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		kp[ptr - 1] = key; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 		pp[ptr - 1] = cpu_to_be64(*bnop); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		numrecs++; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		block->bb_numrecs = cpu_to_be16(numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		xfs_bmbt_log_keys(cur, bp, ptr, numrecs); | 
					
						
							|  |  |  | 		xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		rp = XFS_BMAP_REC_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 		memmove(&rp[ptr], &rp[ptr - 1], | 
					
						
							|  |  |  | 			(numrecs - ptr + 1) * sizeof(*rp)); | 
					
						
							|  |  |  | 		rp[ptr - 1] = *recp; | 
					
						
							|  |  |  | 		numrecs++; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		block->bb_numrecs = cpu_to_be16(numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		xfs_bmbt_log_recs(cur, bp, ptr, numrecs); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if (ptr < numrecs) { | 
					
						
							|  |  |  | 		if (level == 0) | 
					
						
							|  |  |  | 			xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, | 
					
						
							|  |  |  | 				rp + ptr); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, | 
					
						
							|  |  |  | 				kp + ptr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*bnop = nbno; | 
					
						
							|  |  |  | 	if (nbno != NULLFSBLOCK) { | 
					
						
							|  |  |  | 		*recp = nrec; | 
					
						
							|  |  |  | 		*curp = ncur; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | STATIC int | 
					
						
							|  |  |  | xfs_bmbt_killroot( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*cblock; | 
					
						
							|  |  |  | 	xfs_buf_t		*cbp; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*ckp; | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*cpp; | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	int			error; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	int			i; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kp; | 
					
						
							|  |  |  | 	xfs_inode_t		*ip; | 
					
						
							|  |  |  | 	xfs_ifork_t		*ifp; | 
					
						
							|  |  |  | 	int			level; | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*pp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	level = cur->bc_nlevels - 1; | 
					
						
							|  |  |  | 	ASSERT(level >= 1); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Don't deal with the root block needs to be a leaf case. | 
					
						
							|  |  |  | 	 * We're just going to turn the thing back into extents anyway. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (level == 1) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, level, &cbp); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Give up if the root has multiple children. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be16_to_cpu(block->bb_numrecs) != 1) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Only do this if the next level will fit. | 
					
						
							|  |  |  | 	 * Then the data must be copied up to the inode, | 
					
						
							|  |  |  | 	 * instead of freeing the root you free the next level. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	cbp = cur->bc_bufs[level - 1]; | 
					
						
							|  |  |  | 	cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO); | 
					
						
							|  |  |  | 	ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	ip = cur->bc_private.b.ip; | 
					
						
							|  |  |  | 	ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 	ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == | 
					
						
							|  |  |  | 	       XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (i) { | 
					
						
							|  |  |  | 		xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 		block = ifp->if_broot; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&block->bb_numrecs, i); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	ASSERT(block->bb_numrecs == cblock->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 		if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, | 
					
						
							|  |  |  | 			cur->bc_private.b.flist, cur->bc_mp); | 
					
						
							|  |  |  | 	ip->i_d.di_nblocks--; | 
					
						
							|  |  |  | 	XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, | 
					
						
							|  |  |  | 			XFS_TRANS_DQ_BCOUNT, -1L); | 
					
						
							|  |  |  | 	xfs_trans_binval(cur->bc_tp, cbp); | 
					
						
							|  |  |  | 	cur->bc_bufs[level - 1] = NULL; | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&block->bb_level, -1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_trans_log_inode(cur->bc_tp, ip, | 
					
						
							|  |  |  | 		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 
					
						
							|  |  |  | 	cur->bc_nlevels--; | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Log key values from the btree block. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_log_keys( | 
					
						
							|  |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	xfs_buf_t	*bp, | 
					
						
							|  |  |  | 	int		kfirst, | 
					
						
							|  |  |  | 	int		klast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_trans_t	*tp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	if (bp) { | 
					
						
							|  |  |  | 		xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 		int			first; | 
					
						
							|  |  |  | 		xfs_bmbt_key_t		*kp; | 
					
						
							|  |  |  | 		int			last; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 		kp = XFS_BMAP_KEY_DADDR(block, 1, cur); | 
					
						
							|  |  |  | 		first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); | 
					
						
							|  |  |  | 		last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); | 
					
						
							|  |  |  | 		xfs_trans_log_buf(tp, bp, first, last); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		xfs_inode_t		 *ip; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ip = cur->bc_private.b.ip; | 
					
						
							|  |  |  | 		xfs_trans_log_inode(tp, ip, | 
					
						
							|  |  |  | 			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Log pointer values from the btree block. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC void | 
					
						
							|  |  |  | xfs_bmbt_log_ptrs( | 
					
						
							|  |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	xfs_buf_t	*bp, | 
					
						
							|  |  |  | 	int		pfirst, | 
					
						
							|  |  |  | 	int		plast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_trans_t	*tp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	if (bp) { | 
					
						
							|  |  |  | 		xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 		int			first; | 
					
						
							|  |  |  | 		int			last; | 
					
						
							|  |  |  | 		xfs_bmbt_ptr_t		*pp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 		pp = XFS_BMAP_PTR_DADDR(block, 1, cur); | 
					
						
							|  |  |  | 		first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); | 
					
						
							|  |  |  | 		last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); | 
					
						
							|  |  |  | 		xfs_trans_log_buf(tp, bp, first, last); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		xfs_inode_t		*ip; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ip = cur->bc_private.b.ip; | 
					
						
							|  |  |  | 		xfs_trans_log_inode(tp, ip, | 
					
						
							|  |  |  | 			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Lookup the record.  The cursor is made to point to it, based on dir. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC int				/* error */ | 
					
						
							|  |  |  | xfs_bmbt_lookup( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	xfs_lookup_t		dir, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block=NULL; | 
					
						
							|  |  |  | 	xfs_buf_t		*bp; | 
					
						
							|  |  |  | 	xfs_daddr_t		d; | 
					
						
							|  |  |  | 	xfs_sfiloff_t		diff; | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		fsbno=0; | 
					
						
							|  |  |  | 	int			high; | 
					
						
							|  |  |  | 	int			i; | 
					
						
							|  |  |  | 	int			keyno=0; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kkbase=NULL; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kkp; | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*krbase=NULL; | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*krp; | 
					
						
							|  |  |  | 	int			level; | 
					
						
							|  |  |  | 	int			low; | 
					
						
							|  |  |  | 	xfs_mount_t		*mp; | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*pp; | 
					
						
							|  |  |  | 	xfs_bmbt_irec_t		*rp; | 
					
						
							|  |  |  | 	xfs_fileoff_t		startoff; | 
					
						
							|  |  |  | 	xfs_trans_t		*tp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_STATS_INC(xs_bmbt_lookup); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGI(cur, (int)dir); | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	mp = cur->bc_mp; | 
					
						
							|  |  |  | 	rp = &cur->bc_rec.b; | 
					
						
							|  |  |  | 	for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { | 
					
						
							|  |  |  | 		if (level < cur->bc_nlevels - 1) { | 
					
						
							|  |  |  | 			d = XFS_FSB_TO_DADDR(mp, fsbno); | 
					
						
							|  |  |  | 			bp = cur->bc_bufs[level]; | 
					
						
							|  |  |  | 			if (bp && XFS_BUF_ADDR(bp) != d) | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:40 +10:00
										 |  |  | 				bp = NULL; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			if (!bp) { | 
					
						
							|  |  |  | 				if ((error = xfs_btree_read_bufl(mp, tp, fsbno, | 
					
						
							|  |  |  | 						0, &bp, XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 					XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 					return error; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				xfs_btree_setbuf(cur, level, bp); | 
					
						
							|  |  |  | 				block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 				if ((error = xfs_btree_check_lblock(cur, block, | 
					
						
							|  |  |  | 						level, bp))) { | 
					
						
							|  |  |  | 					XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 					return error; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else | 
					
						
							|  |  |  | 				block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | 		if (diff == 0) | 
					
						
							|  |  |  | 			keyno = 1; | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			if (level > 0) | 
					
						
							|  |  |  | 				kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				krbase = XFS_BMAP_REC_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 			low = 1; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 			if (!(high = be16_to_cpu(block->bb_numrecs))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				ASSERT(level == 0); | 
					
						
							|  |  |  | 				cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 				*stat = 0; | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			while (low <= high) { | 
					
						
							|  |  |  | 				XFS_STATS_INC(xs_bmbt_compare); | 
					
						
							|  |  |  | 				keyno = (low + high) >> 1; | 
					
						
							|  |  |  | 				if (level > 0) { | 
					
						
							|  |  |  | 					kkp = kkbase + keyno - 1; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 					startoff = be64_to_cpu(kkp->br_startoff); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				} else { | 
					
						
							|  |  |  | 					krp = krbase + keyno - 1; | 
					
						
							|  |  |  | 					startoff = xfs_bmbt_disk_get_startoff(krp); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				diff = (xfs_sfiloff_t) | 
					
						
							|  |  |  | 						(startoff - rp->br_startoff); | 
					
						
							|  |  |  | 				if (diff < 0) | 
					
						
							|  |  |  | 					low = keyno + 1; | 
					
						
							|  |  |  | 				else if (diff > 0) | 
					
						
							|  |  |  | 					high = keyno - 1; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (level > 0) { | 
					
						
							|  |  |  | 			if (diff > 0 && --keyno < 1) | 
					
						
							|  |  |  | 				keyno = 1; | 
					
						
							|  |  |  | 			pp = XFS_BMAP_PTR_IADDR(block, keyno, cur); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 			fsbno = be64_to_cpu(*pp); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr(cur, fsbno, level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			cur->bc_ptrs[level] = keyno; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (dir != XFS_LOOKUP_LE && diff < 0) { | 
					
						
							|  |  |  | 		keyno++; | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * If ge search and we went off the end of the block, but it's | 
					
						
							|  |  |  | 		 * not the last block, we're in the wrong block. | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) && | 
					
						
							|  |  |  | 		    be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			cur->bc_ptrs[0] = keyno; | 
					
						
							|  |  |  | 			if ((error = xfs_bmbt_increment(cur, 0, &i))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			XFS_WANT_CORRUPTED_RETURN(i == 1); | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 			*stat = 1; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (dir == XFS_LOOKUP_LE && diff > 0) | 
					
						
							|  |  |  | 		keyno--; | 
					
						
							|  |  |  | 	cur->bc_ptrs[0] = keyno; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Move 1 record left from cur/level if possible. | 
					
						
							|  |  |  |  * Update cur to reflect the new path. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC int					/* error */ | 
					
						
							|  |  |  | xfs_bmbt_lshift( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	int			i;		/* loop counter */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		key;		/* bmap btree key */ | 
					
						
							|  |  |  | 	xfs_buf_t		*lbp;		/* left buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*left;		/* left btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*lkp=NULL;	/* left btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */ | 
					
						
							|  |  |  | 	int			lrecs;		/* left record count */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*lrp=NULL;	/* left record pointer */ | 
					
						
							|  |  |  | 	xfs_mount_t		*mp;		/* file system mount point */ | 
					
						
							|  |  |  | 	xfs_buf_t		*rbp;		/* right buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*right;		/* right btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*rkp=NULL;	/* right btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*rpp=NULL;	/* right address pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */ | 
					
						
							|  |  |  | 	int			rrecs;		/* right record count */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGI(cur, level); | 
					
						
							|  |  |  | 	if (level == cur->bc_nlevels - 1) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	rbp = cur->bc_bufs[level]; | 
					
						
							|  |  |  | 	right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (cur->bc_ptrs[level] <= 1) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mp = cur->bc_mp; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			&lbp, XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	lrecs = be16_to_cpu(left->bb_numrecs) + 1; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (level > 0) { | 
					
						
							|  |  |  | 		lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); | 
					
						
							|  |  |  | 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | 
					
						
							|  |  |  | 		*lkp = *rkp; | 
					
						
							|  |  |  | 		xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); | 
					
						
							|  |  |  | 		lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); | 
					
						
							|  |  |  | 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 		if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:11 +10:00
										 |  |  | 		*lpp = *rpp; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); | 
					
						
							|  |  |  | 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | 
					
						
							|  |  |  | 		*lrp = *rrp; | 
					
						
							|  |  |  | 		xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	left->bb_numrecs = cpu_to_be16(lrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if (level > 0) | 
					
						
							|  |  |  | 		xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	rrecs = be16_to_cpu(right->bb_numrecs) - 1; | 
					
						
							|  |  |  | 	right->bb_numrecs = cpu_to_be16(rrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | 
					
						
							|  |  |  | 	if (level > 0) { | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		for (i = 0; i < rrecs; i++) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1], | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 					level))) { | 
					
						
							|  |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); | 
					
						
							|  |  |  | 		memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_keys(cur, rbp, 1, rrecs); | 
					
						
							|  |  |  | 		xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_recs(cur, rbp, 1, rrecs); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 		key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		rkp = &key; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cur->bc_ptrs[level]--; | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Move 1 record right from cur/level if possible. | 
					
						
							|  |  |  |  * Update cur to reflect the new path. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC int					/* error */ | 
					
						
							|  |  |  | xfs_bmbt_rshift( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	int			i;		/* loop counter */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		key;		/* bmap btree key */ | 
					
						
							|  |  |  | 	xfs_buf_t		*lbp;		/* left buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*left;		/* left btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*lkp;		/* left btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*lrp;		/* left record pointer */ | 
					
						
							|  |  |  | 	xfs_mount_t		*mp;		/* file system mount point */ | 
					
						
							|  |  |  | 	xfs_buf_t		*rbp;		/* right buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*right;		/* right btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*rkp;		/* right btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */ | 
					
						
							|  |  |  | 	struct xfs_btree_cur	*tcur;		/* temporary btree cursor */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGI(cur, level); | 
					
						
							|  |  |  | 	if (level == cur->bc_nlevels - 1) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	lbp = cur->bc_bufs[level]; | 
					
						
							|  |  |  | 	left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mp = cur->bc_mp; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			&rbp, XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (level > 0) { | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | 
					
						
							|  |  |  | 		lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | 
					
						
							|  |  |  | 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | 
					
						
							|  |  |  | 		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 		if ((error = xfs_btree_check_lptr_disk(cur, *lpp, level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		*rkp = *lkp; | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:11 +10:00
										 |  |  | 		*rpp = *lpp; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | 
					
						
							|  |  |  | 		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		*rrp = *lrp; | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 		key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		rkp = &key; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&left->bb_numrecs, -1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&right->bb_numrecs, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if (level > 0) | 
					
						
							|  |  |  | 		xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | 
					
						
							|  |  |  | 	if ((error = xfs_btree_dup_cursor(cur, &tcur))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	i = xfs_btree_lastrec(tcur, level); | 
					
						
							|  |  |  | 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 	if ((error = xfs_bmbt_increment(tcur, level, &i))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(tcur, ERROR); | 
					
						
							|  |  |  | 		goto error1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 	if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(tcur, ERROR); | 
					
						
							|  |  |  | 		goto error1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | error0: | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | error1: | 
					
						
							|  |  |  | 	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | 
					
						
							|  |  |  | 	return error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Determine the extent state. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* ARGSUSED */ | 
					
						
							|  |  |  | STATIC xfs_exntst_t | 
					
						
							|  |  |  | xfs_extent_state( | 
					
						
							|  |  |  | 	xfs_filblks_t		blks, | 
					
						
							|  |  |  | 	int			extent_flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (extent_flag) { | 
					
						
							|  |  |  | 		ASSERT(blks != 0);	/* saved for DMIG */ | 
					
						
							|  |  |  | 		return XFS_EXT_UNWRITTEN; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return XFS_EXT_NORM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Split cur/level block in half. | 
					
						
							|  |  |  |  * Return new block number and its first record (to be inserted into parent). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC int					/* error */ | 
					
						
							|  |  |  | xfs_bmbt_split( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	xfs_fsblock_t		*bnop, | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	__uint64_t		*startoff, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_btree_cur_t		**curp, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_alloc_arg_t		args;		/* block allocation args */ | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	int			i;		/* loop counter */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		lbno;		/* left sibling block number */ | 
					
						
							|  |  |  | 	xfs_buf_t		*lbp;		/* left buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*left;		/* left btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*lkp;		/* left btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*lrp;		/* left record pointer */ | 
					
						
							|  |  |  | 	xfs_buf_t		*rbp;		/* right buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*right;		/* right btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*rkp;		/* right btree key */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */ | 
					
						
							|  |  |  | 	xfs_buf_t		*rrbp;		/* right-right buffer pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rrp;		/* right record pointer */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	args.tp = cur->bc_tp; | 
					
						
							|  |  |  | 	args.mp = cur->bc_mp; | 
					
						
							|  |  |  | 	lbp = cur->bc_bufs[level]; | 
					
						
							|  |  |  | 	lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); | 
					
						
							|  |  |  | 	left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 
					
						
							|  |  |  | 	args.fsbno = cur->bc_private.b.firstblock; | 
					
						
							| 
									
										
										
										
											2006-06-09 14:55:18 +10:00
										 |  |  | 	args.firstblock = args.fsbno; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (args.fsbno == NULLFSBLOCK) { | 
					
						
							|  |  |  | 		args.fsbno = lbno; | 
					
						
							|  |  |  | 		args.type = XFS_ALLOCTYPE_START_BNO; | 
					
						
							| 
									
										
										
										
											2006-06-09 14:55:18 +10:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		args.type = XFS_ALLOCTYPE_NEAR_BNO; | 
					
						
							|  |  |  | 	args.mod = args.minleft = args.alignment = args.total = args.isfl = | 
					
						
							|  |  |  | 		args.userdata = args.minalignslop = 0; | 
					
						
							|  |  |  | 	args.minlen = args.maxlen = args.prod = 1; | 
					
						
							|  |  |  | 	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | 
					
						
							|  |  |  | 	if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return XFS_ERROR(ENOSPC); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((error = xfs_alloc_vextent(&args))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (args.fsbno == NULLFSBLOCK) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASSERT(args.len == 1); | 
					
						
							|  |  |  | 	cur->bc_private.b.firstblock = args.fsbno; | 
					
						
							|  |  |  | 	cur->bc_private.b.allocated++; | 
					
						
							|  |  |  | 	cur->bc_private.b.ip->i_d.di_nblocks++; | 
					
						
							|  |  |  | 	xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | 
					
						
							|  |  |  | 	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | 
					
						
							|  |  |  | 			XFS_TRANS_DQ_BCOUNT, 1L); | 
					
						
							|  |  |  | 	rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); | 
					
						
							|  |  |  | 	right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); | 
					
						
							|  |  |  | 	right->bb_level = left->bb_level; | 
					
						
							|  |  |  | 	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); | 
					
						
							|  |  |  | 	if ((be16_to_cpu(left->bb_numrecs) & 1) && | 
					
						
							|  |  |  | 	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 		be16_add_cpu(&right->bb_numrecs, 1); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (level > 0) { | 
					
						
							|  |  |  | 		lkp = XFS_BMAP_KEY_IADDR(left, i, cur); | 
					
						
							|  |  |  | 		lpp = XFS_BMAP_PTR_IADDR(left, i, cur); | 
					
						
							|  |  |  | 		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | 
					
						
							|  |  |  | 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 			if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 				return error; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | 
					
						
							|  |  |  | 		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 		*startoff = be64_to_cpu(rkp->br_startoff); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		lrp = XFS_BMAP_REC_IADDR(left, i, cur); | 
					
						
							|  |  |  | 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | 
					
						
							|  |  |  | 		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 		*startoff = xfs_bmbt_disk_get_startoff(rrp); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	right->bb_rightsib = left->bb_rightsib; | 
					
						
							|  |  |  | 	left->bb_rightsib = cpu_to_be64(args.fsbno); | 
					
						
							|  |  |  | 	right->bb_leftsib = cpu_to_be64(lbno); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); | 
					
						
							|  |  |  | 	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if ((error = xfs_btree_read_bufl(args.mp, args.tp, | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 				be64_to_cpu(right->bb_rightsib), 0, &rrbp, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		rrblock->bb_leftsib = cpu_to_be64(args.fsbno); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		xfs_btree_setbuf(cur, level, rbp); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (level + 1 < cur->bc_nlevels) { | 
					
						
							|  |  |  | 		if ((error = xfs_btree_dup_cursor(cur, curp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		(*curp)->bc_ptrs[level + 1]++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*bnop = args.fsbno; | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Update keys for the record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | STATIC int | 
					
						
							|  |  |  | xfs_bmbt_updkey( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*keyp,	/* on-disk format */ | 
					
						
							|  |  |  | 	int			level) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 	xfs_buf_t		*bp; | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	int			error; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kp; | 
					
						
							|  |  |  | 	int			ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASSERT(level >= 1); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGIK(cur, level, keyp); | 
					
						
							|  |  |  | 	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { | 
					
						
							|  |  |  | 		block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		ptr = cur->bc_ptrs[level]; | 
					
						
							|  |  |  | 		kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); | 
					
						
							|  |  |  | 		*kp = *keyp; | 
					
						
							|  |  |  | 		xfs_bmbt_log_keys(cur, bp, ptr, ptr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Convert on-disk form of btree root to in-memory form. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmdr_to_bmbt( | 
					
						
							|  |  |  | 	xfs_bmdr_block_t	*dblock, | 
					
						
							|  |  |  | 	int			dblocklen, | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*rblock, | 
					
						
							|  |  |  | 	int			rblocklen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int			dmxr; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*fkp; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	__be64			*fpp; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_key_t		*tkp; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	__be64			*tpp; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); | 
					
						
							|  |  |  | 	rblock->bb_level = dblock->bb_level; | 
					
						
							|  |  |  | 	ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 
					
						
							|  |  |  | 	rblock->bb_numrecs = dblock->bb_numrecs; | 
					
						
							|  |  |  | 	rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); | 
					
						
							|  |  |  | 	rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 
					
						
							| 
									
										
										
										
											2007-02-10 18:37:33 +11:00
										 |  |  | 	fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 
					
						
							| 
									
										
										
										
											2007-02-10 18:37:33 +11:00
										 |  |  | 	fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	dmxr = be16_to_cpu(dblock->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Decrement cursor by one record at the level. | 
					
						
							|  |  |  |  * For nonzero levels the leaf-ward information is untouched. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int						/* error */ | 
					
						
							|  |  |  | xfs_bmbt_decrement( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 	xfs_buf_t		*bp; | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		fsbno; | 
					
						
							|  |  |  | 	int			lev; | 
					
						
							|  |  |  | 	xfs_mount_t		*mp; | 
					
						
							|  |  |  | 	xfs_trans_t		*tp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGI(cur, level); | 
					
						
							|  |  |  | 	ASSERT(level < cur->bc_nlevels); | 
					
						
							|  |  |  | 	if (level < cur->bc_nlevels - 1) | 
					
						
							|  |  |  | 		xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); | 
					
						
							|  |  |  | 	if (--cur->bc_ptrs[level] > 0) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (lev = level + 1; lev < cur->bc_nlevels; lev++) { | 
					
						
							|  |  |  | 		if (--cur->bc_ptrs[lev] > 0) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		if (lev < cur->bc_nlevels - 1) | 
					
						
							|  |  |  | 			xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lev == cur->bc_nlevels) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	mp = cur->bc_mp; | 
					
						
							|  |  |  | 	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 		fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, | 
					
						
							|  |  |  | 				XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		lev--; | 
					
						
							|  |  |  | 		xfs_btree_setbuf(cur, lev, bp); | 
					
						
							|  |  |  | 		block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Delete the record pointed to by cur. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int					/* error */ | 
					
						
							|  |  |  | xfs_bmbt_delete( | 
					
						
							|  |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	int		*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int		error;		/* error return value */ | 
					
						
							|  |  |  | 	int		i; | 
					
						
							|  |  |  | 	int		level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	for (level = 0, i = 2; i == 2; level++) { | 
					
						
							|  |  |  | 		if ((error = xfs_bmbt_delrec(cur, level, &i))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (i == 0) { | 
					
						
							|  |  |  | 		for (level = 1; level < cur->bc_nlevels; level++) { | 
					
						
							|  |  |  | 			if (cur->bc_ptrs[level] == 0) { | 
					
						
							|  |  |  | 				if ((error = xfs_bmbt_decrement(cur, level, | 
					
						
							|  |  |  | 						&i))) { | 
					
						
							|  |  |  | 					XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 					return error; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = i; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Convert a compressed bmap extent record to an uncompressed form. | 
					
						
							|  |  |  |  * This code must be in sync with the routines xfs_bmbt_get_startoff, | 
					
						
							|  |  |  |  * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-10 18:34:56 +11:00
										 |  |  | STATIC_INLINE void | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | __xfs_bmbt_get_all( | 
					
						
							|  |  |  | 		__uint64_t l0, | 
					
						
							|  |  |  | 		__uint64_t l1, | 
					
						
							|  |  |  | 		xfs_bmbt_irec_t *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int	ext_flag; | 
					
						
							|  |  |  | 	xfs_exntst_t st; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN)); | 
					
						
							|  |  |  | 	s->br_startoff = ((xfs_fileoff_t)l0 & | 
					
						
							|  |  |  | 			   XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 
					
						
							|  |  |  | #if XFS_BIG_BLKNOS
 | 
					
						
							|  |  |  | 	s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) | | 
					
						
							|  |  |  | 			   (((xfs_fsblock_t)l1) >> 21); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		xfs_dfsbno_t	b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) | | 
					
						
							|  |  |  | 		    (((xfs_dfsbno_t)l1) >> 21); | 
					
						
							|  |  |  | 		ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); | 
					
						
							|  |  |  | 		s->br_startblock = (xfs_fsblock_t)b; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else	/* !DEBUG */
 | 
					
						
							|  |  |  | 	s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21); | 
					
						
							|  |  |  | #endif	/* DEBUG */
 | 
					
						
							|  |  |  | #endif	/* XFS_BIG_BLKNOS */
 | 
					
						
							|  |  |  | 	s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21)); | 
					
						
							|  |  |  | 	/* This is xfs_extent_state() in-line */ | 
					
						
							|  |  |  | 	if (ext_flag) { | 
					
						
							|  |  |  | 		ASSERT(s->br_blockcount != 0);	/* saved for DMIG */ | 
					
						
							|  |  |  | 		st = XFS_EXT_UNWRITTEN; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		st = XFS_EXT_NORM; | 
					
						
							|  |  |  | 	s->br_state = st; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_get_all( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t *r, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_irec_t *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	__xfs_bmbt_get_all(r->l0, r->l1, s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Get the block pointer for the given level of the cursor. | 
					
						
							|  |  |  |  * Fill in the buffer pointer, if applicable. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | xfs_bmbt_block_t * | 
					
						
							|  |  |  | xfs_bmbt_get_block( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	xfs_buf_t		**bpp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_ifork_t		*ifp; | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*rval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (level < cur->bc_nlevels - 1) { | 
					
						
							|  |  |  | 		*bpp = cur->bc_bufs[level]; | 
					
						
							|  |  |  | 		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		*bpp = NULL; | 
					
						
							|  |  |  | 		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, | 
					
						
							|  |  |  | 			cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 		rval = ifp->if_broot; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Extract the blockcount field from an in memory bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | xfs_filblks_t | 
					
						
							|  |  |  | xfs_bmbt_get_blockcount( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t	*r) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Extract the startblock field from an in memory bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | xfs_fsblock_t | 
					
						
							|  |  |  | xfs_bmbt_get_startblock( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t	*r) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | #if XFS_BIG_BLKNOS
 | 
					
						
							|  |  |  | 	return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) | | 
					
						
							|  |  |  | 	       (((xfs_fsblock_t)r->l1) >> 21); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	xfs_dfsbno_t	b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) | | 
					
						
							|  |  |  | 	    (((xfs_dfsbno_t)r->l1) >> 21); | 
					
						
							|  |  |  | 	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); | 
					
						
							|  |  |  | 	return (xfs_fsblock_t)b; | 
					
						
							|  |  |  | #else	/* !DEBUG */
 | 
					
						
							|  |  |  | 	return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21); | 
					
						
							|  |  |  | #endif	/* DEBUG */
 | 
					
						
							|  |  |  | #endif	/* XFS_BIG_BLKNOS */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Extract the startoff field from an in memory bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | xfs_fileoff_t | 
					
						
							|  |  |  | xfs_bmbt_get_startoff( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t	*r) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	return ((xfs_fileoff_t)r->l0 & | 
					
						
							|  |  |  | 		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xfs_exntst_t | 
					
						
							|  |  |  | xfs_bmbt_get_state( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t	*r) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int	ext_flag; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN)); | 
					
						
							|  |  |  | 	return xfs_extent_state(xfs_bmbt_get_blockcount(r), | 
					
						
							|  |  |  | 				ext_flag); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Endian flipping versions of the bmbt extraction functions */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_disk_get_all( | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t	*r, | 
					
						
							|  |  |  | 	xfs_bmbt_irec_t *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 	__xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Extract the blockcount field from an on disk bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | xfs_filblks_t | 
					
						
							|  |  |  | xfs_bmbt_disk_get_blockcount( | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t	*r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 	return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Extract the startoff field from a disk format bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | xfs_fileoff_t | 
					
						
							|  |  |  | xfs_bmbt_disk_get_startoff( | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t	*r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 	return ((xfs_fileoff_t)be64_to_cpu(r->l0) & | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Increment cursor by one record at the level. | 
					
						
							|  |  |  |  * For nonzero levels the leaf-ward information is untouched. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int						/* error */ | 
					
						
							|  |  |  | xfs_bmbt_increment( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	int			level, | 
					
						
							|  |  |  | 	int			*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 	xfs_buf_t		*bp; | 
					
						
							|  |  |  | 	int			error;		/* error return value */ | 
					
						
							|  |  |  | 	xfs_fsblock_t		fsbno; | 
					
						
							|  |  |  | 	int			lev; | 
					
						
							|  |  |  | 	xfs_mount_t		*mp; | 
					
						
							|  |  |  | 	xfs_trans_t		*tp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGI(cur, level); | 
					
						
							|  |  |  | 	ASSERT(level < cur->bc_nlevels); | 
					
						
							|  |  |  | 	if (level < cur->bc_nlevels - 1) | 
					
						
							|  |  |  | 		xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (lev = level + 1; lev < cur->bc_nlevels; lev++) { | 
					
						
							|  |  |  | 		block = xfs_bmbt_get_block(cur, lev, &bp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		if (lev < cur->bc_nlevels - 1) | 
					
						
							|  |  |  | 			xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lev == cur->bc_nlevels) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	mp = cur->bc_mp; | 
					
						
							|  |  |  | 	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 		fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, | 
					
						
							|  |  |  | 				XFS_BMAP_BTREE_REF))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		lev--; | 
					
						
							|  |  |  | 		xfs_btree_setbuf(cur, lev, bp); | 
					
						
							|  |  |  | 		block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cur->bc_ptrs[lev] = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Insert the current record at the point referenced by cur. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int					/* error */ | 
					
						
							|  |  |  | xfs_bmbt_insert( | 
					
						
							|  |  |  | 	xfs_btree_cur_t	*cur, | 
					
						
							|  |  |  | 	int		*stat)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int		error;		/* error return value */ | 
					
						
							|  |  |  | 	int		i; | 
					
						
							|  |  |  | 	int		level; | 
					
						
							|  |  |  | 	xfs_fsblock_t	nbno; | 
					
						
							|  |  |  | 	xfs_btree_cur_t	*ncur; | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t	nrec; | 
					
						
							|  |  |  | 	xfs_btree_cur_t	*pcur; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	level = 0; | 
					
						
							|  |  |  | 	nbno = NULLFSBLOCK; | 
					
						
							|  |  |  | 	xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:40 +10:00
										 |  |  | 	ncur = NULL; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pcur = cur; | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, | 
					
						
							|  |  |  | 				&i))) { | 
					
						
							|  |  |  | 			if (pcur != cur) | 
					
						
							|  |  |  | 				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | 
					
						
							|  |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 
					
						
							|  |  |  | 		if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { | 
					
						
							|  |  |  | 			cur->bc_nlevels = pcur->bc_nlevels; | 
					
						
							|  |  |  | 			cur->bc_private.b.allocated += | 
					
						
							|  |  |  | 				pcur->bc_private.b.allocated; | 
					
						
							|  |  |  | 			pcur->bc_private.b.allocated = 0; | 
					
						
							|  |  |  | 			ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || | 
					
						
							| 
									
										
										
										
											2007-11-23 16:29:42 +11:00
										 |  |  | 			       XFS_IS_REALTIME_INODE(cur->bc_private.b.ip)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			cur->bc_private.b.firstblock = | 
					
						
							|  |  |  | 				pcur->bc_private.b.firstblock; | 
					
						
							|  |  |  | 			ASSERT(cur->bc_private.b.flist == | 
					
						
							|  |  |  | 			       pcur->bc_private.b.flist); | 
					
						
							|  |  |  | 			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (ncur) { | 
					
						
							|  |  |  | 			pcur = ncur; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:40 +10:00
										 |  |  | 			ncur = NULL; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} while (nbno != NULLFSBLOCK); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*stat = i; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | error0: | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 	return error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Log fields from the btree block header. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_log_block( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	xfs_buf_t		*bp, | 
					
						
							|  |  |  | 	int			fields) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int			first; | 
					
						
							|  |  |  | 	int			last; | 
					
						
							|  |  |  | 	xfs_trans_t		*tp; | 
					
						
							|  |  |  | 	static const short	offsets[] = { | 
					
						
							|  |  |  | 		offsetof(xfs_bmbt_block_t, bb_magic), | 
					
						
							|  |  |  | 		offsetof(xfs_bmbt_block_t, bb_level), | 
					
						
							|  |  |  | 		offsetof(xfs_bmbt_block_t, bb_numrecs), | 
					
						
							|  |  |  | 		offsetof(xfs_bmbt_block_t, bb_leftsib), | 
					
						
							|  |  |  | 		offsetof(xfs_bmbt_block_t, bb_rightsib), | 
					
						
							|  |  |  | 		sizeof(xfs_bmbt_block_t) | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGBI(cur, bp, fields); | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	if (bp) { | 
					
						
							|  |  |  | 		xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, | 
					
						
							|  |  |  | 				  &last); | 
					
						
							|  |  |  | 		xfs_trans_log_buf(tp, bp, first, last); | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		xfs_trans_log_inode(tp, cur->bc_private.b.ip, | 
					
						
							|  |  |  | 			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Log record values from the btree block. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_log_recs( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur, | 
					
						
							|  |  |  | 	xfs_buf_t		*bp, | 
					
						
							|  |  |  | 	int			rfirst, | 
					
						
							|  |  |  | 	int			rlast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 	int			first; | 
					
						
							|  |  |  | 	int			last; | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rp; | 
					
						
							|  |  |  | 	xfs_trans_t		*tp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast); | 
					
						
							|  |  |  | 	ASSERT(bp); | 
					
						
							|  |  |  | 	tp = cur->bc_tp; | 
					
						
							|  |  |  | 	block = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 	rp = XFS_BMAP_REC_DADDR(block, 1, cur); | 
					
						
							|  |  |  | 	first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); | 
					
						
							|  |  |  | 	last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); | 
					
						
							|  |  |  | 	xfs_trans_log_buf(tp, bp, first, last); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	cur->bc_rec.b.br_startoff = off; | 
					
						
							|  |  |  | 	cur->bc_rec.b.br_startblock = bno; | 
					
						
							|  |  |  | 	cur->bc_rec.b.br_blockcount = len; | 
					
						
							|  |  |  | 	return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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)		/* success/failure */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	cur->bc_rec.b.br_startoff = off; | 
					
						
							|  |  |  | 	cur->bc_rec.b.br_startblock = bno; | 
					
						
							|  |  |  | 	cur->bc_rec.b.br_blockcount = len; | 
					
						
							|  |  |  | 	return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Give the bmap btree a new root block.  Copy the old broot contents | 
					
						
							|  |  |  |  * down into a real block and make the broot point to it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int						/* error */ | 
					
						
							|  |  |  | xfs_bmbt_newroot( | 
					
						
							|  |  |  | 	xfs_btree_cur_t		*cur,		/* btree cursor */ | 
					
						
							|  |  |  | 	int			*logflags,	/* logging flags for inode */ | 
					
						
							|  |  |  | 	int			*stat)		/* return status - 0 fail */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_alloc_arg_t		args;		/* allocation arguments */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block;		/* bmap btree block */ | 
					
						
							|  |  |  | 	xfs_buf_t		*bp;		/* buffer for block */ | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*cblock;	/* child btree block */ | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*ckp;		/* child key pointer */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*cpp;		/* child ptr pointer */ | 
					
						
							|  |  |  | 	int			error;		/* error return code */ | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	int			i;		/* loop counter */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*kp;		/* pointer to bmap btree key */ | 
					
						
							|  |  |  | 	int			level;		/* btree level */ | 
					
						
							|  |  |  | 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	level = cur->bc_nlevels - 1; | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, level, &bp); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Copy the root into a real block. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	args.mp = cur->bc_mp; | 
					
						
							|  |  |  | 	pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 	args.tp = cur->bc_tp; | 
					
						
							|  |  |  | 	args.fsbno = cur->bc_private.b.firstblock; | 
					
						
							|  |  |  | 	args.mod = args.minleft = args.alignment = args.total = args.isfl = | 
					
						
							|  |  |  | 		args.userdata = args.minalignslop = 0; | 
					
						
							|  |  |  | 	args.minlen = args.maxlen = args.prod = 1; | 
					
						
							|  |  |  | 	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | 
					
						
							| 
									
										
										
										
											2006-06-09 14:55:18 +10:00
										 |  |  | 	args.firstblock = args.fsbno; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (args.fsbno == NULLFSBLOCK) { | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 		if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 		args.fsbno = be64_to_cpu(*pp); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		args.type = XFS_ALLOCTYPE_START_BNO; | 
					
						
							| 
									
										
										
										
											2006-06-09 14:55:18 +10:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		args.type = XFS_ALLOCTYPE_NEAR_BNO; | 
					
						
							|  |  |  | 	if ((error = xfs_alloc_vextent(&args))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (args.fsbno == NULLFSBLOCK) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		*stat = 0; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASSERT(args.len == 1); | 
					
						
							|  |  |  | 	cur->bc_private.b.firstblock = args.fsbno; | 
					
						
							|  |  |  | 	cur->bc_private.b.allocated++; | 
					
						
							|  |  |  | 	cur->bc_private.b.ip->i_d.di_nblocks++; | 
					
						
							|  |  |  | 	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | 
					
						
							|  |  |  | 			  XFS_TRANS_DQ_BCOUNT, 1L); | 
					
						
							|  |  |  | 	bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); | 
					
						
							|  |  |  | 	cblock = XFS_BUF_TO_BMBT_BLOCK(bp); | 
					
						
							|  |  |  | 	*cblock = *block; | 
					
						
							| 
									
										
										
										
											2008-02-13 15:03:29 -08:00
										 |  |  | 	be16_add_cpu(&block->bb_level, 1); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	block->bb_numrecs = cpu_to_be16(1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	cur->bc_nlevels++; | 
					
						
							|  |  |  | 	cur->bc_ptrs[level + 1] = 1; | 
					
						
							|  |  |  | 	kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 
					
						
							|  |  |  | 	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | 
					
						
							| 
									
										
										
										
											2006-09-28 10:57:42 +10:00
										 |  |  | 		if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 			return error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	*pp = cpu_to_be64(args.fsbno); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs), | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 	xfs_btree_setbuf(cur, level, bp); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Do all this logging at the end so that | 
					
						
							|  |  |  | 	 * the root is at the right level. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); | 
					
						
							|  |  |  | 	xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	*logflags |= | 
					
						
							|  |  |  | 		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); | 
					
						
							|  |  |  | 	*stat = 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set all the fields in a bmap extent record from the arguments. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_set_allf( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t	*r, | 
					
						
							|  |  |  | 	xfs_fileoff_t		startoff, | 
					
						
							|  |  |  | 	xfs_fsblock_t		startblock, | 
					
						
							|  |  |  | 	xfs_filblks_t		blockcount, | 
					
						
							|  |  |  | 	xfs_exntst_t		state) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	int		extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); | 
					
						
							|  |  |  | 	ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); | 
					
						
							|  |  |  | 	ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if XFS_BIG_BLKNOS
 | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 		((xfs_bmbt_rec_base_t)startoff << 9) | | 
					
						
							|  |  |  | 		((xfs_bmbt_rec_base_t)startblock >> 43); | 
					
						
							|  |  |  | 	r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | | 
					
						
							|  |  |  | 		((xfs_bmbt_rec_base_t)blockcount & | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 
					
						
							|  |  |  | #else	/* !XFS_BIG_BLKNOS */
 | 
					
						
							| 
									
										
										
										
											2007-08-23 16:20:10 +10:00
										 |  |  | 	if (ISNULLSTARTBLOCK(startblock)) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			((xfs_bmbt_rec_base_t)startoff << 9) | | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); | 
					
						
							|  |  |  | 		r->l1 = XFS_MASK64HI(11) | | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			  ((xfs_bmbt_rec_base_t)startblock << 21) | | 
					
						
							|  |  |  | 			  ((xfs_bmbt_rec_base_t)blockcount & | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			((xfs_bmbt_rec_base_t)startoff << 9); | 
					
						
							|  |  |  | 		r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | | 
					
						
							|  |  |  | 			 ((xfs_bmbt_rec_base_t)blockcount & | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif	/* XFS_BIG_BLKNOS */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set all the fields in a bmap extent record from the uncompressed form. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | xfs_bmbt_set_all( | 
					
						
							|  |  |  | 	xfs_bmbt_rec_host_t *r, | 
					
						
							|  |  |  | 	xfs_bmbt_irec_t	*s) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock, | 
					
						
							|  |  |  | 			     s->br_blockcount, s->br_state); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Set all the fields in a disk format bmap extent record from the arguments. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_disk_set_allf( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	xfs_bmbt_rec_t		*r, | 
					
						
							|  |  |  | 	xfs_fileoff_t		startoff, | 
					
						
							|  |  |  | 	xfs_fsblock_t		startblock, | 
					
						
							|  |  |  | 	xfs_filblks_t		blockcount, | 
					
						
							|  |  |  | 	xfs_exntst_t		state) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	int			extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); | 
					
						
							|  |  |  | 	ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); | 
					
						
							|  |  |  | 	ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if XFS_BIG_BLKNOS
 | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 	ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 	r->l0 = cpu_to_be64( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 		((xfs_bmbt_rec_base_t)extent_flag << 63) | | 
					
						
							|  |  |  | 		 ((xfs_bmbt_rec_base_t)startoff << 9) | | 
					
						
							|  |  |  | 		 ((xfs_bmbt_rec_base_t)startblock >> 43)); | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 	r->l1 = cpu_to_be64( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 		((xfs_bmbt_rec_base_t)startblock << 21) | | 
					
						
							|  |  |  | 		 ((xfs_bmbt_rec_base_t)blockcount & | 
					
						
							|  |  |  | 		  (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #else	/* !XFS_BIG_BLKNOS */
 | 
					
						
							| 
									
										
										
										
											2007-08-23 16:20:10 +10:00
										 |  |  | 	if (ISNULLSTARTBLOCK(startblock)) { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 		r->l0 = cpu_to_be64( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			((xfs_bmbt_rec_base_t)extent_flag << 63) | | 
					
						
							|  |  |  | 			 ((xfs_bmbt_rec_base_t)startoff << 9) | | 
					
						
							|  |  |  | 			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 		r->l1 = cpu_to_be64(XFS_MASK64HI(11) | | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			  ((xfs_bmbt_rec_base_t)startblock << 21) | | 
					
						
							|  |  |  | 			  ((xfs_bmbt_rec_base_t)blockcount & | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 		r->l0 = cpu_to_be64( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			((xfs_bmbt_rec_base_t)extent_flag << 63) | | 
					
						
							|  |  |  | 			 ((xfs_bmbt_rec_base_t)startoff << 9)); | 
					
						
							| 
									
										
										
										
											2007-08-16 16:24:15 +10:00
										 |  |  | 		r->l1 = cpu_to_be64( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 			((xfs_bmbt_rec_base_t)startblock << 21) | | 
					
						
							|  |  |  | 			 ((xfs_bmbt_rec_base_t)blockcount & | 
					
						
							|  |  |  | 			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | #endif	/* XFS_BIG_BLKNOS */
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:53 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set all the fields in a bmap extent record from the uncompressed form. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_disk_set_all( | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t	*r, | 
					
						
							|  |  |  | 	xfs_bmbt_irec_t *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock, | 
					
						
							|  |  |  | 				  s->br_blockcount, s->br_state); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set the blockcount field in a bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_set_blockcount( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t *r, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_filblks_t	v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ASSERT((v & XFS_MASK64HI(43)) == 0); | 
					
						
							|  |  |  | 	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) | | 
					
						
							|  |  |  | 		  (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set the startblock field in a bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_set_startblock( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t *r, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_fsblock_t	v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if XFS_BIG_BLKNOS
 | 
					
						
							|  |  |  | 	ASSERT((v & XFS_MASK64HI(12)) == 0); | 
					
						
							|  |  |  | 	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) | | 
					
						
							|  |  |  | 		  (xfs_bmbt_rec_base_t)(v >> 43); | 
					
						
							|  |  |  | 	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) | | 
					
						
							|  |  |  | 		  (xfs_bmbt_rec_base_t)(v << 21); | 
					
						
							|  |  |  | #else	/* !XFS_BIG_BLKNOS */
 | 
					
						
							|  |  |  | 	if (ISNULLSTARTBLOCK(v)) { | 
					
						
							|  |  |  | 		r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); | 
					
						
							|  |  |  | 		r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) | | 
					
						
							|  |  |  | 			  ((xfs_bmbt_rec_base_t)v << 21) | | 
					
						
							|  |  |  | 			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9); | 
					
						
							|  |  |  | 		r->l1 = ((xfs_bmbt_rec_base_t)v << 21) | | 
					
						
							|  |  |  | 			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif	/* XFS_BIG_BLKNOS */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set the startoff field in a bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_set_startoff( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t *r, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_fileoff_t	v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ASSERT((v & XFS_MASK64HI(9)) == 0); | 
					
						
							|  |  |  | 	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) | | 
					
						
							|  |  |  | 		((xfs_bmbt_rec_base_t)v << 9) | | 
					
						
							|  |  |  | 		  (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set the extent state field in a bmap extent record. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_set_state( | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 	xfs_bmbt_rec_host_t *r, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_exntst_t	v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN); | 
					
						
							|  |  |  | 	if (v == XFS_EXT_NORM) | 
					
						
							|  |  |  | 		r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Convert in-memory form of btree root to on-disk form. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xfs_bmbt_to_bmdr( | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*rblock, | 
					
						
							|  |  |  | 	int			rblocklen, | 
					
						
							|  |  |  | 	xfs_bmdr_block_t	*dblock, | 
					
						
							|  |  |  | 	int			dblocklen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int			dmxr; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		*fkp; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	__be64			*fpp; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_bmbt_key_t		*tkp; | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	__be64			*tpp; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC); | 
					
						
							|  |  |  | 	ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO); | 
					
						
							|  |  |  | 	ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO); | 
					
						
							|  |  |  | 	ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 
					
						
							|  |  |  | 	dblock->bb_level = rblock->bb_level; | 
					
						
							|  |  |  | 	dblock->bb_numrecs = rblock->bb_numrecs; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 
					
						
							|  |  |  | 	fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 
					
						
							| 
									
										
										
										
											2007-02-10 18:37:33 +11:00
										 |  |  | 	tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 
					
						
							| 
									
										
										
										
											2007-02-10 18:37:33 +11:00
										 |  |  | 	tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); | 
					
						
							| 
									
										
										
										
											2005-11-02 15:11:25 +11:00
										 |  |  | 	dmxr = be16_to_cpu(dblock->bb_numrecs); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:06 +10:00
										 |  |  | 	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Update the record to the passed values. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xfs_bmbt_block_t	*block; | 
					
						
							|  |  |  | 	xfs_buf_t		*bp; | 
					
						
							|  |  |  | 	int			error; | 
					
						
							|  |  |  | 	xfs_bmbt_key_t		key; | 
					
						
							|  |  |  | 	int			ptr; | 
					
						
							|  |  |  | 	xfs_bmbt_rec_t		*rp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno, | 
					
						
							|  |  |  | 		(xfs_dfilblks_t)len, (int)state); | 
					
						
							|  |  |  | 	block = xfs_bmbt_get_block(cur, 0, &bp); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	ptr = cur->bc_ptrs[0]; | 
					
						
							|  |  |  | 	rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | 
					
						
							|  |  |  | 	xfs_bmbt_disk_set_allf(rp, off, bno, len, state); | 
					
						
							|  |  |  | 	xfs_bmbt_log_recs(cur, bp, ptr, ptr); | 
					
						
							|  |  |  | 	if (ptr > 1) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-28 10:58:17 +10:00
										 |  |  | 	key.br_startoff = cpu_to_be64(off); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if ((error = xfs_bmbt_updkey(cur, &key, 1))) { | 
					
						
							|  |  |  | 		XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2006-03-14 13:29:52 +11:00
										 |  |  |  * Check extent records, which have just been read, for | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * any bit in the extent flag field. ASSERT on debug | 
					
						
							|  |  |  |  * kernels, as this condition should not occur. | 
					
						
							|  |  |  |  * Return an error condition (1) if any flags found, | 
					
						
							|  |  |  |  * otherwise return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | xfs_check_nostate_extents( | 
					
						
							| 
									
										
										
										
											2006-03-14 13:29:52 +11:00
										 |  |  | 	xfs_ifork_t		*ifp, | 
					
						
							|  |  |  | 	xfs_extnum_t		idx, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	xfs_extnum_t		num) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-03-14 13:29:52 +11:00
										 |  |  | 	for (; num > 0; num--, idx++) { | 
					
						
							| 
									
										
										
										
											2007-08-16 16:23:40 +10:00
										 |  |  | 		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		if ((ep->l0 >> | 
					
						
							|  |  |  | 		     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) { | 
					
						
							|  |  |  | 			ASSERT(0); | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } |