• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_bit.h"
22 #include "xfs_log.h"
23 #include "xfs_inum.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_dir2.h"
28 #include "xfs_da_btree.h"
29 #include "xfs_bmap_btree.h"
30 #include "xfs_alloc_btree.h"
31 #include "xfs_ialloc_btree.h"
32 #include "xfs_dir2_sf.h"
33 #include "xfs_attr_sf.h"
34 #include "xfs_dinode.h"
35 #include "xfs_inode.h"
36 #include "xfs_btree.h"
37 #include "xfs_dmapi.h"
38 #include "xfs_mount.h"
39 #include "xfs_ialloc.h"
40 #include "xfs_itable.h"
41 #include "xfs_dir2_data.h"
42 #include "xfs_dir2_leaf.h"
43 #include "xfs_dir2_block.h"
44 #include "xfs_inode_item.h"
45 #include "xfs_extfree_item.h"
46 #include "xfs_alloc.h"
47 #include "xfs_bmap.h"
48 #include "xfs_rtalloc.h"
49 #include "xfs_error.h"
50 #include "xfs_attr_leaf.h"
51 #include "xfs_rw.h"
52 #include "xfs_quota.h"
53 #include "xfs_trans_space.h"
54 #include "xfs_buf_item.h"
55 #include "xfs_filestream.h"
56 #include "xfs_vnodeops.h"
57 
58 
59 #ifdef DEBUG
60 STATIC void
61 xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork);
62 #endif
63 
64 kmem_zone_t		*xfs_bmap_free_item_zone;
65 
66 /*
67  * Prototypes for internal bmap routines.
68  */
69 
70 
71 /*
72  * Called from xfs_bmap_add_attrfork to handle extents format files.
73  */
74 STATIC int					/* error */
75 xfs_bmap_add_attrfork_extents(
76 	xfs_trans_t		*tp,		/* transaction pointer */
77 	xfs_inode_t		*ip,		/* incore inode pointer */
78 	xfs_fsblock_t		*firstblock,	/* first block allocated */
79 	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
80 	int			*flags);	/* inode logging flags */
81 
82 /*
83  * Called from xfs_bmap_add_attrfork to handle local format files.
84  */
85 STATIC int					/* error */
86 xfs_bmap_add_attrfork_local(
87 	xfs_trans_t		*tp,		/* transaction pointer */
88 	xfs_inode_t		*ip,		/* incore inode pointer */
89 	xfs_fsblock_t		*firstblock,	/* first block allocated */
90 	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
91 	int			*flags);	/* inode logging flags */
92 
93 /*
94  * Called by xfs_bmapi to update file extent records and the btree
95  * after allocating space (or doing a delayed allocation).
96  */
97 STATIC int				/* error */
98 xfs_bmap_add_extent(
99 	xfs_inode_t		*ip,	/* incore inode pointer */
100 	xfs_extnum_t		idx,	/* extent number to update/insert */
101 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
102 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
103 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
104 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
105 	int			*logflagsp, /* inode logging flags */
106 	xfs_extdelta_t		*delta, /* Change made to incore extents */
107 	int			whichfork, /* data or attr fork */
108 	int			rsvd);	/* OK to allocate reserved blocks */
109 
110 /*
111  * Called by xfs_bmap_add_extent to handle cases converting a delayed
112  * allocation to a real allocation.
113  */
114 STATIC int				/* error */
115 xfs_bmap_add_extent_delay_real(
116 	xfs_inode_t		*ip,	/* incore inode pointer */
117 	xfs_extnum_t		idx,	/* extent number to update/insert */
118 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
119 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
120 	xfs_filblks_t		*dnew,	/* new delayed-alloc indirect blocks */
121 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
122 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
123 	int			*logflagsp, /* inode logging flags */
124 	xfs_extdelta_t		*delta, /* Change made to incore extents */
125 	int			rsvd);	/* OK to allocate reserved blocks */
126 
127 /*
128  * Called by xfs_bmap_add_extent to handle cases converting a hole
129  * to a delayed allocation.
130  */
131 STATIC int				/* error */
132 xfs_bmap_add_extent_hole_delay(
133 	xfs_inode_t		*ip,	/* incore inode pointer */
134 	xfs_extnum_t		idx,	/* extent number to update/insert */
135 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
136 	int			*logflagsp,/* inode logging flags */
137 	xfs_extdelta_t		*delta, /* Change made to incore extents */
138 	int			rsvd);	/* OK to allocate reserved blocks */
139 
140 /*
141  * Called by xfs_bmap_add_extent to handle cases converting a hole
142  * to a real allocation.
143  */
144 STATIC int				/* error */
145 xfs_bmap_add_extent_hole_real(
146 	xfs_inode_t		*ip,	/* incore inode pointer */
147 	xfs_extnum_t		idx,	/* extent number to update/insert */
148 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
149 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
150 	int			*logflagsp, /* inode logging flags */
151 	xfs_extdelta_t		*delta, /* Change made to incore extents */
152 	int			whichfork); /* data or attr fork */
153 
154 /*
155  * Called by xfs_bmap_add_extent to handle cases converting an unwritten
156  * allocation to a real allocation or vice versa.
157  */
158 STATIC int				/* error */
159 xfs_bmap_add_extent_unwritten_real(
160 	xfs_inode_t		*ip,	/* incore inode pointer */
161 	xfs_extnum_t		idx,	/* extent number to update/insert */
162 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
163 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
164 	int			*logflagsp, /* inode logging flags */
165 	xfs_extdelta_t		*delta); /* Change made to incore extents */
166 
167 /*
168  * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
169  * It figures out where to ask the underlying allocator to put the new extent.
170  */
171 STATIC int				/* error */
172 xfs_bmap_alloc(
173 	xfs_bmalloca_t		*ap);	/* bmap alloc argument struct */
174 
175 /*
176  * Transform a btree format file with only one leaf node, where the
177  * extents list will fit in the inode, into an extents format file.
178  * Since the file extents are already in-core, all we have to do is
179  * give up the space for the btree root and pitch the leaf block.
180  */
181 STATIC int				/* error */
182 xfs_bmap_btree_to_extents(
183 	xfs_trans_t		*tp,	/* transaction pointer */
184 	xfs_inode_t		*ip,	/* incore inode pointer */
185 	xfs_btree_cur_t		*cur,	/* btree cursor */
186 	int			*logflagsp, /* inode logging flags */
187 	int			whichfork); /* data or attr fork */
188 
189 /*
190  * Called by xfs_bmapi to update file extent records and the btree
191  * after removing space (or undoing a delayed allocation).
192  */
193 STATIC int				/* error */
194 xfs_bmap_del_extent(
195 	xfs_inode_t		*ip,	/* incore inode pointer */
196 	xfs_trans_t		*tp,	/* current trans pointer */
197 	xfs_extnum_t		idx,	/* extent number to update/insert */
198 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
199 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
200 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
201 	int			*logflagsp,/* inode logging flags */
202 	xfs_extdelta_t		*delta, /* Change made to incore extents */
203 	int			whichfork, /* data or attr fork */
204 	int			rsvd);	 /* OK to allocate reserved blocks */
205 
206 /*
207  * Remove the entry "free" from the free item list.  Prev points to the
208  * previous entry, unless "free" is the head of the list.
209  */
210 STATIC void
211 xfs_bmap_del_free(
212 	xfs_bmap_free_t		*flist,	/* free item list header */
213 	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
214 	xfs_bmap_free_item_t	*free);	/* list item to be freed */
215 
216 /*
217  * Convert an extents-format file into a btree-format file.
218  * The new file will have a root block (in the inode) and a single child block.
219  */
220 STATIC int					/* error */
221 xfs_bmap_extents_to_btree(
222 	xfs_trans_t		*tp,		/* transaction pointer */
223 	xfs_inode_t		*ip,		/* incore inode pointer */
224 	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
225 	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
226 	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
227 	int			wasdel,		/* converting a delayed alloc */
228 	int			*logflagsp,	/* inode logging flags */
229 	int			whichfork);	/* data or attr fork */
230 
231 /*
232  * Convert a local file to an extents file.
233  * This code is sort of bogus, since the file data needs to get
234  * logged so it won't be lost.  The bmap-level manipulations are ok, though.
235  */
236 STATIC int				/* error */
237 xfs_bmap_local_to_extents(
238 	xfs_trans_t	*tp,		/* transaction pointer */
239 	xfs_inode_t	*ip,		/* incore inode pointer */
240 	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
241 	xfs_extlen_t	total,		/* total blocks needed by transaction */
242 	int		*logflagsp,	/* inode logging flags */
243 	int		whichfork);	/* data or attr fork */
244 
245 /*
246  * Search the extents list for the inode, for the extent containing bno.
247  * If bno lies in a hole, point to the next entry.  If bno lies past eof,
248  * *eofp will be set, and *prevp will contain the last entry (null if none).
249  * Else, *lastxp will be set to the index of the found
250  * entry; *gotp will contain the entry.
251  */
252 STATIC xfs_bmbt_rec_host_t *		/* pointer to found extent entry */
253 xfs_bmap_search_extents(
254 	xfs_inode_t	*ip,		/* incore inode pointer */
255 	xfs_fileoff_t	bno,		/* block number searched for */
256 	int		whichfork,	/* data or attr fork */
257 	int		*eofp,		/* out: end of file found */
258 	xfs_extnum_t	*lastxp,	/* out: last extent index */
259 	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
260 	xfs_bmbt_irec_t	*prevp);	/* out: previous extent entry found */
261 
262 /*
263  * Check the last inode extent to determine whether this allocation will result
264  * in blocks being allocated at the end of the file. When we allocate new data
265  * blocks at the end of the file which do not start at the previous data block,
266  * we will try to align the new blocks at stripe unit boundaries.
267  */
268 STATIC int				/* error */
269 xfs_bmap_isaeof(
270 	xfs_inode_t	*ip,		/* incore inode pointer */
271 	xfs_fileoff_t   off,		/* file offset in fsblocks */
272 	int             whichfork,	/* data or attribute fork */
273 	char		*aeof);		/* return value */
274 
275 #ifdef XFS_BMAP_TRACE
276 /*
277  * Add bmap trace entry prior to a call to xfs_iext_remove.
278  */
279 STATIC void
280 xfs_bmap_trace_delete(
281 	const char	*fname,		/* function name */
282 	char		*desc,		/* operation description */
283 	xfs_inode_t	*ip,		/* incore inode pointer */
284 	xfs_extnum_t	idx,		/* index of entry(entries) deleted */
285 	xfs_extnum_t	cnt,		/* count of entries deleted, 1 or 2 */
286 	int		whichfork);	/* data or attr fork */
287 
288 /*
289  * Add bmap trace entry prior to a call to xfs_iext_insert, or
290  * reading in the extents list from the disk (in the btree).
291  */
292 STATIC void
293 xfs_bmap_trace_insert(
294 	const char	*fname,		/* function name */
295 	char		*desc,		/* operation description */
296 	xfs_inode_t	*ip,		/* incore inode pointer */
297 	xfs_extnum_t	idx,		/* index of entry(entries) inserted */
298 	xfs_extnum_t	cnt,		/* count of entries inserted, 1 or 2 */
299 	xfs_bmbt_irec_t	*r1,		/* inserted record 1 */
300 	xfs_bmbt_irec_t	*r2,		/* inserted record 2 or null */
301 	int		whichfork);	/* data or attr fork */
302 
303 /*
304  * Add bmap trace entry after updating an extent record in place.
305  */
306 STATIC void
307 xfs_bmap_trace_post_update(
308 	const char	*fname,		/* function name */
309 	char		*desc,		/* operation description */
310 	xfs_inode_t	*ip,		/* incore inode pointer */
311 	xfs_extnum_t	idx,		/* index of entry updated */
312 	int		whichfork);	/* data or attr fork */
313 
314 /*
315  * Add bmap trace entry prior to updating an extent record in place.
316  */
317 STATIC void
318 xfs_bmap_trace_pre_update(
319 	const char	*fname,		/* function name */
320 	char		*desc,		/* operation description */
321 	xfs_inode_t	*ip,		/* incore inode pointer */
322 	xfs_extnum_t	idx,		/* index of entry to be updated */
323 	int		whichfork);	/* data or attr fork */
324 
325 #define	XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)	\
326 	xfs_bmap_trace_delete(__func__,d,ip,i,c,w)
327 #define	XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)	\
328 	xfs_bmap_trace_insert(__func__,d,ip,i,c,r1,r2,w)
329 #define	XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)	\
330 	xfs_bmap_trace_post_update(__func__,d,ip,i,w)
331 #define	XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)	\
332 	xfs_bmap_trace_pre_update(__func__,d,ip,i,w)
333 #else
334 #define	XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
335 #define	XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
336 #define	XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)
337 #define	XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)
338 #endif	/* XFS_BMAP_TRACE */
339 
340 /*
341  * Compute the worst-case number of indirect blocks that will be used
342  * for ip's delayed extent of length "len".
343  */
344 STATIC xfs_filblks_t
345 xfs_bmap_worst_indlen(
346 	xfs_inode_t		*ip,	/* incore inode pointer */
347 	xfs_filblks_t		len);	/* delayed extent length */
348 
349 #ifdef DEBUG
350 /*
351  * Perform various validation checks on the values being returned
352  * from xfs_bmapi().
353  */
354 STATIC void
355 xfs_bmap_validate_ret(
356 	xfs_fileoff_t		bno,
357 	xfs_filblks_t		len,
358 	int			flags,
359 	xfs_bmbt_irec_t		*mval,
360 	int			nmap,
361 	int			ret_nmap);
362 #else
363 #define	xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
364 #endif /* DEBUG */
365 
366 #if defined(XFS_RW_TRACE)
367 STATIC void
368 xfs_bunmap_trace(
369 	xfs_inode_t		*ip,
370 	xfs_fileoff_t		bno,
371 	xfs_filblks_t		len,
372 	int			flags,
373 	inst_t			*ra);
374 #else
375 #define	xfs_bunmap_trace(ip, bno, len, flags, ra)
376 #endif	/* XFS_RW_TRACE */
377 
378 STATIC int
379 xfs_bmap_count_tree(
380 	xfs_mount_t     *mp,
381 	xfs_trans_t     *tp,
382 	xfs_ifork_t	*ifp,
383 	xfs_fsblock_t   blockno,
384 	int             levelin,
385 	int		*count);
386 
387 STATIC void
388 xfs_bmap_count_leaves(
389 	xfs_ifork_t		*ifp,
390 	xfs_extnum_t		idx,
391 	int			numrecs,
392 	int			*count);
393 
394 STATIC void
395 xfs_bmap_disk_count_leaves(
396 	struct xfs_mount	*mp,
397 	struct xfs_btree_block	*block,
398 	int			numrecs,
399 	int			*count);
400 
401 /*
402  * Bmap internal routines.
403  */
404 
405 STATIC int				/* error */
xfs_bmbt_lookup_eq(struct xfs_btree_cur * cur,xfs_fileoff_t off,xfs_fsblock_t bno,xfs_filblks_t len,int * stat)406 xfs_bmbt_lookup_eq(
407 	struct xfs_btree_cur	*cur,
408 	xfs_fileoff_t		off,
409 	xfs_fsblock_t		bno,
410 	xfs_filblks_t		len,
411 	int			*stat)	/* success/failure */
412 {
413 	cur->bc_rec.b.br_startoff = off;
414 	cur->bc_rec.b.br_startblock = bno;
415 	cur->bc_rec.b.br_blockcount = len;
416 	return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
417 }
418 
419 STATIC int				/* error */
xfs_bmbt_lookup_ge(struct xfs_btree_cur * cur,xfs_fileoff_t off,xfs_fsblock_t bno,xfs_filblks_t len,int * stat)420 xfs_bmbt_lookup_ge(
421 	struct xfs_btree_cur	*cur,
422 	xfs_fileoff_t		off,
423 	xfs_fsblock_t		bno,
424 	xfs_filblks_t		len,
425 	int			*stat)	/* success/failure */
426 {
427 	cur->bc_rec.b.br_startoff = off;
428 	cur->bc_rec.b.br_startblock = bno;
429 	cur->bc_rec.b.br_blockcount = len;
430 	return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
431 }
432 
433 /*
434 * Update the record referred to by cur to the value given
435  * by [off, bno, len, state].
436  * This either works (return 0) or gets an EFSCORRUPTED error.
437  */
438 STATIC int
xfs_bmbt_update(struct xfs_btree_cur * cur,xfs_fileoff_t off,xfs_fsblock_t bno,xfs_filblks_t len,xfs_exntst_t state)439 xfs_bmbt_update(
440 	struct xfs_btree_cur	*cur,
441 	xfs_fileoff_t		off,
442 	xfs_fsblock_t		bno,
443 	xfs_filblks_t		len,
444 	xfs_exntst_t		state)
445 {
446 	union xfs_btree_rec	rec;
447 
448 	xfs_bmbt_disk_set_allf(&rec.bmbt, off, bno, len, state);
449 	return xfs_btree_update(cur, &rec);
450 }
451 
452 /*
453  * Called from xfs_bmap_add_attrfork to handle btree format files.
454  */
455 STATIC int					/* error */
xfs_bmap_add_attrfork_btree(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fsblock_t * firstblock,xfs_bmap_free_t * flist,int * flags)456 xfs_bmap_add_attrfork_btree(
457 	xfs_trans_t		*tp,		/* transaction pointer */
458 	xfs_inode_t		*ip,		/* incore inode pointer */
459 	xfs_fsblock_t		*firstblock,	/* first block allocated */
460 	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
461 	int			*flags)		/* inode logging flags */
462 {
463 	xfs_btree_cur_t		*cur;		/* btree cursor */
464 	int			error;		/* error return value */
465 	xfs_mount_t		*mp;		/* file system mount struct */
466 	int			stat;		/* newroot status */
467 
468 	mp = ip->i_mount;
469 	if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
470 		*flags |= XFS_ILOG_DBROOT;
471 	else {
472 		cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
473 		cur->bc_private.b.flist = flist;
474 		cur->bc_private.b.firstblock = *firstblock;
475 		if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
476 			goto error0;
477 		/* must be at least one entry */
478 		XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
479 		if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
480 			goto error0;
481 		if (stat == 0) {
482 			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
483 			return XFS_ERROR(ENOSPC);
484 		}
485 		*firstblock = cur->bc_private.b.firstblock;
486 		cur->bc_private.b.allocated = 0;
487 		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
488 	}
489 	return 0;
490 error0:
491 	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
492 	return error;
493 }
494 
495 /*
496  * Called from xfs_bmap_add_attrfork to handle extents format files.
497  */
498 STATIC int					/* error */
xfs_bmap_add_attrfork_extents(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fsblock_t * firstblock,xfs_bmap_free_t * flist,int * flags)499 xfs_bmap_add_attrfork_extents(
500 	xfs_trans_t		*tp,		/* transaction pointer */
501 	xfs_inode_t		*ip,		/* incore inode pointer */
502 	xfs_fsblock_t		*firstblock,	/* first block allocated */
503 	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
504 	int			*flags)		/* inode logging flags */
505 {
506 	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
507 	int			error;		/* error return value */
508 
509 	if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
510 		return 0;
511 	cur = NULL;
512 	error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
513 		flags, XFS_DATA_FORK);
514 	if (cur) {
515 		cur->bc_private.b.allocated = 0;
516 		xfs_btree_del_cursor(cur,
517 			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
518 	}
519 	return error;
520 }
521 
522 /*
523  * Called from xfs_bmap_add_attrfork to handle local format files.
524  */
525 STATIC int					/* error */
xfs_bmap_add_attrfork_local(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fsblock_t * firstblock,xfs_bmap_free_t * flist,int * flags)526 xfs_bmap_add_attrfork_local(
527 	xfs_trans_t		*tp,		/* transaction pointer */
528 	xfs_inode_t		*ip,		/* incore inode pointer */
529 	xfs_fsblock_t		*firstblock,	/* first block allocated */
530 	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
531 	int			*flags)		/* inode logging flags */
532 {
533 	xfs_da_args_t		dargs;		/* args for dir/attr code */
534 	int			error;		/* error return value */
535 	xfs_mount_t		*mp;		/* mount structure pointer */
536 
537 	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
538 		return 0;
539 	if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
540 		mp = ip->i_mount;
541 		memset(&dargs, 0, sizeof(dargs));
542 		dargs.dp = ip;
543 		dargs.firstblock = firstblock;
544 		dargs.flist = flist;
545 		dargs.total = mp->m_dirblkfsbs;
546 		dargs.whichfork = XFS_DATA_FORK;
547 		dargs.trans = tp;
548 		error = xfs_dir2_sf_to_block(&dargs);
549 	} else
550 		error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
551 			XFS_DATA_FORK);
552 	return error;
553 }
554 
555 /*
556  * Called by xfs_bmapi to update file extent records and the btree
557  * after allocating space (or doing a delayed allocation).
558  */
559 STATIC int				/* error */
xfs_bmap_add_extent(xfs_inode_t * ip,xfs_extnum_t idx,xfs_btree_cur_t ** curp,xfs_bmbt_irec_t * new,xfs_fsblock_t * first,xfs_bmap_free_t * flist,int * logflagsp,xfs_extdelta_t * delta,int whichfork,int rsvd)560 xfs_bmap_add_extent(
561 	xfs_inode_t		*ip,	/* incore inode pointer */
562 	xfs_extnum_t		idx,	/* extent number to update/insert */
563 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
564 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
565 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
566 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
567 	int			*logflagsp, /* inode logging flags */
568 	xfs_extdelta_t		*delta, /* Change made to incore extents */
569 	int			whichfork, /* data or attr fork */
570 	int			rsvd)	/* OK to use reserved data blocks */
571 {
572 	xfs_btree_cur_t		*cur;	/* btree cursor or null */
573 	xfs_filblks_t		da_new; /* new count del alloc blocks used */
574 	xfs_filblks_t		da_old; /* old count del alloc blocks used */
575 	int			error;	/* error return value */
576 	xfs_ifork_t		*ifp;	/* inode fork ptr */
577 	int			logflags; /* returned value */
578 	xfs_extnum_t		nextents; /* number of extents in file now */
579 
580 	XFS_STATS_INC(xs_add_exlist);
581 	cur = *curp;
582 	ifp = XFS_IFORK_PTR(ip, whichfork);
583 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
584 	ASSERT(idx <= nextents);
585 	da_old = da_new = 0;
586 	error = 0;
587 	/*
588 	 * This is the first extent added to a new/empty file.
589 	 * Special case this one, so other routines get to assume there are
590 	 * already extents in the list.
591 	 */
592 	if (nextents == 0) {
593 		XFS_BMAP_TRACE_INSERT("insert empty", ip, 0, 1, new, NULL,
594 			whichfork);
595 		xfs_iext_insert(ifp, 0, 1, new);
596 		ASSERT(cur == NULL);
597 		ifp->if_lastex = 0;
598 		if (!isnullstartblock(new->br_startblock)) {
599 			XFS_IFORK_NEXT_SET(ip, whichfork, 1);
600 			logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
601 		} else
602 			logflags = 0;
603 		/* DELTA: single new extent */
604 		if (delta) {
605 			if (delta->xed_startoff > new->br_startoff)
606 				delta->xed_startoff = new->br_startoff;
607 			if (delta->xed_blockcount <
608 					new->br_startoff + new->br_blockcount)
609 				delta->xed_blockcount = new->br_startoff +
610 						new->br_blockcount;
611 		}
612 	}
613 	/*
614 	 * Any kind of new delayed allocation goes here.
615 	 */
616 	else if (isnullstartblock(new->br_startblock)) {
617 		if (cur)
618 			ASSERT((cur->bc_private.b.flags &
619 				XFS_BTCUR_BPRV_WASDEL) == 0);
620 		if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new,
621 				&logflags, delta, rsvd)))
622 			goto done;
623 	}
624 	/*
625 	 * Real allocation off the end of the file.
626 	 */
627 	else if (idx == nextents) {
628 		if (cur)
629 			ASSERT((cur->bc_private.b.flags &
630 				XFS_BTCUR_BPRV_WASDEL) == 0);
631 		if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
632 				&logflags, delta, whichfork)))
633 			goto done;
634 	} else {
635 		xfs_bmbt_irec_t	prev;	/* old extent at offset idx */
636 
637 		/*
638 		 * Get the record referred to by idx.
639 		 */
640 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &prev);
641 		/*
642 		 * If it's a real allocation record, and the new allocation ends
643 		 * after the start of the referred to record, then we're filling
644 		 * in a delayed or unwritten allocation with a real one, or
645 		 * converting real back to unwritten.
646 		 */
647 		if (!isnullstartblock(new->br_startblock) &&
648 		    new->br_startoff + new->br_blockcount > prev.br_startoff) {
649 			if (prev.br_state != XFS_EXT_UNWRITTEN &&
650 			    isnullstartblock(prev.br_startblock)) {
651 				da_old = startblockval(prev.br_startblock);
652 				if (cur)
653 					ASSERT(cur->bc_private.b.flags &
654 						XFS_BTCUR_BPRV_WASDEL);
655 				if ((error = xfs_bmap_add_extent_delay_real(ip,
656 					idx, &cur, new, &da_new, first, flist,
657 					&logflags, delta, rsvd)))
658 					goto done;
659 			} else if (new->br_state == XFS_EXT_NORM) {
660 				ASSERT(new->br_state == XFS_EXT_NORM);
661 				if ((error = xfs_bmap_add_extent_unwritten_real(
662 					ip, idx, &cur, new, &logflags, delta)))
663 					goto done;
664 			} else {
665 				ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
666 				if ((error = xfs_bmap_add_extent_unwritten_real(
667 					ip, idx, &cur, new, &logflags, delta)))
668 					goto done;
669 			}
670 			ASSERT(*curp == cur || *curp == NULL);
671 		}
672 		/*
673 		 * Otherwise we're filling in a hole with an allocation.
674 		 */
675 		else {
676 			if (cur)
677 				ASSERT((cur->bc_private.b.flags &
678 					XFS_BTCUR_BPRV_WASDEL) == 0);
679 			if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
680 					new, &logflags, delta, whichfork)))
681 				goto done;
682 		}
683 	}
684 
685 	ASSERT(*curp == cur || *curp == NULL);
686 	/*
687 	 * Convert to a btree if necessary.
688 	 */
689 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
690 	    XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
691 		int	tmp_logflags;	/* partial log flag return val */
692 
693 		ASSERT(cur == NULL);
694 		error = xfs_bmap_extents_to_btree(ip->i_transp, ip, first,
695 			flist, &cur, da_old > 0, &tmp_logflags, whichfork);
696 		logflags |= tmp_logflags;
697 		if (error)
698 			goto done;
699 	}
700 	/*
701 	 * Adjust for changes in reserved delayed indirect blocks.
702 	 * Nothing to do for disk quotas here.
703 	 */
704 	if (da_old || da_new) {
705 		xfs_filblks_t	nblks;
706 
707 		nblks = da_new;
708 		if (cur)
709 			nblks += cur->bc_private.b.allocated;
710 		ASSERT(nblks <= da_old);
711 		if (nblks < da_old)
712 			xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
713 				(int64_t)(da_old - nblks), rsvd);
714 	}
715 	/*
716 	 * Clear out the allocated field, done with it now in any case.
717 	 */
718 	if (cur) {
719 		cur->bc_private.b.allocated = 0;
720 		*curp = cur;
721 	}
722 done:
723 #ifdef DEBUG
724 	if (!error)
725 		xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
726 #endif
727 	*logflagsp = logflags;
728 	return error;
729 }
730 
731 /*
732  * Called by xfs_bmap_add_extent to handle cases converting a delayed
733  * allocation to a real allocation.
734  */
735 STATIC int				/* error */
xfs_bmap_add_extent_delay_real(xfs_inode_t * ip,xfs_extnum_t idx,xfs_btree_cur_t ** curp,xfs_bmbt_irec_t * new,xfs_filblks_t * dnew,xfs_fsblock_t * first,xfs_bmap_free_t * flist,int * logflagsp,xfs_extdelta_t * delta,int rsvd)736 xfs_bmap_add_extent_delay_real(
737 	xfs_inode_t		*ip,	/* incore inode pointer */
738 	xfs_extnum_t		idx,	/* extent number to update/insert */
739 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
740 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
741 	xfs_filblks_t		*dnew,	/* new delayed-alloc indirect blocks */
742 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
743 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
744 	int			*logflagsp, /* inode logging flags */
745 	xfs_extdelta_t		*delta, /* Change made to incore extents */
746 	int			rsvd)	/* OK to use reserved data block allocation */
747 {
748 	xfs_btree_cur_t		*cur;	/* btree cursor */
749 	int			diff;	/* temp value */
750 	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */
751 	int			error;	/* error return value */
752 	int			i;	/* temp state */
753 	xfs_ifork_t		*ifp;	/* inode fork pointer */
754 	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
755 	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
756 					/* left is 0, right is 1, prev is 2 */
757 	int			rval=0;	/* return value (logging flags) */
758 	int			state = 0;/* state bits, accessed thru macros */
759 	xfs_filblks_t		temp=0;	/* value for dnew calculations */
760 	xfs_filblks_t		temp2=0;/* value for dnew calculations */
761 	int			tmp_rval;	/* partial logging flags */
762 	enum {				/* bit number definitions for state */
763 		LEFT_CONTIG,	RIGHT_CONTIG,
764 		LEFT_FILLING,	RIGHT_FILLING,
765 		LEFT_DELAY,	RIGHT_DELAY,
766 		LEFT_VALID,	RIGHT_VALID
767 	};
768 
769 #define	LEFT		r[0]
770 #define	RIGHT		r[1]
771 #define	PREV		r[2]
772 #define	MASK(b)		(1 << (b))
773 #define	MASK2(a,b)	(MASK(a) | MASK(b))
774 #define	MASK3(a,b,c)	(MASK2(a,b) | MASK(c))
775 #define	MASK4(a,b,c,d)	(MASK3(a,b,c) | MASK(d))
776 #define	STATE_SET(b,v)	((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
777 #define	STATE_TEST(b)	(state & MASK(b))
778 #define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
779 				       ((state &= ~MASK(b)), 0))
780 #define	SWITCH_STATE		\
781 	(state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
782 
783 	/*
784 	 * Set up a bunch of variables to make the tests simpler.
785 	 */
786 	cur = *curp;
787 	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
788 	ep = xfs_iext_get_ext(ifp, idx);
789 	xfs_bmbt_get_all(ep, &PREV);
790 	new_endoff = new->br_startoff + new->br_blockcount;
791 	ASSERT(PREV.br_startoff <= new->br_startoff);
792 	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
793 	/*
794 	 * Set flags determining what part of the previous delayed allocation
795 	 * extent is being replaced by a real allocation.
796 	 */
797 	STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
798 	STATE_SET(RIGHT_FILLING,
799 		PREV.br_startoff + PREV.br_blockcount == new_endoff);
800 	/*
801 	 * Check and set flags if this segment has a left neighbor.
802 	 * Don't set contiguous if the combined extent would be too large.
803 	 */
804 	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
805 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
806 		STATE_SET(LEFT_DELAY, isnullstartblock(LEFT.br_startblock));
807 	}
808 	STATE_SET(LEFT_CONTIG,
809 		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
810 		LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
811 		LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
812 		LEFT.br_state == new->br_state &&
813 		LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
814 	/*
815 	 * Check and set flags if this segment has a right neighbor.
816 	 * Don't set contiguous if the combined extent would be too large.
817 	 * Also check for all-three-contiguous being too large.
818 	 */
819 	if (STATE_SET_TEST(RIGHT_VALID,
820 			idx <
821 			ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
822 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
823 		STATE_SET(RIGHT_DELAY, isnullstartblock(RIGHT.br_startblock));
824 	}
825 	STATE_SET(RIGHT_CONTIG,
826 		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
827 		new_endoff == RIGHT.br_startoff &&
828 		new->br_startblock + new->br_blockcount ==
829 		    RIGHT.br_startblock &&
830 		new->br_state == RIGHT.br_state &&
831 		new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
832 		((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
833 		  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
834 		 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
835 		     <= MAXEXTLEN));
836 	error = 0;
837 	/*
838 	 * Switch out based on the FILLING and CONTIG state bits.
839 	 */
840 	switch (SWITCH_STATE) {
841 
842 	case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
843 		/*
844 		 * Filling in all of a previously delayed allocation extent.
845 		 * The left and right neighbors are both contiguous with new.
846 		 */
847 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
848 			XFS_DATA_FORK);
849 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
850 			LEFT.br_blockcount + PREV.br_blockcount +
851 			RIGHT.br_blockcount);
852 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
853 			XFS_DATA_FORK);
854 		XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
855 		xfs_iext_remove(ifp, idx, 2);
856 		ip->i_df.if_lastex = idx - 1;
857 		ip->i_d.di_nextents--;
858 		if (cur == NULL)
859 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
860 		else {
861 			rval = XFS_ILOG_CORE;
862 			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
863 					RIGHT.br_startblock,
864 					RIGHT.br_blockcount, &i)))
865 				goto done;
866 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
867 			if ((error = xfs_btree_delete(cur, &i)))
868 				goto done;
869 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
870 			if ((error = xfs_btree_decrement(cur, 0, &i)))
871 				goto done;
872 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
873 			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
874 					LEFT.br_startblock,
875 					LEFT.br_blockcount +
876 					PREV.br_blockcount +
877 					RIGHT.br_blockcount, LEFT.br_state)))
878 				goto done;
879 		}
880 		*dnew = 0;
881 		/* DELTA: Three in-core extents are replaced by one. */
882 		temp = LEFT.br_startoff;
883 		temp2 = LEFT.br_blockcount +
884 			PREV.br_blockcount +
885 			RIGHT.br_blockcount;
886 		break;
887 
888 	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
889 		/*
890 		 * Filling in all of a previously delayed allocation extent.
891 		 * The left neighbor is contiguous, the right is not.
892 		 */
893 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
894 			XFS_DATA_FORK);
895 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
896 			LEFT.br_blockcount + PREV.br_blockcount);
897 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
898 			XFS_DATA_FORK);
899 		ip->i_df.if_lastex = idx - 1;
900 		XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
901 		xfs_iext_remove(ifp, idx, 1);
902 		if (cur == NULL)
903 			rval = XFS_ILOG_DEXT;
904 		else {
905 			rval = 0;
906 			if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
907 					LEFT.br_startblock, LEFT.br_blockcount,
908 					&i)))
909 				goto done;
910 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
911 			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
912 					LEFT.br_startblock,
913 					LEFT.br_blockcount +
914 					PREV.br_blockcount, LEFT.br_state)))
915 				goto done;
916 		}
917 		*dnew = 0;
918 		/* DELTA: Two in-core extents are replaced by one. */
919 		temp = LEFT.br_startoff;
920 		temp2 = LEFT.br_blockcount +
921 			PREV.br_blockcount;
922 		break;
923 
924 	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
925 		/*
926 		 * Filling in all of a previously delayed allocation extent.
927 		 * The right neighbor is contiguous, the left is not.
928 		 */
929 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
930 		xfs_bmbt_set_startblock(ep, new->br_startblock);
931 		xfs_bmbt_set_blockcount(ep,
932 			PREV.br_blockcount + RIGHT.br_blockcount);
933 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
934 		ip->i_df.if_lastex = idx;
935 		XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
936 		xfs_iext_remove(ifp, idx + 1, 1);
937 		if (cur == NULL)
938 			rval = XFS_ILOG_DEXT;
939 		else {
940 			rval = 0;
941 			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
942 					RIGHT.br_startblock,
943 					RIGHT.br_blockcount, &i)))
944 				goto done;
945 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
946 			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
947 					new->br_startblock,
948 					PREV.br_blockcount +
949 					RIGHT.br_blockcount, PREV.br_state)))
950 				goto done;
951 		}
952 		*dnew = 0;
953 		/* DELTA: Two in-core extents are replaced by one. */
954 		temp = PREV.br_startoff;
955 		temp2 = PREV.br_blockcount +
956 			RIGHT.br_blockcount;
957 		break;
958 
959 	case MASK2(LEFT_FILLING, RIGHT_FILLING):
960 		/*
961 		 * Filling in all of a previously delayed allocation extent.
962 		 * Neither the left nor right neighbors are contiguous with
963 		 * the new one.
964 		 */
965 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
966 		xfs_bmbt_set_startblock(ep, new->br_startblock);
967 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
968 		ip->i_df.if_lastex = idx;
969 		ip->i_d.di_nextents++;
970 		if (cur == NULL)
971 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
972 		else {
973 			rval = XFS_ILOG_CORE;
974 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
975 					new->br_startblock, new->br_blockcount,
976 					&i)))
977 				goto done;
978 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
979 			cur->bc_rec.b.br_state = XFS_EXT_NORM;
980 			if ((error = xfs_btree_insert(cur, &i)))
981 				goto done;
982 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
983 		}
984 		*dnew = 0;
985 		/* DELTA: The in-core extent described by new changed type. */
986 		temp = new->br_startoff;
987 		temp2 = new->br_blockcount;
988 		break;
989 
990 	case MASK2(LEFT_FILLING, LEFT_CONTIG):
991 		/*
992 		 * Filling in the first part of a previous delayed allocation.
993 		 * The left neighbor is contiguous.
994 		 */
995 		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
996 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
997 			LEFT.br_blockcount + new->br_blockcount);
998 		xfs_bmbt_set_startoff(ep,
999 			PREV.br_startoff + new->br_blockcount);
1000 		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
1001 		temp = PREV.br_blockcount - new->br_blockcount;
1002 		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
1003 		xfs_bmbt_set_blockcount(ep, temp);
1004 		ip->i_df.if_lastex = idx - 1;
1005 		if (cur == NULL)
1006 			rval = XFS_ILOG_DEXT;
1007 		else {
1008 			rval = 0;
1009 			if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
1010 					LEFT.br_startblock, LEFT.br_blockcount,
1011 					&i)))
1012 				goto done;
1013 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1014 			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1015 					LEFT.br_startblock,
1016 					LEFT.br_blockcount +
1017 					new->br_blockcount,
1018 					LEFT.br_state)))
1019 				goto done;
1020 		}
1021 		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1022 			startblockval(PREV.br_startblock));
1023 		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1024 		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
1025 		*dnew = temp;
1026 		/* DELTA: The boundary between two in-core extents moved. */
1027 		temp = LEFT.br_startoff;
1028 		temp2 = LEFT.br_blockcount +
1029 			PREV.br_blockcount;
1030 		break;
1031 
1032 	case MASK(LEFT_FILLING):
1033 		/*
1034 		 * Filling in the first part of a previous delayed allocation.
1035 		 * The left neighbor is not contiguous.
1036 		 */
1037 		XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1038 		xfs_bmbt_set_startoff(ep, new_endoff);
1039 		temp = PREV.br_blockcount - new->br_blockcount;
1040 		xfs_bmbt_set_blockcount(ep, temp);
1041 		XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
1042 			XFS_DATA_FORK);
1043 		xfs_iext_insert(ifp, idx, 1, new);
1044 		ip->i_df.if_lastex = idx;
1045 		ip->i_d.di_nextents++;
1046 		if (cur == NULL)
1047 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1048 		else {
1049 			rval = XFS_ILOG_CORE;
1050 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1051 					new->br_startblock, new->br_blockcount,
1052 					&i)))
1053 				goto done;
1054 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1055 			cur->bc_rec.b.br_state = XFS_EXT_NORM;
1056 			if ((error = xfs_btree_insert(cur, &i)))
1057 				goto done;
1058 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1059 		}
1060 		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1061 		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1062 			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1063 					first, flist, &cur, 1, &tmp_rval,
1064 					XFS_DATA_FORK);
1065 			rval |= tmp_rval;
1066 			if (error)
1067 				goto done;
1068 		}
1069 		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1070 			startblockval(PREV.br_startblock) -
1071 			(cur ? cur->bc_private.b.allocated : 0));
1072 		ep = xfs_iext_get_ext(ifp, idx + 1);
1073 		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1074 		XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx + 1, XFS_DATA_FORK);
1075 		*dnew = temp;
1076 		/* DELTA: One in-core extent is split in two. */
1077 		temp = PREV.br_startoff;
1078 		temp2 = PREV.br_blockcount;
1079 		break;
1080 
1081 	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
1082 		/*
1083 		 * Filling in the last part of a previous delayed allocation.
1084 		 * The right neighbor is contiguous with the new allocation.
1085 		 */
1086 		temp = PREV.br_blockcount - new->br_blockcount;
1087 		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
1088 		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
1089 		xfs_bmbt_set_blockcount(ep, temp);
1090 		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
1091 			new->br_startoff, new->br_startblock,
1092 			new->br_blockcount + RIGHT.br_blockcount,
1093 			RIGHT.br_state);
1094 		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
1095 		ip->i_df.if_lastex = idx + 1;
1096 		if (cur == NULL)
1097 			rval = XFS_ILOG_DEXT;
1098 		else {
1099 			rval = 0;
1100 			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1101 					RIGHT.br_startblock,
1102 					RIGHT.br_blockcount, &i)))
1103 				goto done;
1104 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1105 			if ((error = xfs_bmbt_update(cur, new->br_startoff,
1106 					new->br_startblock,
1107 					new->br_blockcount +
1108 					RIGHT.br_blockcount,
1109 					RIGHT.br_state)))
1110 				goto done;
1111 		}
1112 		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1113 			startblockval(PREV.br_startblock));
1114 		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1115 		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
1116 		*dnew = temp;
1117 		/* DELTA: The boundary between two in-core extents moved. */
1118 		temp = PREV.br_startoff;
1119 		temp2 = PREV.br_blockcount +
1120 			RIGHT.br_blockcount;
1121 		break;
1122 
1123 	case MASK(RIGHT_FILLING):
1124 		/*
1125 		 * Filling in the last part of a previous delayed allocation.
1126 		 * The right neighbor is not contiguous.
1127 		 */
1128 		temp = PREV.br_blockcount - new->br_blockcount;
1129 		XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1130 		xfs_bmbt_set_blockcount(ep, temp);
1131 		XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
1132 			XFS_DATA_FORK);
1133 		xfs_iext_insert(ifp, idx + 1, 1, new);
1134 		ip->i_df.if_lastex = idx + 1;
1135 		ip->i_d.di_nextents++;
1136 		if (cur == NULL)
1137 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1138 		else {
1139 			rval = XFS_ILOG_CORE;
1140 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1141 					new->br_startblock, new->br_blockcount,
1142 					&i)))
1143 				goto done;
1144 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1145 			cur->bc_rec.b.br_state = XFS_EXT_NORM;
1146 			if ((error = xfs_btree_insert(cur, &i)))
1147 				goto done;
1148 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1149 		}
1150 		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1151 		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1152 			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1153 				first, flist, &cur, 1, &tmp_rval,
1154 				XFS_DATA_FORK);
1155 			rval |= tmp_rval;
1156 			if (error)
1157 				goto done;
1158 		}
1159 		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1160 			startblockval(PREV.br_startblock) -
1161 			(cur ? cur->bc_private.b.allocated : 0));
1162 		ep = xfs_iext_get_ext(ifp, idx);
1163 		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1164 		XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1165 		*dnew = temp;
1166 		/* DELTA: One in-core extent is split in two. */
1167 		temp = PREV.br_startoff;
1168 		temp2 = PREV.br_blockcount;
1169 		break;
1170 
1171 	case 0:
1172 		/*
1173 		 * Filling in the middle part of a previous delayed allocation.
1174 		 * Contiguity is impossible here.
1175 		 * This case is avoided almost all the time.
1176 		 */
1177 		temp = new->br_startoff - PREV.br_startoff;
1178 		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
1179 		xfs_bmbt_set_blockcount(ep, temp);
1180 		r[0] = *new;
1181 		r[1].br_state = PREV.br_state;
1182 		r[1].br_startblock = 0;
1183 		r[1].br_startoff = new_endoff;
1184 		temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
1185 		r[1].br_blockcount = temp2;
1186 		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
1187 			XFS_DATA_FORK);
1188 		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
1189 		ip->i_df.if_lastex = idx + 1;
1190 		ip->i_d.di_nextents++;
1191 		if (cur == NULL)
1192 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1193 		else {
1194 			rval = XFS_ILOG_CORE;
1195 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1196 					new->br_startblock, new->br_blockcount,
1197 					&i)))
1198 				goto done;
1199 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1200 			cur->bc_rec.b.br_state = XFS_EXT_NORM;
1201 			if ((error = xfs_btree_insert(cur, &i)))
1202 				goto done;
1203 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1204 		}
1205 		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1206 		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1207 			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1208 					first, flist, &cur, 1, &tmp_rval,
1209 					XFS_DATA_FORK);
1210 			rval |= tmp_rval;
1211 			if (error)
1212 				goto done;
1213 		}
1214 		temp = xfs_bmap_worst_indlen(ip, temp);
1215 		temp2 = xfs_bmap_worst_indlen(ip, temp2);
1216 		diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
1217 			(cur ? cur->bc_private.b.allocated : 0));
1218 		if (diff > 0 &&
1219 		    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
1220 			/*
1221 			 * Ick gross gag me with a spoon.
1222 			 */
1223 			ASSERT(0);	/* want to see if this ever happens! */
1224 			while (diff > 0) {
1225 				if (temp) {
1226 					temp--;
1227 					diff--;
1228 					if (!diff ||
1229 					    !xfs_mod_incore_sb(ip->i_mount,
1230 						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
1231 						break;
1232 				}
1233 				if (temp2) {
1234 					temp2--;
1235 					diff--;
1236 					if (!diff ||
1237 					    !xfs_mod_incore_sb(ip->i_mount,
1238 						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
1239 						break;
1240 				}
1241 			}
1242 		}
1243 		ep = xfs_iext_get_ext(ifp, idx);
1244 		xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1245 		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
1246 		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
1247 		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
1248 			nullstartblock((int)temp2));
1249 		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
1250 		*dnew = temp + temp2;
1251 		/* DELTA: One in-core extent is split in three. */
1252 		temp = PREV.br_startoff;
1253 		temp2 = PREV.br_blockcount;
1254 		break;
1255 
1256 	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1257 	case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1258 	case MASK2(LEFT_FILLING, RIGHT_CONTIG):
1259 	case MASK2(RIGHT_FILLING, LEFT_CONTIG):
1260 	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1261 	case MASK(LEFT_CONTIG):
1262 	case MASK(RIGHT_CONTIG):
1263 		/*
1264 		 * These cases are all impossible.
1265 		 */
1266 		ASSERT(0);
1267 	}
1268 	*curp = cur;
1269 	if (delta) {
1270 		temp2 += temp;
1271 		if (delta->xed_startoff > temp)
1272 			delta->xed_startoff = temp;
1273 		if (delta->xed_blockcount < temp2)
1274 			delta->xed_blockcount = temp2;
1275 	}
1276 done:
1277 	*logflagsp = rval;
1278 	return error;
1279 #undef	LEFT
1280 #undef	RIGHT
1281 #undef	PREV
1282 #undef	MASK
1283 #undef	MASK2
1284 #undef	MASK3
1285 #undef	MASK4
1286 #undef	STATE_SET
1287 #undef	STATE_TEST
1288 #undef	STATE_SET_TEST
1289 #undef	SWITCH_STATE
1290 }
1291 
1292 /*
1293  * Called by xfs_bmap_add_extent to handle cases converting an unwritten
1294  * allocation to a real allocation or vice versa.
1295  */
1296 STATIC int				/* error */
xfs_bmap_add_extent_unwritten_real(xfs_inode_t * ip,xfs_extnum_t idx,xfs_btree_cur_t ** curp,xfs_bmbt_irec_t * new,int * logflagsp,xfs_extdelta_t * delta)1297 xfs_bmap_add_extent_unwritten_real(
1298 	xfs_inode_t		*ip,	/* incore inode pointer */
1299 	xfs_extnum_t		idx,	/* extent number to update/insert */
1300 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
1301 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
1302 	int			*logflagsp, /* inode logging flags */
1303 	xfs_extdelta_t		*delta) /* Change made to incore extents */
1304 {
1305 	xfs_btree_cur_t		*cur;	/* btree cursor */
1306 	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */
1307 	int			error;	/* error return value */
1308 	int			i;	/* temp state */
1309 	xfs_ifork_t		*ifp;	/* inode fork pointer */
1310 	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
1311 	xfs_exntst_t		newext;	/* new extent state */
1312 	xfs_exntst_t		oldext;	/* old extent state */
1313 	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
1314 					/* left is 0, right is 1, prev is 2 */
1315 	int			rval=0;	/* return value (logging flags) */
1316 	int			state = 0;/* state bits, accessed thru macros */
1317 	xfs_filblks_t		temp=0;
1318 	xfs_filblks_t		temp2=0;
1319 	enum {				/* bit number definitions for state */
1320 		LEFT_CONTIG,	RIGHT_CONTIG,
1321 		LEFT_FILLING,	RIGHT_FILLING,
1322 		LEFT_DELAY,	RIGHT_DELAY,
1323 		LEFT_VALID,	RIGHT_VALID
1324 	};
1325 
1326 #define	LEFT		r[0]
1327 #define	RIGHT		r[1]
1328 #define	PREV		r[2]
1329 #define	MASK(b)		(1 << (b))
1330 #define	MASK2(a,b)	(MASK(a) | MASK(b))
1331 #define	MASK3(a,b,c)	(MASK2(a,b) | MASK(c))
1332 #define	MASK4(a,b,c,d)	(MASK3(a,b,c) | MASK(d))
1333 #define	STATE_SET(b,v)	((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
1334 #define	STATE_TEST(b)	(state & MASK(b))
1335 #define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
1336 				       ((state &= ~MASK(b)), 0))
1337 #define	SWITCH_STATE		\
1338 	(state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
1339 
1340 	/*
1341 	 * Set up a bunch of variables to make the tests simpler.
1342 	 */
1343 	error = 0;
1344 	cur = *curp;
1345 	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1346 	ep = xfs_iext_get_ext(ifp, idx);
1347 	xfs_bmbt_get_all(ep, &PREV);
1348 	newext = new->br_state;
1349 	oldext = (newext == XFS_EXT_UNWRITTEN) ?
1350 		XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
1351 	ASSERT(PREV.br_state == oldext);
1352 	new_endoff = new->br_startoff + new->br_blockcount;
1353 	ASSERT(PREV.br_startoff <= new->br_startoff);
1354 	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
1355 	/*
1356 	 * Set flags determining what part of the previous oldext allocation
1357 	 * extent is being replaced by a newext allocation.
1358 	 */
1359 	STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
1360 	STATE_SET(RIGHT_FILLING,
1361 		PREV.br_startoff + PREV.br_blockcount == new_endoff);
1362 	/*
1363 	 * Check and set flags if this segment has a left neighbor.
1364 	 * Don't set contiguous if the combined extent would be too large.
1365 	 */
1366 	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
1367 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
1368 		STATE_SET(LEFT_DELAY, isnullstartblock(LEFT.br_startblock));
1369 	}
1370 	STATE_SET(LEFT_CONTIG,
1371 		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
1372 		LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
1373 		LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
1374 		LEFT.br_state == newext &&
1375 		LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
1376 	/*
1377 	 * Check and set flags if this segment has a right neighbor.
1378 	 * Don't set contiguous if the combined extent would be too large.
1379 	 * Also check for all-three-contiguous being too large.
1380 	 */
1381 	if (STATE_SET_TEST(RIGHT_VALID,
1382 			idx <
1383 			ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
1384 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
1385 		STATE_SET(RIGHT_DELAY, isnullstartblock(RIGHT.br_startblock));
1386 	}
1387 	STATE_SET(RIGHT_CONTIG,
1388 		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
1389 		new_endoff == RIGHT.br_startoff &&
1390 		new->br_startblock + new->br_blockcount ==
1391 		    RIGHT.br_startblock &&
1392 		newext == RIGHT.br_state &&
1393 		new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
1394 		((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
1395 		  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
1396 		 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
1397 		     <= MAXEXTLEN));
1398 	/*
1399 	 * Switch out based on the FILLING and CONTIG state bits.
1400 	 */
1401 	switch (SWITCH_STATE) {
1402 
1403 	case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1404 		/*
1405 		 * Setting all of a previous oldext extent to newext.
1406 		 * The left and right neighbors are both contiguous with new.
1407 		 */
1408 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
1409 			XFS_DATA_FORK);
1410 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1411 			LEFT.br_blockcount + PREV.br_blockcount +
1412 			RIGHT.br_blockcount);
1413 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
1414 			XFS_DATA_FORK);
1415 		XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
1416 		xfs_iext_remove(ifp, idx, 2);
1417 		ip->i_df.if_lastex = idx - 1;
1418 		ip->i_d.di_nextents -= 2;
1419 		if (cur == NULL)
1420 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1421 		else {
1422 			rval = XFS_ILOG_CORE;
1423 			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1424 					RIGHT.br_startblock,
1425 					RIGHT.br_blockcount, &i)))
1426 				goto done;
1427 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1428 			if ((error = xfs_btree_delete(cur, &i)))
1429 				goto done;
1430 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1431 			if ((error = xfs_btree_decrement(cur, 0, &i)))
1432 				goto done;
1433 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1434 			if ((error = xfs_btree_delete(cur, &i)))
1435 				goto done;
1436 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1437 			if ((error = xfs_btree_decrement(cur, 0, &i)))
1438 				goto done;
1439 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1440 			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1441 				LEFT.br_startblock,
1442 				LEFT.br_blockcount + PREV.br_blockcount +
1443 				RIGHT.br_blockcount, LEFT.br_state)))
1444 				goto done;
1445 		}
1446 		/* DELTA: Three in-core extents are replaced by one. */
1447 		temp = LEFT.br_startoff;
1448 		temp2 = LEFT.br_blockcount +
1449 			PREV.br_blockcount +
1450 			RIGHT.br_blockcount;
1451 		break;
1452 
1453 	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
1454 		/*
1455 		 * Setting all of a previous oldext extent to newext.
1456 		 * The left neighbor is contiguous, the right is not.
1457 		 */
1458 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
1459 			XFS_DATA_FORK);
1460 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1461 			LEFT.br_blockcount + PREV.br_blockcount);
1462 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
1463 			XFS_DATA_FORK);
1464 		ip->i_df.if_lastex = idx - 1;
1465 		XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
1466 		xfs_iext_remove(ifp, idx, 1);
1467 		ip->i_d.di_nextents--;
1468 		if (cur == NULL)
1469 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1470 		else {
1471 			rval = XFS_ILOG_CORE;
1472 			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1473 					PREV.br_startblock, PREV.br_blockcount,
1474 					&i)))
1475 				goto done;
1476 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1477 			if ((error = xfs_btree_delete(cur, &i)))
1478 				goto done;
1479 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1480 			if ((error = xfs_btree_decrement(cur, 0, &i)))
1481 				goto done;
1482 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1483 			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1484 				LEFT.br_startblock,
1485 				LEFT.br_blockcount + PREV.br_blockcount,
1486 				LEFT.br_state)))
1487 				goto done;
1488 		}
1489 		/* DELTA: Two in-core extents are replaced by one. */
1490 		temp = LEFT.br_startoff;
1491 		temp2 = LEFT.br_blockcount +
1492 			PREV.br_blockcount;
1493 		break;
1494 
1495 	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
1496 		/*
1497 		 * Setting all of a previous oldext extent to newext.
1498 		 * The right neighbor is contiguous, the left is not.
1499 		 */
1500 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,
1501 			XFS_DATA_FORK);
1502 		xfs_bmbt_set_blockcount(ep,
1503 			PREV.br_blockcount + RIGHT.br_blockcount);
1504 		xfs_bmbt_set_state(ep, newext);
1505 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,
1506 			XFS_DATA_FORK);
1507 		ip->i_df.if_lastex = idx;
1508 		XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
1509 		xfs_iext_remove(ifp, idx + 1, 1);
1510 		ip->i_d.di_nextents--;
1511 		if (cur == NULL)
1512 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1513 		else {
1514 			rval = XFS_ILOG_CORE;
1515 			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1516 					RIGHT.br_startblock,
1517 					RIGHT.br_blockcount, &i)))
1518 				goto done;
1519 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1520 			if ((error = xfs_btree_delete(cur, &i)))
1521 				goto done;
1522 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1523 			if ((error = xfs_btree_decrement(cur, 0, &i)))
1524 				goto done;
1525 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1526 			if ((error = xfs_bmbt_update(cur, new->br_startoff,
1527 				new->br_startblock,
1528 				new->br_blockcount + RIGHT.br_blockcount,
1529 				newext)))
1530 				goto done;
1531 		}
1532 		/* DELTA: Two in-core extents are replaced by one. */
1533 		temp = PREV.br_startoff;
1534 		temp2 = PREV.br_blockcount +
1535 			RIGHT.br_blockcount;
1536 		break;
1537 
1538 	case MASK2(LEFT_FILLING, RIGHT_FILLING):
1539 		/*
1540 		 * Setting all of a previous oldext extent to newext.
1541 		 * Neither the left nor right neighbors are contiguous with
1542 		 * the new one.
1543 		 */
1544 		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,
1545 			XFS_DATA_FORK);
1546 		xfs_bmbt_set_state(ep, newext);
1547 		XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,
1548 			XFS_DATA_FORK);
1549 		ip->i_df.if_lastex = idx;
1550 		if (cur == NULL)
1551 			rval = XFS_ILOG_DEXT;
1552 		else {
1553 			rval = 0;
1554 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1555 					new->br_startblock, new->br_blockcount,
1556 					&i)))
1557 				goto done;
1558 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1559 			if ((error = xfs_bmbt_update(cur, new->br_startoff,
1560 				new->br_startblock, new->br_blockcount,
1561 				newext)))
1562 				goto done;
1563 		}
1564 		/* DELTA: The in-core extent described by new changed type. */
1565 		temp = new->br_startoff;
1566 		temp2 = new->br_blockcount;
1567 		break;
1568 
1569 	case MASK2(LEFT_FILLING, LEFT_CONTIG):
1570 		/*
1571 		 * Setting the first part of a previous oldext extent to newext.
1572 		 * The left neighbor is contiguous.
1573 		 */
1574 		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,
1575 			XFS_DATA_FORK);
1576 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1577 			LEFT.br_blockcount + new->br_blockcount);
1578 		xfs_bmbt_set_startoff(ep,
1579 			PREV.br_startoff + new->br_blockcount);
1580 		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,
1581 			XFS_DATA_FORK);
1582 		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,
1583 			XFS_DATA_FORK);
1584 		xfs_bmbt_set_startblock(ep,
1585 			new->br_startblock + new->br_blockcount);
1586 		xfs_bmbt_set_blockcount(ep,
1587 			PREV.br_blockcount - new->br_blockcount);
1588 		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,
1589 			XFS_DATA_FORK);
1590 		ip->i_df.if_lastex = idx - 1;
1591 		if (cur == NULL)
1592 			rval = XFS_ILOG_DEXT;
1593 		else {
1594 			rval = 0;
1595 			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1596 					PREV.br_startblock, PREV.br_blockcount,
1597 					&i)))
1598 				goto done;
1599 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1600 			if ((error = xfs_bmbt_update(cur,
1601 				PREV.br_startoff + new->br_blockcount,
1602 				PREV.br_startblock + new->br_blockcount,
1603 				PREV.br_blockcount - new->br_blockcount,
1604 				oldext)))
1605 				goto done;
1606 			if ((error = xfs_btree_decrement(cur, 0, &i)))
1607 				goto done;
1608 			if (xfs_bmbt_update(cur, LEFT.br_startoff,
1609 				LEFT.br_startblock,
1610 				LEFT.br_blockcount + new->br_blockcount,
1611 				LEFT.br_state))
1612 				goto done;
1613 		}
1614 		/* DELTA: The boundary between two in-core extents moved. */
1615 		temp = LEFT.br_startoff;
1616 		temp2 = LEFT.br_blockcount +
1617 			PREV.br_blockcount;
1618 		break;
1619 
1620 	case MASK(LEFT_FILLING):
1621 		/*
1622 		 * Setting the first part of a previous oldext extent to newext.
1623 		 * The left neighbor is not contiguous.
1624 		 */
1625 		XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1626 		ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
1627 		xfs_bmbt_set_startoff(ep, new_endoff);
1628 		xfs_bmbt_set_blockcount(ep,
1629 			PREV.br_blockcount - new->br_blockcount);
1630 		xfs_bmbt_set_startblock(ep,
1631 			new->br_startblock + new->br_blockcount);
1632 		XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1633 		XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
1634 			XFS_DATA_FORK);
1635 		xfs_iext_insert(ifp, idx, 1, new);
1636 		ip->i_df.if_lastex = idx;
1637 		ip->i_d.di_nextents++;
1638 		if (cur == NULL)
1639 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1640 		else {
1641 			rval = XFS_ILOG_CORE;
1642 			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1643 					PREV.br_startblock, PREV.br_blockcount,
1644 					&i)))
1645 				goto done;
1646 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1647 			if ((error = xfs_bmbt_update(cur,
1648 				PREV.br_startoff + new->br_blockcount,
1649 				PREV.br_startblock + new->br_blockcount,
1650 				PREV.br_blockcount - new->br_blockcount,
1651 				oldext)))
1652 				goto done;
1653 			cur->bc_rec.b = *new;
1654 			if ((error = xfs_btree_insert(cur, &i)))
1655 				goto done;
1656 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1657 		}
1658 		/* DELTA: One in-core extent is split in two. */
1659 		temp = PREV.br_startoff;
1660 		temp2 = PREV.br_blockcount;
1661 		break;
1662 
1663 	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
1664 		/*
1665 		 * Setting the last part of a previous oldext extent to newext.
1666 		 * The right neighbor is contiguous with the new allocation.
1667 		 */
1668 		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,
1669 			XFS_DATA_FORK);
1670 		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,
1671 			XFS_DATA_FORK);
1672 		xfs_bmbt_set_blockcount(ep,
1673 			PREV.br_blockcount - new->br_blockcount);
1674 		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,
1675 			XFS_DATA_FORK);
1676 		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
1677 			new->br_startoff, new->br_startblock,
1678 			new->br_blockcount + RIGHT.br_blockcount, newext);
1679 		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,
1680 			XFS_DATA_FORK);
1681 		ip->i_df.if_lastex = idx + 1;
1682 		if (cur == NULL)
1683 			rval = XFS_ILOG_DEXT;
1684 		else {
1685 			rval = 0;
1686 			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1687 					PREV.br_startblock,
1688 					PREV.br_blockcount, &i)))
1689 				goto done;
1690 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1691 			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1692 				PREV.br_startblock,
1693 				PREV.br_blockcount - new->br_blockcount,
1694 				oldext)))
1695 				goto done;
1696 			if ((error = xfs_btree_increment(cur, 0, &i)))
1697 				goto done;
1698 			if ((error = xfs_bmbt_update(cur, new->br_startoff,
1699 				new->br_startblock,
1700 				new->br_blockcount + RIGHT.br_blockcount,
1701 				newext)))
1702 				goto done;
1703 		}
1704 		/* DELTA: The boundary between two in-core extents moved. */
1705 		temp = PREV.br_startoff;
1706 		temp2 = PREV.br_blockcount +
1707 			RIGHT.br_blockcount;
1708 		break;
1709 
1710 	case MASK(RIGHT_FILLING):
1711 		/*
1712 		 * Setting the last part of a previous oldext extent to newext.
1713 		 * The right neighbor is not contiguous.
1714 		 */
1715 		XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1716 		xfs_bmbt_set_blockcount(ep,
1717 			PREV.br_blockcount - new->br_blockcount);
1718 		XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1719 		XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
1720 			XFS_DATA_FORK);
1721 		xfs_iext_insert(ifp, idx + 1, 1, new);
1722 		ip->i_df.if_lastex = idx + 1;
1723 		ip->i_d.di_nextents++;
1724 		if (cur == NULL)
1725 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1726 		else {
1727 			rval = XFS_ILOG_CORE;
1728 			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1729 					PREV.br_startblock, PREV.br_blockcount,
1730 					&i)))
1731 				goto done;
1732 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1733 			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1734 				PREV.br_startblock,
1735 				PREV.br_blockcount - new->br_blockcount,
1736 				oldext)))
1737 				goto done;
1738 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1739 					new->br_startblock, new->br_blockcount,
1740 					&i)))
1741 				goto done;
1742 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1743 			cur->bc_rec.b.br_state = XFS_EXT_NORM;
1744 			if ((error = xfs_btree_insert(cur, &i)))
1745 				goto done;
1746 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1747 		}
1748 		/* DELTA: One in-core extent is split in two. */
1749 		temp = PREV.br_startoff;
1750 		temp2 = PREV.br_blockcount;
1751 		break;
1752 
1753 	case 0:
1754 		/*
1755 		 * Setting the middle part of a previous oldext extent to
1756 		 * newext.  Contiguity is impossible here.
1757 		 * One extent becomes three extents.
1758 		 */
1759 		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
1760 		xfs_bmbt_set_blockcount(ep,
1761 			new->br_startoff - PREV.br_startoff);
1762 		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
1763 		r[0] = *new;
1764 		r[1].br_startoff = new_endoff;
1765 		r[1].br_blockcount =
1766 			PREV.br_startoff + PREV.br_blockcount - new_endoff;
1767 		r[1].br_startblock = new->br_startblock + new->br_blockcount;
1768 		r[1].br_state = oldext;
1769 		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
1770 			XFS_DATA_FORK);
1771 		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
1772 		ip->i_df.if_lastex = idx + 1;
1773 		ip->i_d.di_nextents += 2;
1774 		if (cur == NULL)
1775 			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1776 		else {
1777 			rval = XFS_ILOG_CORE;
1778 			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1779 					PREV.br_startblock, PREV.br_blockcount,
1780 					&i)))
1781 				goto done;
1782 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1783 			/* new right extent - oldext */
1784 			if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
1785 				r[1].br_startblock, r[1].br_blockcount,
1786 				r[1].br_state)))
1787 				goto done;
1788 			/* new left extent - oldext */
1789 			cur->bc_rec.b = PREV;
1790 			cur->bc_rec.b.br_blockcount =
1791 				new->br_startoff - PREV.br_startoff;
1792 			if ((error = xfs_btree_insert(cur, &i)))
1793 				goto done;
1794 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1795 			/*
1796 			 * Reset the cursor to the position of the new extent
1797 			 * we are about to insert as we can't trust it after
1798 			 * the previous insert.
1799 			 */
1800 			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1801 					new->br_startblock, new->br_blockcount,
1802 					&i)))
1803 				goto done;
1804 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1805 			/* new middle extent - newext */
1806 			cur->bc_rec.b.br_state = new->br_state;
1807 			if ((error = xfs_btree_insert(cur, &i)))
1808 				goto done;
1809 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1810 		}
1811 		/* DELTA: One in-core extent is split in three. */
1812 		temp = PREV.br_startoff;
1813 		temp2 = PREV.br_blockcount;
1814 		break;
1815 
1816 	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1817 	case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1818 	case MASK2(LEFT_FILLING, RIGHT_CONTIG):
1819 	case MASK2(RIGHT_FILLING, LEFT_CONTIG):
1820 	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1821 	case MASK(LEFT_CONTIG):
1822 	case MASK(RIGHT_CONTIG):
1823 		/*
1824 		 * These cases are all impossible.
1825 		 */
1826 		ASSERT(0);
1827 	}
1828 	*curp = cur;
1829 	if (delta) {
1830 		temp2 += temp;
1831 		if (delta->xed_startoff > temp)
1832 			delta->xed_startoff = temp;
1833 		if (delta->xed_blockcount < temp2)
1834 			delta->xed_blockcount = temp2;
1835 	}
1836 done:
1837 	*logflagsp = rval;
1838 	return error;
1839 #undef	LEFT
1840 #undef	RIGHT
1841 #undef	PREV
1842 #undef	MASK
1843 #undef	MASK2
1844 #undef	MASK3
1845 #undef	MASK4
1846 #undef	STATE_SET
1847 #undef	STATE_TEST
1848 #undef	STATE_SET_TEST
1849 #undef	SWITCH_STATE
1850 }
1851 
1852 /*
1853  * Called by xfs_bmap_add_extent to handle cases converting a hole
1854  * to a delayed allocation.
1855  */
1856 /*ARGSUSED*/
1857 STATIC int				/* error */
xfs_bmap_add_extent_hole_delay(xfs_inode_t * ip,xfs_extnum_t idx,xfs_bmbt_irec_t * new,int * logflagsp,xfs_extdelta_t * delta,int rsvd)1858 xfs_bmap_add_extent_hole_delay(
1859 	xfs_inode_t		*ip,	/* incore inode pointer */
1860 	xfs_extnum_t		idx,	/* extent number to update/insert */
1861 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
1862 	int			*logflagsp, /* inode logging flags */
1863 	xfs_extdelta_t		*delta, /* Change made to incore extents */
1864 	int			rsvd)		/* OK to allocate reserved blocks */
1865 {
1866 	xfs_bmbt_rec_host_t	*ep;	/* extent record for idx */
1867 	xfs_ifork_t		*ifp;	/* inode fork pointer */
1868 	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
1869 	xfs_filblks_t		newlen=0;	/* new indirect size */
1870 	xfs_filblks_t		oldlen=0;	/* old indirect size */
1871 	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
1872 	int			state;  /* state bits, accessed thru macros */
1873 	xfs_filblks_t		temp=0;	/* temp for indirect calculations */
1874 	xfs_filblks_t		temp2=0;
1875 	enum {				/* bit number definitions for state */
1876 		LEFT_CONTIG,	RIGHT_CONTIG,
1877 		LEFT_DELAY,	RIGHT_DELAY,
1878 		LEFT_VALID,	RIGHT_VALID
1879 	};
1880 
1881 #define	MASK(b)			(1 << (b))
1882 #define	MASK2(a,b)		(MASK(a) | MASK(b))
1883 #define	STATE_SET(b,v)		((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
1884 #define	STATE_TEST(b)		(state & MASK(b))
1885 #define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
1886 				       ((state &= ~MASK(b)), 0))
1887 #define	SWITCH_STATE		(state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
1888 
1889 	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1890 	ep = xfs_iext_get_ext(ifp, idx);
1891 	state = 0;
1892 	ASSERT(isnullstartblock(new->br_startblock));
1893 	/*
1894 	 * Check and set flags if this segment has a left neighbor
1895 	 */
1896 	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
1897 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
1898 		STATE_SET(LEFT_DELAY, isnullstartblock(left.br_startblock));
1899 	}
1900 	/*
1901 	 * Check and set flags if the current (right) segment exists.
1902 	 * If it doesn't exist, we're converting the hole at end-of-file.
1903 	 */
1904 	if (STATE_SET_TEST(RIGHT_VALID,
1905 			   idx <
1906 			   ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
1907 		xfs_bmbt_get_all(ep, &right);
1908 		STATE_SET(RIGHT_DELAY, isnullstartblock(right.br_startblock));
1909 	}
1910 	/*
1911 	 * Set contiguity flags on the left and right neighbors.
1912 	 * Don't let extents get too large, even if the pieces are contiguous.
1913 	 */
1914 	STATE_SET(LEFT_CONTIG,
1915 		STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) &&
1916 		left.br_startoff + left.br_blockcount == new->br_startoff &&
1917 		left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
1918 	STATE_SET(RIGHT_CONTIG,
1919 		STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) &&
1920 		new->br_startoff + new->br_blockcount == right.br_startoff &&
1921 		new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
1922 		(!STATE_TEST(LEFT_CONTIG) ||
1923 		 (left.br_blockcount + new->br_blockcount +
1924 		     right.br_blockcount <= MAXEXTLEN)));
1925 	/*
1926 	 * Switch out based on the contiguity flags.
1927 	 */
1928 	switch (SWITCH_STATE) {
1929 
1930 	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1931 		/*
1932 		 * New allocation is contiguous with delayed allocations
1933 		 * on the left and on the right.
1934 		 * Merge all three into a single extent record.
1935 		 */
1936 		temp = left.br_blockcount + new->br_blockcount +
1937 			right.br_blockcount;
1938 		XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
1939 			XFS_DATA_FORK);
1940 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
1941 		oldlen = startblockval(left.br_startblock) +
1942 			startblockval(new->br_startblock) +
1943 			startblockval(right.br_startblock);
1944 		newlen = xfs_bmap_worst_indlen(ip, temp);
1945 		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
1946 			nullstartblock((int)newlen));
1947 		XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
1948 			XFS_DATA_FORK);
1949 		XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);
1950 		xfs_iext_remove(ifp, idx, 1);
1951 		ip->i_df.if_lastex = idx - 1;
1952 		/* DELTA: Two in-core extents were replaced by one. */
1953 		temp2 = temp;
1954 		temp = left.br_startoff;
1955 		break;
1956 
1957 	case MASK(LEFT_CONTIG):
1958 		/*
1959 		 * New allocation is contiguous with a delayed allocation
1960 		 * on the left.
1961 		 * Merge the new allocation with the left neighbor.
1962 		 */
1963 		temp = left.br_blockcount + new->br_blockcount;
1964 		XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,
1965 			XFS_DATA_FORK);
1966 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
1967 		oldlen = startblockval(left.br_startblock) +
1968 			startblockval(new->br_startblock);
1969 		newlen = xfs_bmap_worst_indlen(ip, temp);
1970 		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
1971 			nullstartblock((int)newlen));
1972 		XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,
1973 			XFS_DATA_FORK);
1974 		ip->i_df.if_lastex = idx - 1;
1975 		/* DELTA: One in-core extent grew into a hole. */
1976 		temp2 = temp;
1977 		temp = left.br_startoff;
1978 		break;
1979 
1980 	case MASK(RIGHT_CONTIG):
1981 		/*
1982 		 * New allocation is contiguous with a delayed allocation
1983 		 * on the right.
1984 		 * Merge the new allocation with the right neighbor.
1985 		 */
1986 		XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);
1987 		temp = new->br_blockcount + right.br_blockcount;
1988 		oldlen = startblockval(new->br_startblock) +
1989 			startblockval(right.br_startblock);
1990 		newlen = xfs_bmap_worst_indlen(ip, temp);
1991 		xfs_bmbt_set_allf(ep, new->br_startoff,
1992 			nullstartblock((int)newlen), temp, right.br_state);
1993 		XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);
1994 		ip->i_df.if_lastex = idx;
1995 		/* DELTA: One in-core extent grew into a hole. */
1996 		temp2 = temp;
1997 		temp = new->br_startoff;
1998 		break;
1999 
2000 	case 0:
2001 		/*
2002 		 * New allocation is not contiguous with another
2003 		 * delayed allocation.
2004 		 * Insert a new entry.
2005 		 */
2006 		oldlen = newlen = 0;
2007 		XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,
2008 			XFS_DATA_FORK);
2009 		xfs_iext_insert(ifp, idx, 1, new);
2010 		ip->i_df.if_lastex = idx;
2011 		/* DELTA: A new in-core extent was added in a hole. */
2012 		temp2 = new->br_blockcount;
2013 		temp = new->br_startoff;
2014 		break;
2015 	}
2016 	if (oldlen != newlen) {
2017 		ASSERT(oldlen > newlen);
2018 		xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
2019 			(int64_t)(oldlen - newlen), rsvd);
2020 		/*
2021 		 * Nothing to do for disk quota accounting here.
2022 		 */
2023 	}
2024 	if (delta) {
2025 		temp2 += temp;
2026 		if (delta->xed_startoff > temp)
2027 			delta->xed_startoff = temp;
2028 		if (delta->xed_blockcount < temp2)
2029 			delta->xed_blockcount = temp2;
2030 	}
2031 	*logflagsp = 0;
2032 	return 0;
2033 #undef	MASK
2034 #undef	MASK2
2035 #undef	STATE_SET
2036 #undef	STATE_TEST
2037 #undef	STATE_SET_TEST
2038 #undef	SWITCH_STATE
2039 }
2040 
2041 /*
2042  * Called by xfs_bmap_add_extent to handle cases converting a hole
2043  * to a real allocation.
2044  */
2045 STATIC int				/* error */
xfs_bmap_add_extent_hole_real(xfs_inode_t * ip,xfs_extnum_t idx,xfs_btree_cur_t * cur,xfs_bmbt_irec_t * new,int * logflagsp,xfs_extdelta_t * delta,int whichfork)2046 xfs_bmap_add_extent_hole_real(
2047 	xfs_inode_t		*ip,	/* incore inode pointer */
2048 	xfs_extnum_t		idx,	/* extent number to update/insert */
2049 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
2050 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
2051 	int			*logflagsp, /* inode logging flags */
2052 	xfs_extdelta_t		*delta, /* Change made to incore extents */
2053 	int			whichfork) /* data or attr fork */
2054 {
2055 	xfs_bmbt_rec_host_t	*ep;	/* pointer to extent entry ins. point */
2056 	int			error;	/* error return value */
2057 	int			i;	/* temp state */
2058 	xfs_ifork_t		*ifp;	/* inode fork pointer */
2059 	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
2060 	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
2061 	int			rval=0;	/* return value (logging flags) */
2062 	int			state;	/* state bits, accessed thru macros */
2063 	xfs_filblks_t		temp=0;
2064 	xfs_filblks_t		temp2=0;
2065 	enum {				/* bit number definitions for state */
2066 		LEFT_CONTIG,	RIGHT_CONTIG,
2067 		LEFT_DELAY,	RIGHT_DELAY,
2068 		LEFT_VALID,	RIGHT_VALID
2069 	};
2070 
2071 #define	MASK(b)			(1 << (b))
2072 #define	MASK2(a,b)		(MASK(a) | MASK(b))
2073 #define	STATE_SET(b,v)		((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
2074 #define	STATE_TEST(b)		(state & MASK(b))
2075 #define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
2076 				       ((state &= ~MASK(b)), 0))
2077 #define	SWITCH_STATE		(state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
2078 
2079 	ifp = XFS_IFORK_PTR(ip, whichfork);
2080 	ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
2081 	ep = xfs_iext_get_ext(ifp, idx);
2082 	state = 0;
2083 	/*
2084 	 * Check and set flags if this segment has a left neighbor.
2085 	 */
2086 	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
2087 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
2088 		STATE_SET(LEFT_DELAY, isnullstartblock(left.br_startblock));
2089 	}
2090 	/*
2091 	 * Check and set flags if this segment has a current value.
2092 	 * Not true if we're inserting into the "hole" at eof.
2093 	 */
2094 	if (STATE_SET_TEST(RIGHT_VALID,
2095 			   idx <
2096 			   ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
2097 		xfs_bmbt_get_all(ep, &right);
2098 		STATE_SET(RIGHT_DELAY, isnullstartblock(right.br_startblock));
2099 	}
2100 	/*
2101 	 * We're inserting a real allocation between "left" and "right".
2102 	 * Set the contiguity flags.  Don't let extents get too large.
2103 	 */
2104 	STATE_SET(LEFT_CONTIG,
2105 		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
2106 		left.br_startoff + left.br_blockcount == new->br_startoff &&
2107 		left.br_startblock + left.br_blockcount == new->br_startblock &&
2108 		left.br_state == new->br_state &&
2109 		left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
2110 	STATE_SET(RIGHT_CONTIG,
2111 		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
2112 		new->br_startoff + new->br_blockcount == right.br_startoff &&
2113 		new->br_startblock + new->br_blockcount ==
2114 		    right.br_startblock &&
2115 		new->br_state == right.br_state &&
2116 		new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
2117 		(!STATE_TEST(LEFT_CONTIG) ||
2118 		 left.br_blockcount + new->br_blockcount +
2119 		     right.br_blockcount <= MAXEXTLEN));
2120 
2121 	error = 0;
2122 	/*
2123 	 * Select which case we're in here, and implement it.
2124 	 */
2125 	switch (SWITCH_STATE) {
2126 
2127 	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
2128 		/*
2129 		 * New allocation is contiguous with real allocations on the
2130 		 * left and on the right.
2131 		 * Merge all three into a single extent record.
2132 		 */
2133 		XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
2134 			whichfork);
2135 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
2136 			left.br_blockcount + new->br_blockcount +
2137 			right.br_blockcount);
2138 		XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
2139 			whichfork);
2140 		XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, whichfork);
2141 		xfs_iext_remove(ifp, idx, 1);
2142 		ifp->if_lastex = idx - 1;
2143 		XFS_IFORK_NEXT_SET(ip, whichfork,
2144 			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
2145 		if (cur == NULL) {
2146 			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
2147 		} else {
2148 			rval = XFS_ILOG_CORE;
2149 			if ((error = xfs_bmbt_lookup_eq(cur,
2150 					right.br_startoff,
2151 					right.br_startblock,
2152 					right.br_blockcount, &i)))
2153 				goto done;
2154 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2155 			if ((error = xfs_btree_delete(cur, &i)))
2156 				goto done;
2157 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2158 			if ((error = xfs_btree_decrement(cur, 0, &i)))
2159 				goto done;
2160 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2161 			if ((error = xfs_bmbt_update(cur, left.br_startoff,
2162 					left.br_startblock,
2163 					left.br_blockcount +
2164 						new->br_blockcount +
2165 						right.br_blockcount,
2166 					left.br_state)))
2167 				goto done;
2168 		}
2169 		/* DELTA: Two in-core extents were replaced by one. */
2170 		temp = left.br_startoff;
2171 		temp2 = left.br_blockcount +
2172 			new->br_blockcount +
2173 			right.br_blockcount;
2174 		break;
2175 
2176 	case MASK(LEFT_CONTIG):
2177 		/*
2178 		 * New allocation is contiguous with a real allocation
2179 		 * on the left.
2180 		 * Merge the new allocation with the left neighbor.
2181 		 */
2182 		XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, whichfork);
2183 		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
2184 			left.br_blockcount + new->br_blockcount);
2185 		XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, whichfork);
2186 		ifp->if_lastex = idx - 1;
2187 		if (cur == NULL) {
2188 			rval = xfs_ilog_fext(whichfork);
2189 		} else {
2190 			rval = 0;
2191 			if ((error = xfs_bmbt_lookup_eq(cur,
2192 					left.br_startoff,
2193 					left.br_startblock,
2194 					left.br_blockcount, &i)))
2195 				goto done;
2196 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2197 			if ((error = xfs_bmbt_update(cur, left.br_startoff,
2198 					left.br_startblock,
2199 					left.br_blockcount +
2200 						new->br_blockcount,
2201 					left.br_state)))
2202 				goto done;
2203 		}
2204 		/* DELTA: One in-core extent grew. */
2205 		temp = left.br_startoff;
2206 		temp2 = left.br_blockcount +
2207 			new->br_blockcount;
2208 		break;
2209 
2210 	case MASK(RIGHT_CONTIG):
2211 		/*
2212 		 * New allocation is contiguous with a real allocation
2213 		 * on the right.
2214 		 * Merge the new allocation with the right neighbor.
2215 		 */
2216 		XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, whichfork);
2217 		xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
2218 			new->br_blockcount + right.br_blockcount,
2219 			right.br_state);
2220 		XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, whichfork);
2221 		ifp->if_lastex = idx;
2222 		if (cur == NULL) {
2223 			rval = xfs_ilog_fext(whichfork);
2224 		} else {
2225 			rval = 0;
2226 			if ((error = xfs_bmbt_lookup_eq(cur,
2227 					right.br_startoff,
2228 					right.br_startblock,
2229 					right.br_blockcount, &i)))
2230 				goto done;
2231 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2232 			if ((error = xfs_bmbt_update(cur, new->br_startoff,
2233 					new->br_startblock,
2234 					new->br_blockcount +
2235 						right.br_blockcount,
2236 					right.br_state)))
2237 				goto done;
2238 		}
2239 		/* DELTA: One in-core extent grew. */
2240 		temp = new->br_startoff;
2241 		temp2 = new->br_blockcount +
2242 			right.br_blockcount;
2243 		break;
2244 
2245 	case 0:
2246 		/*
2247 		 * New allocation is not contiguous with another
2248 		 * real allocation.
2249 		 * Insert a new entry.
2250 		 */
2251 		XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, whichfork);
2252 		xfs_iext_insert(ifp, idx, 1, new);
2253 		ifp->if_lastex = idx;
2254 		XFS_IFORK_NEXT_SET(ip, whichfork,
2255 			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
2256 		if (cur == NULL) {
2257 			rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
2258 		} else {
2259 			rval = XFS_ILOG_CORE;
2260 			if ((error = xfs_bmbt_lookup_eq(cur,
2261 					new->br_startoff,
2262 					new->br_startblock,
2263 					new->br_blockcount, &i)))
2264 				goto done;
2265 			XFS_WANT_CORRUPTED_GOTO(i == 0, done);
2266 			cur->bc_rec.b.br_state = new->br_state;
2267 			if ((error = xfs_btree_insert(cur, &i)))
2268 				goto done;
2269 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2270 		}
2271 		/* DELTA: A new extent was added in a hole. */
2272 		temp = new->br_startoff;
2273 		temp2 = new->br_blockcount;
2274 		break;
2275 	}
2276 	if (delta) {
2277 		temp2 += temp;
2278 		if (delta->xed_startoff > temp)
2279 			delta->xed_startoff = temp;
2280 		if (delta->xed_blockcount < temp2)
2281 			delta->xed_blockcount = temp2;
2282 	}
2283 done:
2284 	*logflagsp = rval;
2285 	return error;
2286 #undef	MASK
2287 #undef	MASK2
2288 #undef	STATE_SET
2289 #undef	STATE_TEST
2290 #undef	STATE_SET_TEST
2291 #undef	SWITCH_STATE
2292 }
2293 
2294 /*
2295  * Adjust the size of the new extent based on di_extsize and rt extsize.
2296  */
2297 STATIC int
xfs_bmap_extsize_align(xfs_mount_t * mp,xfs_bmbt_irec_t * gotp,xfs_bmbt_irec_t * prevp,xfs_extlen_t extsz,int rt,int eof,int delay,int convert,xfs_fileoff_t * offp,xfs_extlen_t * lenp)2298 xfs_bmap_extsize_align(
2299 	xfs_mount_t	*mp,
2300 	xfs_bmbt_irec_t	*gotp,		/* next extent pointer */
2301 	xfs_bmbt_irec_t	*prevp,		/* previous extent pointer */
2302 	xfs_extlen_t	extsz,		/* align to this extent size */
2303 	int		rt,		/* is this a realtime inode? */
2304 	int		eof,		/* is extent at end-of-file? */
2305 	int		delay,		/* creating delalloc extent? */
2306 	int		convert,	/* overwriting unwritten extent? */
2307 	xfs_fileoff_t	*offp,		/* in/out: aligned offset */
2308 	xfs_extlen_t	*lenp)		/* in/out: aligned length */
2309 {
2310 	xfs_fileoff_t	orig_off;	/* original offset */
2311 	xfs_extlen_t	orig_alen;	/* original length */
2312 	xfs_fileoff_t	orig_end;	/* original off+len */
2313 	xfs_fileoff_t	nexto;		/* next file offset */
2314 	xfs_fileoff_t	prevo;		/* previous file offset */
2315 	xfs_fileoff_t	align_off;	/* temp for offset */
2316 	xfs_extlen_t	align_alen;	/* temp for length */
2317 	xfs_extlen_t	temp;		/* temp for calculations */
2318 
2319 	if (convert)
2320 		return 0;
2321 
2322 	orig_off = align_off = *offp;
2323 	orig_alen = align_alen = *lenp;
2324 	orig_end = orig_off + orig_alen;
2325 
2326 	/*
2327 	 * If this request overlaps an existing extent, then don't
2328 	 * attempt to perform any additional alignment.
2329 	 */
2330 	if (!delay && !eof &&
2331 	    (orig_off >= gotp->br_startoff) &&
2332 	    (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
2333 		return 0;
2334 	}
2335 
2336 	/*
2337 	 * If the file offset is unaligned vs. the extent size
2338 	 * we need to align it.  This will be possible unless
2339 	 * the file was previously written with a kernel that didn't
2340 	 * perform this alignment, or if a truncate shot us in the
2341 	 * foot.
2342 	 */
2343 	temp = do_mod(orig_off, extsz);
2344 	if (temp) {
2345 		align_alen += temp;
2346 		align_off -= temp;
2347 	}
2348 	/*
2349 	 * Same adjustment for the end of the requested area.
2350 	 */
2351 	if ((temp = (align_alen % extsz))) {
2352 		align_alen += extsz - temp;
2353 	}
2354 	/*
2355 	 * If the previous block overlaps with this proposed allocation
2356 	 * then move the start forward without adjusting the length.
2357 	 */
2358 	if (prevp->br_startoff != NULLFILEOFF) {
2359 		if (prevp->br_startblock == HOLESTARTBLOCK)
2360 			prevo = prevp->br_startoff;
2361 		else
2362 			prevo = prevp->br_startoff + prevp->br_blockcount;
2363 	} else
2364 		prevo = 0;
2365 	if (align_off != orig_off && align_off < prevo)
2366 		align_off = prevo;
2367 	/*
2368 	 * If the next block overlaps with this proposed allocation
2369 	 * then move the start back without adjusting the length,
2370 	 * but not before offset 0.
2371 	 * This may of course make the start overlap previous block,
2372 	 * and if we hit the offset 0 limit then the next block
2373 	 * can still overlap too.
2374 	 */
2375 	if (!eof && gotp->br_startoff != NULLFILEOFF) {
2376 		if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
2377 		    (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
2378 			nexto = gotp->br_startoff + gotp->br_blockcount;
2379 		else
2380 			nexto = gotp->br_startoff;
2381 	} else
2382 		nexto = NULLFILEOFF;
2383 	if (!eof &&
2384 	    align_off + align_alen != orig_end &&
2385 	    align_off + align_alen > nexto)
2386 		align_off = nexto > align_alen ? nexto - align_alen : 0;
2387 	/*
2388 	 * If we're now overlapping the next or previous extent that
2389 	 * means we can't fit an extsz piece in this hole.  Just move
2390 	 * the start forward to the first valid spot and set
2391 	 * the length so we hit the end.
2392 	 */
2393 	if (align_off != orig_off && align_off < prevo)
2394 		align_off = prevo;
2395 	if (align_off + align_alen != orig_end &&
2396 	    align_off + align_alen > nexto &&
2397 	    nexto != NULLFILEOFF) {
2398 		ASSERT(nexto > prevo);
2399 		align_alen = nexto - align_off;
2400 	}
2401 
2402 	/*
2403 	 * If realtime, and the result isn't a multiple of the realtime
2404 	 * extent size we need to remove blocks until it is.
2405 	 */
2406 	if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
2407 		/*
2408 		 * We're not covering the original request, or
2409 		 * we won't be able to once we fix the length.
2410 		 */
2411 		if (orig_off < align_off ||
2412 		    orig_end > align_off + align_alen ||
2413 		    align_alen - temp < orig_alen)
2414 			return XFS_ERROR(EINVAL);
2415 		/*
2416 		 * Try to fix it by moving the start up.
2417 		 */
2418 		if (align_off + temp <= orig_off) {
2419 			align_alen -= temp;
2420 			align_off += temp;
2421 		}
2422 		/*
2423 		 * Try to fix it by moving the end in.
2424 		 */
2425 		else if (align_off + align_alen - temp >= orig_end)
2426 			align_alen -= temp;
2427 		/*
2428 		 * Set the start to the minimum then trim the length.
2429 		 */
2430 		else {
2431 			align_alen -= orig_off - align_off;
2432 			align_off = orig_off;
2433 			align_alen -= align_alen % mp->m_sb.sb_rextsize;
2434 		}
2435 		/*
2436 		 * Result doesn't cover the request, fail it.
2437 		 */
2438 		if (orig_off < align_off || orig_end > align_off + align_alen)
2439 			return XFS_ERROR(EINVAL);
2440 	} else {
2441 		ASSERT(orig_off >= align_off);
2442 		ASSERT(orig_end <= align_off + align_alen);
2443 	}
2444 
2445 #ifdef DEBUG
2446 	if (!eof && gotp->br_startoff != NULLFILEOFF)
2447 		ASSERT(align_off + align_alen <= gotp->br_startoff);
2448 	if (prevp->br_startoff != NULLFILEOFF)
2449 		ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
2450 #endif
2451 
2452 	*lenp = align_alen;
2453 	*offp = align_off;
2454 	return 0;
2455 }
2456 
2457 #define XFS_ALLOC_GAP_UNITS	4
2458 
2459 STATIC void
xfs_bmap_adjacent(xfs_bmalloca_t * ap)2460 xfs_bmap_adjacent(
2461 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
2462 {
2463 	xfs_fsblock_t	adjust;		/* adjustment to block numbers */
2464 	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
2465 	xfs_mount_t	*mp;		/* mount point structure */
2466 	int		nullfb;		/* true if ap->firstblock isn't set */
2467 	int		rt;		/* true if inode is realtime */
2468 
2469 #define	ISVALID(x,y)	\
2470 	(rt ? \
2471 		(x) < mp->m_sb.sb_rblocks : \
2472 		XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
2473 		XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
2474 		XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
2475 
2476 	mp = ap->ip->i_mount;
2477 	nullfb = ap->firstblock == NULLFSBLOCK;
2478 	rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
2479 	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2480 	/*
2481 	 * If allocating at eof, and there's a previous real block,
2482 	 * try to use it's last block as our starting point.
2483 	 */
2484 	if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF &&
2485 	    !isnullstartblock(ap->prevp->br_startblock) &&
2486 	    ISVALID(ap->prevp->br_startblock + ap->prevp->br_blockcount,
2487 		    ap->prevp->br_startblock)) {
2488 		ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount;
2489 		/*
2490 		 * Adjust for the gap between prevp and us.
2491 		 */
2492 		adjust = ap->off -
2493 			(ap->prevp->br_startoff + ap->prevp->br_blockcount);
2494 		if (adjust &&
2495 		    ISVALID(ap->rval + adjust, ap->prevp->br_startblock))
2496 			ap->rval += adjust;
2497 	}
2498 	/*
2499 	 * If not at eof, then compare the two neighbor blocks.
2500 	 * Figure out whether either one gives us a good starting point,
2501 	 * and pick the better one.
2502 	 */
2503 	else if (!ap->eof) {
2504 		xfs_fsblock_t	gotbno;		/* right side block number */
2505 		xfs_fsblock_t	gotdiff=0;	/* right side difference */
2506 		xfs_fsblock_t	prevbno;	/* left side block number */
2507 		xfs_fsblock_t	prevdiff=0;	/* left side difference */
2508 
2509 		/*
2510 		 * If there's a previous (left) block, select a requested
2511 		 * start block based on it.
2512 		 */
2513 		if (ap->prevp->br_startoff != NULLFILEOFF &&
2514 		    !isnullstartblock(ap->prevp->br_startblock) &&
2515 		    (prevbno = ap->prevp->br_startblock +
2516 			       ap->prevp->br_blockcount) &&
2517 		    ISVALID(prevbno, ap->prevp->br_startblock)) {
2518 			/*
2519 			 * Calculate gap to end of previous block.
2520 			 */
2521 			adjust = prevdiff = ap->off -
2522 				(ap->prevp->br_startoff +
2523 				 ap->prevp->br_blockcount);
2524 			/*
2525 			 * Figure the startblock based on the previous block's
2526 			 * end and the gap size.
2527 			 * Heuristic!
2528 			 * If the gap is large relative to the piece we're
2529 			 * allocating, or using it gives us an invalid block
2530 			 * number, then just use the end of the previous block.
2531 			 */
2532 			if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
2533 			    ISVALID(prevbno + prevdiff,
2534 				    ap->prevp->br_startblock))
2535 				prevbno += adjust;
2536 			else
2537 				prevdiff += adjust;
2538 			/*
2539 			 * If the firstblock forbids it, can't use it,
2540 			 * must use default.
2541 			 */
2542 			if (!rt && !nullfb &&
2543 			    XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
2544 				prevbno = NULLFSBLOCK;
2545 		}
2546 		/*
2547 		 * No previous block or can't follow it, just default.
2548 		 */
2549 		else
2550 			prevbno = NULLFSBLOCK;
2551 		/*
2552 		 * If there's a following (right) block, select a requested
2553 		 * start block based on it.
2554 		 */
2555 		if (!isnullstartblock(ap->gotp->br_startblock)) {
2556 			/*
2557 			 * Calculate gap to start of next block.
2558 			 */
2559 			adjust = gotdiff = ap->gotp->br_startoff - ap->off;
2560 			/*
2561 			 * Figure the startblock based on the next block's
2562 			 * start and the gap size.
2563 			 */
2564 			gotbno = ap->gotp->br_startblock;
2565 			/*
2566 			 * Heuristic!
2567 			 * If the gap is large relative to the piece we're
2568 			 * allocating, or using it gives us an invalid block
2569 			 * number, then just use the start of the next block
2570 			 * offset by our length.
2571 			 */
2572 			if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
2573 			    ISVALID(gotbno - gotdiff, gotbno))
2574 				gotbno -= adjust;
2575 			else if (ISVALID(gotbno - ap->alen, gotbno)) {
2576 				gotbno -= ap->alen;
2577 				gotdiff += adjust - ap->alen;
2578 			} else
2579 				gotdiff += adjust;
2580 			/*
2581 			 * If the firstblock forbids it, can't use it,
2582 			 * must use default.
2583 			 */
2584 			if (!rt && !nullfb &&
2585 			    XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
2586 				gotbno = NULLFSBLOCK;
2587 		}
2588 		/*
2589 		 * No next block, just default.
2590 		 */
2591 		else
2592 			gotbno = NULLFSBLOCK;
2593 		/*
2594 		 * If both valid, pick the better one, else the only good
2595 		 * one, else ap->rval is already set (to 0 or the inode block).
2596 		 */
2597 		if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
2598 			ap->rval = prevdiff <= gotdiff ? prevbno : gotbno;
2599 		else if (prevbno != NULLFSBLOCK)
2600 			ap->rval = prevbno;
2601 		else if (gotbno != NULLFSBLOCK)
2602 			ap->rval = gotbno;
2603 	}
2604 #undef ISVALID
2605 }
2606 
2607 STATIC int
xfs_bmap_rtalloc(xfs_bmalloca_t * ap)2608 xfs_bmap_rtalloc(
2609 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
2610 {
2611 	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
2612 	int		error;		/* error return value */
2613 	xfs_mount_t	*mp;		/* mount point structure */
2614 	xfs_extlen_t	prod = 0;	/* product factor for allocators */
2615 	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
2616 	xfs_extlen_t	align;		/* minimum allocation alignment */
2617 	xfs_rtblock_t	rtb;
2618 
2619 	mp = ap->ip->i_mount;
2620 	align = xfs_get_extsz_hint(ap->ip);
2621 	prod = align / mp->m_sb.sb_rextsize;
2622 	error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2623 					align, 1, ap->eof, 0,
2624 					ap->conv, &ap->off, &ap->alen);
2625 	if (error)
2626 		return error;
2627 	ASSERT(ap->alen);
2628 	ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
2629 
2630 	/*
2631 	 * If the offset & length are not perfectly aligned
2632 	 * then kill prod, it will just get us in trouble.
2633 	 */
2634 	if (do_mod(ap->off, align) || ap->alen % align)
2635 		prod = 1;
2636 	/*
2637 	 * Set ralen to be the actual requested length in rtextents.
2638 	 */
2639 	ralen = ap->alen / mp->m_sb.sb_rextsize;
2640 	/*
2641 	 * If the old value was close enough to MAXEXTLEN that
2642 	 * we rounded up to it, cut it back so it's valid again.
2643 	 * Note that if it's a really large request (bigger than
2644 	 * MAXEXTLEN), we don't hear about that number, and can't
2645 	 * adjust the starting point to match it.
2646 	 */
2647 	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
2648 		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
2649 	/*
2650 	 * If it's an allocation to an empty file at offset 0,
2651 	 * pick an extent that will space things out in the rt area.
2652 	 */
2653 	if (ap->eof && ap->off == 0) {
2654 		xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
2655 
2656 		error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
2657 		if (error)
2658 			return error;
2659 		ap->rval = rtx * mp->m_sb.sb_rextsize;
2660 	} else {
2661 		ap->rval = 0;
2662 	}
2663 
2664 	xfs_bmap_adjacent(ap);
2665 
2666 	/*
2667 	 * Realtime allocation, done through xfs_rtallocate_extent.
2668 	 */
2669 	atype = ap->rval == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
2670 	do_div(ap->rval, mp->m_sb.sb_rextsize);
2671 	rtb = ap->rval;
2672 	ap->alen = ralen;
2673 	if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen,
2674 				&ralen, atype, ap->wasdel, prod, &rtb)))
2675 		return error;
2676 	if (rtb == NULLFSBLOCK && prod > 1 &&
2677 	    (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1,
2678 					   ap->alen, &ralen, atype,
2679 					   ap->wasdel, 1, &rtb)))
2680 		return error;
2681 	ap->rval = rtb;
2682 	if (ap->rval != NULLFSBLOCK) {
2683 		ap->rval *= mp->m_sb.sb_rextsize;
2684 		ralen *= mp->m_sb.sb_rextsize;
2685 		ap->alen = ralen;
2686 		ap->ip->i_d.di_nblocks += ralen;
2687 		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2688 		if (ap->wasdel)
2689 			ap->ip->i_delayed_blks -= ralen;
2690 		/*
2691 		 * Adjust the disk quota also. This was reserved
2692 		 * earlier.
2693 		 */
2694 		XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
2695 			ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
2696 					XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
2697 	} else {
2698 		ap->alen = 0;
2699 	}
2700 	return 0;
2701 }
2702 
2703 STATIC int
xfs_bmap_btalloc(xfs_bmalloca_t * ap)2704 xfs_bmap_btalloc(
2705 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
2706 {
2707 	xfs_mount_t	*mp;		/* mount point structure */
2708 	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
2709 	xfs_extlen_t	align;		/* minimum allocation alignment */
2710 	xfs_agnumber_t	ag;
2711 	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
2712 	xfs_agnumber_t	startag;
2713 	xfs_alloc_arg_t	args;
2714 	xfs_extlen_t	blen;
2715 	xfs_extlen_t	delta;
2716 	xfs_extlen_t	longest;
2717 	xfs_extlen_t	need;
2718 	xfs_extlen_t	nextminlen = 0;
2719 	xfs_perag_t	*pag;
2720 	int		nullfb;		/* true if ap->firstblock isn't set */
2721 	int		isaligned;
2722 	int		notinit;
2723 	int		tryagain;
2724 	int		error;
2725 
2726 	mp = ap->ip->i_mount;
2727 	align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
2728 	if (unlikely(align)) {
2729 		error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2730 						align, 0, ap->eof, 0, ap->conv,
2731 						&ap->off, &ap->alen);
2732 		ASSERT(!error);
2733 		ASSERT(ap->alen);
2734 	}
2735 	nullfb = ap->firstblock == NULLFSBLOCK;
2736 	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2737 	if (nullfb) {
2738 		if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
2739 			ag = xfs_filestream_lookup_ag(ap->ip);
2740 			ag = (ag != NULLAGNUMBER) ? ag : 0;
2741 			ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
2742 		} else {
2743 			ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
2744 		}
2745 	} else
2746 		ap->rval = ap->firstblock;
2747 
2748 	xfs_bmap_adjacent(ap);
2749 
2750 	/*
2751 	 * If allowed, use ap->rval; otherwise must use firstblock since
2752 	 * it's in the right allocation group.
2753 	 */
2754 	if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
2755 		;
2756 	else
2757 		ap->rval = ap->firstblock;
2758 	/*
2759 	 * Normal allocation, done through xfs_alloc_vextent.
2760 	 */
2761 	tryagain = isaligned = 0;
2762 	args.tp = ap->tp;
2763 	args.mp = mp;
2764 	args.fsbno = ap->rval;
2765 	args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
2766 	args.firstblock = ap->firstblock;
2767 	blen = 0;
2768 	if (nullfb) {
2769 		if (ap->userdata && xfs_inode_is_filestream(ap->ip))
2770 			args.type = XFS_ALLOCTYPE_NEAR_BNO;
2771 		else
2772 			args.type = XFS_ALLOCTYPE_START_BNO;
2773 		args.total = ap->total;
2774 
2775 		/*
2776 		 * Search for an allocation group with a single extent
2777 		 * large enough for the request.
2778 		 *
2779 		 * If one isn't found, then adjust the minimum allocation
2780 		 * size to the largest space found.
2781 		 */
2782 		startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
2783 		if (startag == NULLAGNUMBER)
2784 			startag = ag = 0;
2785 		notinit = 0;
2786 		down_read(&mp->m_peraglock);
2787 		while (blen < ap->alen) {
2788 			pag = &mp->m_perag[ag];
2789 			if (!pag->pagf_init &&
2790 			    (error = xfs_alloc_pagf_init(mp, args.tp,
2791 				    ag, XFS_ALLOC_FLAG_TRYLOCK))) {
2792 				up_read(&mp->m_peraglock);
2793 				return error;
2794 			}
2795 			/*
2796 			 * See xfs_alloc_fix_freelist...
2797 			 */
2798 			if (pag->pagf_init) {
2799 				need = XFS_MIN_FREELIST_PAG(pag, mp);
2800 				delta = need > pag->pagf_flcount ?
2801 					need - pag->pagf_flcount : 0;
2802 				longest = (pag->pagf_longest > delta) ?
2803 					(pag->pagf_longest - delta) :
2804 					(pag->pagf_flcount > 0 ||
2805 					 pag->pagf_longest > 0);
2806 				if (blen < longest)
2807 					blen = longest;
2808 			} else
2809 				notinit = 1;
2810 
2811 			if (xfs_inode_is_filestream(ap->ip)) {
2812 				if (blen >= ap->alen)
2813 					break;
2814 
2815 				if (ap->userdata) {
2816 					/*
2817 					 * If startag is an invalid AG, we've
2818 					 * come here once before and
2819 					 * xfs_filestream_new_ag picked the
2820 					 * best currently available.
2821 					 *
2822 					 * Don't continue looping, since we
2823 					 * could loop forever.
2824 					 */
2825 					if (startag == NULLAGNUMBER)
2826 						break;
2827 
2828 					error = xfs_filestream_new_ag(ap, &ag);
2829 					if (error) {
2830 						up_read(&mp->m_peraglock);
2831 						return error;
2832 					}
2833 
2834 					/* loop again to set 'blen'*/
2835 					startag = NULLAGNUMBER;
2836 					continue;
2837 				}
2838 			}
2839 			if (++ag == mp->m_sb.sb_agcount)
2840 				ag = 0;
2841 			if (ag == startag)
2842 				break;
2843 		}
2844 		up_read(&mp->m_peraglock);
2845 		/*
2846 		 * Since the above loop did a BUF_TRYLOCK, it is
2847 		 * possible that there is space for this request.
2848 		 */
2849 		if (notinit || blen < ap->minlen)
2850 			args.minlen = ap->minlen;
2851 		/*
2852 		 * If the best seen length is less than the request
2853 		 * length, use the best as the minimum.
2854 		 */
2855 		else if (blen < ap->alen)
2856 			args.minlen = blen;
2857 		/*
2858 		 * Otherwise we've seen an extent as big as alen,
2859 		 * use that as the minimum.
2860 		 */
2861 		else
2862 			args.minlen = ap->alen;
2863 
2864 		/*
2865 		 * set the failure fallback case to look in the selected
2866 		 * AG as the stream may have moved.
2867 		 */
2868 		if (xfs_inode_is_filestream(ap->ip))
2869 			ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
2870 	} else if (ap->low) {
2871 		if (xfs_inode_is_filestream(ap->ip))
2872 			args.type = XFS_ALLOCTYPE_FIRST_AG;
2873 		else
2874 			args.type = XFS_ALLOCTYPE_START_BNO;
2875 		args.total = args.minlen = ap->minlen;
2876 	} else {
2877 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
2878 		args.total = ap->total;
2879 		args.minlen = ap->minlen;
2880 	}
2881 	/* apply extent size hints if obtained earlier */
2882 	if (unlikely(align)) {
2883 		args.prod = align;
2884 		if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
2885 			args.mod = (xfs_extlen_t)(args.prod - args.mod);
2886 	} else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) {
2887 		args.prod = 1;
2888 		args.mod = 0;
2889 	} else {
2890 		args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog;
2891 		if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
2892 			args.mod = (xfs_extlen_t)(args.prod - args.mod);
2893 	}
2894 	/*
2895 	 * If we are not low on available data blocks, and the
2896 	 * underlying logical volume manager is a stripe, and
2897 	 * the file offset is zero then try to allocate data
2898 	 * blocks on stripe unit boundary.
2899 	 * NOTE: ap->aeof is only set if the allocation length
2900 	 * is >= the stripe unit and the allocation offset is
2901 	 * at the end of file.
2902 	 */
2903 	if (!ap->low && ap->aeof) {
2904 		if (!ap->off) {
2905 			args.alignment = mp->m_dalign;
2906 			atype = args.type;
2907 			isaligned = 1;
2908 			/*
2909 			 * Adjust for alignment
2910 			 */
2911 			if (blen > args.alignment && blen <= ap->alen)
2912 				args.minlen = blen - args.alignment;
2913 			args.minalignslop = 0;
2914 		} else {
2915 			/*
2916 			 * First try an exact bno allocation.
2917 			 * If it fails then do a near or start bno
2918 			 * allocation with alignment turned on.
2919 			 */
2920 			atype = args.type;
2921 			tryagain = 1;
2922 			args.type = XFS_ALLOCTYPE_THIS_BNO;
2923 			args.alignment = 1;
2924 			/*
2925 			 * Compute the minlen+alignment for the
2926 			 * next case.  Set slop so that the value
2927 			 * of minlen+alignment+slop doesn't go up
2928 			 * between the calls.
2929 			 */
2930 			if (blen > mp->m_dalign && blen <= ap->alen)
2931 				nextminlen = blen - mp->m_dalign;
2932 			else
2933 				nextminlen = args.minlen;
2934 			if (nextminlen + mp->m_dalign > args.minlen + 1)
2935 				args.minalignslop =
2936 					nextminlen + mp->m_dalign -
2937 					args.minlen - 1;
2938 			else
2939 				args.minalignslop = 0;
2940 		}
2941 	} else {
2942 		args.alignment = 1;
2943 		args.minalignslop = 0;
2944 	}
2945 	args.minleft = ap->minleft;
2946 	args.wasdel = ap->wasdel;
2947 	args.isfl = 0;
2948 	args.userdata = ap->userdata;
2949 	if ((error = xfs_alloc_vextent(&args)))
2950 		return error;
2951 	if (tryagain && args.fsbno == NULLFSBLOCK) {
2952 		/*
2953 		 * Exact allocation failed. Now try with alignment
2954 		 * turned on.
2955 		 */
2956 		args.type = atype;
2957 		args.fsbno = ap->rval;
2958 		args.alignment = mp->m_dalign;
2959 		args.minlen = nextminlen;
2960 		args.minalignslop = 0;
2961 		isaligned = 1;
2962 		if ((error = xfs_alloc_vextent(&args)))
2963 			return error;
2964 	}
2965 	if (isaligned && args.fsbno == NULLFSBLOCK) {
2966 		/*
2967 		 * allocation failed, so turn off alignment and
2968 		 * try again.
2969 		 */
2970 		args.type = atype;
2971 		args.fsbno = ap->rval;
2972 		args.alignment = 0;
2973 		if ((error = xfs_alloc_vextent(&args)))
2974 			return error;
2975 	}
2976 	if (args.fsbno == NULLFSBLOCK && nullfb &&
2977 	    args.minlen > ap->minlen) {
2978 		args.minlen = ap->minlen;
2979 		args.type = XFS_ALLOCTYPE_START_BNO;
2980 		args.fsbno = ap->rval;
2981 		if ((error = xfs_alloc_vextent(&args)))
2982 			return error;
2983 	}
2984 	if (args.fsbno == NULLFSBLOCK && nullfb) {
2985 		args.fsbno = 0;
2986 		args.type = XFS_ALLOCTYPE_FIRST_AG;
2987 		args.total = ap->minlen;
2988 		args.minleft = 0;
2989 		if ((error = xfs_alloc_vextent(&args)))
2990 			return error;
2991 		ap->low = 1;
2992 	}
2993 	if (args.fsbno != NULLFSBLOCK) {
2994 		ap->firstblock = ap->rval = args.fsbno;
2995 		ASSERT(nullfb || fb_agno == args.agno ||
2996 		       (ap->low && fb_agno < args.agno));
2997 		ap->alen = args.len;
2998 		ap->ip->i_d.di_nblocks += args.len;
2999 		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
3000 		if (ap->wasdel)
3001 			ap->ip->i_delayed_blks -= args.len;
3002 		/*
3003 		 * Adjust the disk quota also. This was reserved
3004 		 * earlier.
3005 		 */
3006 		XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
3007 			ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
3008 					XFS_TRANS_DQ_BCOUNT,
3009 			(long) args.len);
3010 	} else {
3011 		ap->rval = NULLFSBLOCK;
3012 		ap->alen = 0;
3013 	}
3014 	return 0;
3015 }
3016 
3017 /*
3018  * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
3019  * It figures out where to ask the underlying allocator to put the new extent.
3020  */
3021 STATIC int
xfs_bmap_alloc(xfs_bmalloca_t * ap)3022 xfs_bmap_alloc(
3023 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
3024 {
3025 	if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)
3026 		return xfs_bmap_rtalloc(ap);
3027 	return xfs_bmap_btalloc(ap);
3028 }
3029 
3030 /*
3031  * Transform a btree format file with only one leaf node, where the
3032  * extents list will fit in the inode, into an extents format file.
3033  * Since the file extents are already in-core, all we have to do is
3034  * give up the space for the btree root and pitch the leaf block.
3035  */
3036 STATIC int				/* error */
xfs_bmap_btree_to_extents(xfs_trans_t * tp,xfs_inode_t * ip,xfs_btree_cur_t * cur,int * logflagsp,int whichfork)3037 xfs_bmap_btree_to_extents(
3038 	xfs_trans_t		*tp,	/* transaction pointer */
3039 	xfs_inode_t		*ip,	/* incore inode pointer */
3040 	xfs_btree_cur_t		*cur,	/* btree cursor */
3041 	int			*logflagsp, /* inode logging flags */
3042 	int			whichfork)  /* data or attr fork */
3043 {
3044 	/* REFERENCED */
3045 	struct xfs_btree_block	*cblock;/* child btree block */
3046 	xfs_fsblock_t		cbno;	/* child block number */
3047 	xfs_buf_t		*cbp;	/* child block's buffer */
3048 	int			error;	/* error return value */
3049 	xfs_ifork_t		*ifp;	/* inode fork data */
3050 	xfs_mount_t		*mp;	/* mount point structure */
3051 	__be64			*pp;	/* ptr to block address */
3052 	struct xfs_btree_block	*rblock;/* root btree block */
3053 
3054 	mp = ip->i_mount;
3055 	ifp = XFS_IFORK_PTR(ip, whichfork);
3056 	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
3057 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
3058 	rblock = ifp->if_broot;
3059 	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
3060 	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
3061 	ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
3062 	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes);
3063 	cbno = be64_to_cpu(*pp);
3064 	*logflagsp = 0;
3065 #ifdef DEBUG
3066 	if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
3067 		return error;
3068 #endif
3069 	if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
3070 			XFS_BMAP_BTREE_REF)))
3071 		return error;
3072 	cblock = XFS_BUF_TO_BLOCK(cbp);
3073 	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
3074 		return error;
3075 	xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
3076 	ip->i_d.di_nblocks--;
3077 	XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
3078 	xfs_trans_binval(tp, cbp);
3079 	if (cur->bc_bufs[0] == cbp)
3080 		cur->bc_bufs[0] = NULL;
3081 	xfs_iroot_realloc(ip, -1, whichfork);
3082 	ASSERT(ifp->if_broot == NULL);
3083 	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
3084 	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
3085 	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
3086 	return 0;
3087 }
3088 
3089 /*
3090  * Called by xfs_bmapi to update file extent records and the btree
3091  * after removing space (or undoing a delayed allocation).
3092  */
3093 STATIC int				/* error */
xfs_bmap_del_extent(xfs_inode_t * ip,xfs_trans_t * tp,xfs_extnum_t idx,xfs_bmap_free_t * flist,xfs_btree_cur_t * cur,xfs_bmbt_irec_t * del,int * logflagsp,xfs_extdelta_t * delta,int whichfork,int rsvd)3094 xfs_bmap_del_extent(
3095 	xfs_inode_t		*ip,	/* incore inode pointer */
3096 	xfs_trans_t		*tp,	/* current transaction pointer */
3097 	xfs_extnum_t		idx,	/* extent number to update/delete */
3098 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
3099 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
3100 	xfs_bmbt_irec_t		*del,	/* data to remove from extents */
3101 	int			*logflagsp, /* inode logging flags */
3102 	xfs_extdelta_t		*delta, /* Change made to incore extents */
3103 	int			whichfork, /* data or attr fork */
3104 	int			rsvd)	/* OK to allocate reserved blocks */
3105 {
3106 	xfs_filblks_t		da_new;	/* new delay-alloc indirect blocks */
3107 	xfs_filblks_t		da_old;	/* old delay-alloc indirect blocks */
3108 	xfs_fsblock_t		del_endblock=0;	/* first block past del */
3109 	xfs_fileoff_t		del_endoff;	/* first offset past del */
3110 	int			delay;	/* current block is delayed allocated */
3111 	int			do_fx;	/* free extent at end of routine */
3112 	xfs_bmbt_rec_host_t	*ep;	/* current extent entry pointer */
3113 	int			error;	/* error return value */
3114 	int			flags;	/* inode logging flags */
3115 	xfs_bmbt_irec_t		got;	/* current extent entry */
3116 	xfs_fileoff_t		got_endoff;	/* first offset past got */
3117 	int			i;	/* temp state */
3118 	xfs_ifork_t		*ifp;	/* inode fork pointer */
3119 	xfs_mount_t		*mp;	/* mount structure */
3120 	xfs_filblks_t		nblks;	/* quota/sb block count */
3121 	xfs_bmbt_irec_t		new;	/* new record to be inserted */
3122 	/* REFERENCED */
3123 	uint			qfield;	/* quota field to update */
3124 	xfs_filblks_t		temp;	/* for indirect length calculations */
3125 	xfs_filblks_t		temp2;	/* for indirect length calculations */
3126 
3127 	XFS_STATS_INC(xs_del_exlist);
3128 	mp = ip->i_mount;
3129 	ifp = XFS_IFORK_PTR(ip, whichfork);
3130 	ASSERT((idx >= 0) && (idx < ifp->if_bytes /
3131 		(uint)sizeof(xfs_bmbt_rec_t)));
3132 	ASSERT(del->br_blockcount > 0);
3133 	ep = xfs_iext_get_ext(ifp, idx);
3134 	xfs_bmbt_get_all(ep, &got);
3135 	ASSERT(got.br_startoff <= del->br_startoff);
3136 	del_endoff = del->br_startoff + del->br_blockcount;
3137 	got_endoff = got.br_startoff + got.br_blockcount;
3138 	ASSERT(got_endoff >= del_endoff);
3139 	delay = isnullstartblock(got.br_startblock);
3140 	ASSERT(isnullstartblock(del->br_startblock) == delay);
3141 	flags = 0;
3142 	qfield = 0;
3143 	error = 0;
3144 	/*
3145 	 * If deleting a real allocation, must free up the disk space.
3146 	 */
3147 	if (!delay) {
3148 		flags = XFS_ILOG_CORE;
3149 		/*
3150 		 * Realtime allocation.  Free it and record di_nblocks update.
3151 		 */
3152 		if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
3153 			xfs_fsblock_t	bno;
3154 			xfs_filblks_t	len;
3155 
3156 			ASSERT(do_mod(del->br_blockcount,
3157 				      mp->m_sb.sb_rextsize) == 0);
3158 			ASSERT(do_mod(del->br_startblock,
3159 				      mp->m_sb.sb_rextsize) == 0);
3160 			bno = del->br_startblock;
3161 			len = del->br_blockcount;
3162 			do_div(bno, mp->m_sb.sb_rextsize);
3163 			do_div(len, mp->m_sb.sb_rextsize);
3164 			if ((error = xfs_rtfree_extent(ip->i_transp, bno,
3165 					(xfs_extlen_t)len)))
3166 				goto done;
3167 			do_fx = 0;
3168 			nblks = len * mp->m_sb.sb_rextsize;
3169 			qfield = XFS_TRANS_DQ_RTBCOUNT;
3170 		}
3171 		/*
3172 		 * Ordinary allocation.
3173 		 */
3174 		else {
3175 			do_fx = 1;
3176 			nblks = del->br_blockcount;
3177 			qfield = XFS_TRANS_DQ_BCOUNT;
3178 		}
3179 		/*
3180 		 * Set up del_endblock and cur for later.
3181 		 */
3182 		del_endblock = del->br_startblock + del->br_blockcount;
3183 		if (cur) {
3184 			if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
3185 					got.br_startblock, got.br_blockcount,
3186 					&i)))
3187 				goto done;
3188 			XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3189 		}
3190 		da_old = da_new = 0;
3191 	} else {
3192 		da_old = startblockval(got.br_startblock);
3193 		da_new = 0;
3194 		nblks = 0;
3195 		do_fx = 0;
3196 	}
3197 	/*
3198 	 * Set flag value to use in switch statement.
3199 	 * Left-contig is 2, right-contig is 1.
3200 	 */
3201 	switch (((got.br_startoff == del->br_startoff) << 1) |
3202 		(got_endoff == del_endoff)) {
3203 	case 3:
3204 		/*
3205 		 * Matches the whole extent.  Delete the entry.
3206 		 */
3207 		XFS_BMAP_TRACE_DELETE("3", ip, idx, 1, whichfork);
3208 		xfs_iext_remove(ifp, idx, 1);
3209 		ifp->if_lastex = idx;
3210 		if (delay)
3211 			break;
3212 		XFS_IFORK_NEXT_SET(ip, whichfork,
3213 			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
3214 		flags |= XFS_ILOG_CORE;
3215 		if (!cur) {
3216 			flags |= xfs_ilog_fext(whichfork);
3217 			break;
3218 		}
3219 		if ((error = xfs_btree_delete(cur, &i)))
3220 			goto done;
3221 		XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3222 		break;
3223 
3224 	case 2:
3225 		/*
3226 		 * Deleting the first part of the extent.
3227 		 */
3228 		XFS_BMAP_TRACE_PRE_UPDATE("2", ip, idx, whichfork);
3229 		xfs_bmbt_set_startoff(ep, del_endoff);
3230 		temp = got.br_blockcount - del->br_blockcount;
3231 		xfs_bmbt_set_blockcount(ep, temp);
3232 		ifp->if_lastex = idx;
3233 		if (delay) {
3234 			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
3235 				da_old);
3236 			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
3237 			XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx,
3238 				whichfork);
3239 			da_new = temp;
3240 			break;
3241 		}
3242 		xfs_bmbt_set_startblock(ep, del_endblock);
3243 		XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx, whichfork);
3244 		if (!cur) {
3245 			flags |= xfs_ilog_fext(whichfork);
3246 			break;
3247 		}
3248 		if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
3249 				got.br_blockcount - del->br_blockcount,
3250 				got.br_state)))
3251 			goto done;
3252 		break;
3253 
3254 	case 1:
3255 		/*
3256 		 * Deleting the last part of the extent.
3257 		 */
3258 		temp = got.br_blockcount - del->br_blockcount;
3259 		XFS_BMAP_TRACE_PRE_UPDATE("1", ip, idx, whichfork);
3260 		xfs_bmbt_set_blockcount(ep, temp);
3261 		ifp->if_lastex = idx;
3262 		if (delay) {
3263 			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
3264 				da_old);
3265 			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
3266 			XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx,
3267 				whichfork);
3268 			da_new = temp;
3269 			break;
3270 		}
3271 		XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx, whichfork);
3272 		if (!cur) {
3273 			flags |= xfs_ilog_fext(whichfork);
3274 			break;
3275 		}
3276 		if ((error = xfs_bmbt_update(cur, got.br_startoff,
3277 				got.br_startblock,
3278 				got.br_blockcount - del->br_blockcount,
3279 				got.br_state)))
3280 			goto done;
3281 		break;
3282 
3283 	case 0:
3284 		/*
3285 		 * Deleting the middle of the extent.
3286 		 */
3287 		temp = del->br_startoff - got.br_startoff;
3288 		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, whichfork);
3289 		xfs_bmbt_set_blockcount(ep, temp);
3290 		new.br_startoff = del_endoff;
3291 		temp2 = got_endoff - del_endoff;
3292 		new.br_blockcount = temp2;
3293 		new.br_state = got.br_state;
3294 		if (!delay) {
3295 			new.br_startblock = del_endblock;
3296 			flags |= XFS_ILOG_CORE;
3297 			if (cur) {
3298 				if ((error = xfs_bmbt_update(cur,
3299 						got.br_startoff,
3300 						got.br_startblock, temp,
3301 						got.br_state)))
3302 					goto done;
3303 				if ((error = xfs_btree_increment(cur, 0, &i)))
3304 					goto done;
3305 				cur->bc_rec.b = new;
3306 				error = xfs_btree_insert(cur, &i);
3307 				if (error && error != ENOSPC)
3308 					goto done;
3309 				/*
3310 				 * If get no-space back from btree insert,
3311 				 * it tried a split, and we have a zero
3312 				 * block reservation.
3313 				 * Fix up our state and return the error.
3314 				 */
3315 				if (error == ENOSPC) {
3316 					/*
3317 					 * Reset the cursor, don't trust
3318 					 * it after any insert operation.
3319 					 */
3320 					if ((error = xfs_bmbt_lookup_eq(cur,
3321 							got.br_startoff,
3322 							got.br_startblock,
3323 							temp, &i)))
3324 						goto done;
3325 					XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3326 					/*
3327 					 * Update the btree record back
3328 					 * to the original value.
3329 					 */
3330 					if ((error = xfs_bmbt_update(cur,
3331 							got.br_startoff,
3332 							got.br_startblock,
3333 							got.br_blockcount,
3334 							got.br_state)))
3335 						goto done;
3336 					/*
3337 					 * Reset the extent record back
3338 					 * to the original value.
3339 					 */
3340 					xfs_bmbt_set_blockcount(ep,
3341 						got.br_blockcount);
3342 					flags = 0;
3343 					error = XFS_ERROR(ENOSPC);
3344 					goto done;
3345 				}
3346 				XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3347 			} else
3348 				flags |= xfs_ilog_fext(whichfork);
3349 			XFS_IFORK_NEXT_SET(ip, whichfork,
3350 				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
3351 		} else {
3352 			ASSERT(whichfork == XFS_DATA_FORK);
3353 			temp = xfs_bmap_worst_indlen(ip, temp);
3354 			xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
3355 			temp2 = xfs_bmap_worst_indlen(ip, temp2);
3356 			new.br_startblock = nullstartblock((int)temp2);
3357 			da_new = temp + temp2;
3358 			while (da_new > da_old) {
3359 				if (temp) {
3360 					temp--;
3361 					da_new--;
3362 					xfs_bmbt_set_startblock(ep,
3363 						nullstartblock((int)temp));
3364 				}
3365 				if (da_new == da_old)
3366 					break;
3367 				if (temp2) {
3368 					temp2--;
3369 					da_new--;
3370 					new.br_startblock =
3371 						nullstartblock((int)temp2);
3372 				}
3373 			}
3374 		}
3375 		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, whichfork);
3376 		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 1, &new, NULL,
3377 			whichfork);
3378 		xfs_iext_insert(ifp, idx + 1, 1, &new);
3379 		ifp->if_lastex = idx + 1;
3380 		break;
3381 	}
3382 	/*
3383 	 * If we need to, add to list of extents to delete.
3384 	 */
3385 	if (do_fx)
3386 		xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
3387 			mp);
3388 	/*
3389 	 * Adjust inode # blocks in the file.
3390 	 */
3391 	if (nblks)
3392 		ip->i_d.di_nblocks -= nblks;
3393 	/*
3394 	 * Adjust quota data.
3395 	 */
3396 	if (qfield)
3397 		XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, qfield, (long)-nblks);
3398 
3399 	/*
3400 	 * Account for change in delayed indirect blocks.
3401 	 * Nothing to do for disk quota accounting here.
3402 	 */
3403 	ASSERT(da_old >= da_new);
3404 	if (da_old > da_new)
3405 		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
3406 			rsvd);
3407 	if (delta) {
3408 		/* DELTA: report the original extent. */
3409 		if (delta->xed_startoff > got.br_startoff)
3410 			delta->xed_startoff = got.br_startoff;
3411 		if (delta->xed_blockcount < got.br_startoff+got.br_blockcount)
3412 			delta->xed_blockcount = got.br_startoff +
3413 							got.br_blockcount;
3414 	}
3415 done:
3416 	*logflagsp = flags;
3417 	return error;
3418 }
3419 
3420 /*
3421  * Remove the entry "free" from the free item list.  Prev points to the
3422  * previous entry, unless "free" is the head of the list.
3423  */
3424 STATIC void
xfs_bmap_del_free(xfs_bmap_free_t * flist,xfs_bmap_free_item_t * prev,xfs_bmap_free_item_t * free)3425 xfs_bmap_del_free(
3426 	xfs_bmap_free_t		*flist,	/* free item list header */
3427 	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
3428 	xfs_bmap_free_item_t	*free)	/* list item to be freed */
3429 {
3430 	if (prev)
3431 		prev->xbfi_next = free->xbfi_next;
3432 	else
3433 		flist->xbf_first = free->xbfi_next;
3434 	flist->xbf_count--;
3435 	kmem_zone_free(xfs_bmap_free_item_zone, free);
3436 }
3437 
3438 /*
3439  * Convert an extents-format file into a btree-format file.
3440  * The new file will have a root block (in the inode) and a single child block.
3441  */
3442 STATIC int					/* error */
xfs_bmap_extents_to_btree(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fsblock_t * firstblock,xfs_bmap_free_t * flist,xfs_btree_cur_t ** curp,int wasdel,int * logflagsp,int whichfork)3443 xfs_bmap_extents_to_btree(
3444 	xfs_trans_t		*tp,		/* transaction pointer */
3445 	xfs_inode_t		*ip,		/* incore inode pointer */
3446 	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
3447 	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
3448 	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
3449 	int			wasdel,		/* converting a delayed alloc */
3450 	int			*logflagsp,	/* inode logging flags */
3451 	int			whichfork)	/* data or attr fork */
3452 {
3453 	struct xfs_btree_block	*ablock;	/* allocated (child) bt block */
3454 	xfs_buf_t		*abp;		/* buffer for ablock */
3455 	xfs_alloc_arg_t		args;		/* allocation arguments */
3456 	xfs_bmbt_rec_t		*arp;		/* child record pointer */
3457 	struct xfs_btree_block	*block;		/* btree root block */
3458 	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
3459 	xfs_bmbt_rec_host_t	*ep;		/* extent record pointer */
3460 	int			error;		/* error return value */
3461 	xfs_extnum_t		i, cnt;		/* extent record index */
3462 	xfs_ifork_t		*ifp;		/* inode fork pointer */
3463 	xfs_bmbt_key_t		*kp;		/* root block key pointer */
3464 	xfs_mount_t		*mp;		/* mount structure */
3465 	xfs_extnum_t		nextents;	/* number of file extents */
3466 	xfs_bmbt_ptr_t		*pp;		/* root block address pointer */
3467 
3468 	ifp = XFS_IFORK_PTR(ip, whichfork);
3469 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
3470 	ASSERT(ifp->if_ext_max ==
3471 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
3472 	/*
3473 	 * Make space in the inode incore.
3474 	 */
3475 	xfs_iroot_realloc(ip, 1, whichfork);
3476 	ifp->if_flags |= XFS_IFBROOT;
3477 
3478 	/*
3479 	 * Fill in the root.
3480 	 */
3481 	block = ifp->if_broot;
3482 	block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
3483 	block->bb_level = cpu_to_be16(1);
3484 	block->bb_numrecs = cpu_to_be16(1);
3485 	block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
3486 	block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
3487 
3488 	/*
3489 	 * Need a cursor.  Can't allocate until bb_level is filled in.
3490 	 */
3491 	mp = ip->i_mount;
3492 	cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
3493 	cur->bc_private.b.firstblock = *firstblock;
3494 	cur->bc_private.b.flist = flist;
3495 	cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
3496 	/*
3497 	 * Convert to a btree with two levels, one record in root.
3498 	 */
3499 	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
3500 	args.tp = tp;
3501 	args.mp = mp;
3502 	args.firstblock = *firstblock;
3503 	if (*firstblock == NULLFSBLOCK) {
3504 		args.type = XFS_ALLOCTYPE_START_BNO;
3505 		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
3506 	} else if (flist->xbf_low) {
3507 		args.type = XFS_ALLOCTYPE_START_BNO;
3508 		args.fsbno = *firstblock;
3509 	} else {
3510 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
3511 		args.fsbno = *firstblock;
3512 	}
3513 	args.minlen = args.maxlen = args.prod = 1;
3514 	args.total = args.minleft = args.alignment = args.mod = args.isfl =
3515 		args.minalignslop = 0;
3516 	args.wasdel = wasdel;
3517 	*logflagsp = 0;
3518 	if ((error = xfs_alloc_vextent(&args))) {
3519 		xfs_iroot_realloc(ip, -1, whichfork);
3520 		xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
3521 		return error;
3522 	}
3523 	/*
3524 	 * Allocation can't fail, the space was reserved.
3525 	 */
3526 	ASSERT(args.fsbno != NULLFSBLOCK);
3527 	ASSERT(*firstblock == NULLFSBLOCK ||
3528 	       args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
3529 	       (flist->xbf_low &&
3530 		args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
3531 	*firstblock = cur->bc_private.b.firstblock = args.fsbno;
3532 	cur->bc_private.b.allocated++;
3533 	ip->i_d.di_nblocks++;
3534 	XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
3535 	abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
3536 	/*
3537 	 * Fill in the child block.
3538 	 */
3539 	ablock = XFS_BUF_TO_BLOCK(abp);
3540 	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
3541 	ablock->bb_level = 0;
3542 	ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
3543 	ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
3544 	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
3545 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3546 	for (cnt = i = 0; i < nextents; i++) {
3547 		ep = xfs_iext_get_ext(ifp, i);
3548 		if (!isnullstartblock(xfs_bmbt_get_startblock(ep))) {
3549 			arp->l0 = cpu_to_be64(ep->l0);
3550 			arp->l1 = cpu_to_be64(ep->l1);
3551 			arp++; cnt++;
3552 		}
3553 	}
3554 	ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
3555 	xfs_btree_set_numrecs(ablock, cnt);
3556 
3557 	/*
3558 	 * Fill in the root key and pointer.
3559 	 */
3560 	kp = XFS_BMBT_KEY_ADDR(mp, block, 1);
3561 	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
3562 	kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
3563 	pp = XFS_BMBT_PTR_ADDR(mp, block, 1, xfs_bmbt_get_maxrecs(cur,
3564 						be16_to_cpu(block->bb_level)));
3565 	*pp = cpu_to_be64(args.fsbno);
3566 
3567 	/*
3568 	 * Do all this logging at the end so that
3569 	 * the root is at the right level.
3570 	 */
3571 	xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
3572 	xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
3573 	ASSERT(*curp == NULL);
3574 	*curp = cur;
3575 	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork);
3576 	return 0;
3577 }
3578 
3579 /*
3580  * Helper routine to reset inode di_forkoff field when switching
3581  * attribute fork from local to extent format - we reset it where
3582  * possible to make space available for inline data fork extents.
3583  */
3584 STATIC void
xfs_bmap_forkoff_reset(xfs_mount_t * mp,xfs_inode_t * ip,int whichfork)3585 xfs_bmap_forkoff_reset(
3586 	xfs_mount_t	*mp,
3587 	xfs_inode_t	*ip,
3588 	int		whichfork)
3589 {
3590 	if (whichfork == XFS_ATTR_FORK &&
3591 	    (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
3592 	    (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
3593 	    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
3594 	    ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
3595 		ip->i_d.di_forkoff = mp->m_attroffset >> 3;
3596 		ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
3597 					(uint)sizeof(xfs_bmbt_rec_t);
3598 		ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) /
3599 					(uint)sizeof(xfs_bmbt_rec_t);
3600 	}
3601 }
3602 
3603 /*
3604  * Convert a local file to an extents file.
3605  * This code is out of bounds for data forks of regular files,
3606  * since the file data needs to get logged so things will stay consistent.
3607  * (The bmap-level manipulations are ok, though).
3608  */
3609 STATIC int				/* error */
xfs_bmap_local_to_extents(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fsblock_t * firstblock,xfs_extlen_t total,int * logflagsp,int whichfork)3610 xfs_bmap_local_to_extents(
3611 	xfs_trans_t	*tp,		/* transaction pointer */
3612 	xfs_inode_t	*ip,		/* incore inode pointer */
3613 	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
3614 	xfs_extlen_t	total,		/* total blocks needed by transaction */
3615 	int		*logflagsp,	/* inode logging flags */
3616 	int		whichfork)	/* data or attr fork */
3617 {
3618 	int		error;		/* error return value */
3619 	int		flags;		/* logging flags returned */
3620 	xfs_ifork_t	*ifp;		/* inode fork pointer */
3621 
3622 	/*
3623 	 * We don't want to deal with the case of keeping inode data inline yet.
3624 	 * So sending the data fork of a regular inode is invalid.
3625 	 */
3626 	ASSERT(!((ip->i_d.di_mode & S_IFMT) == S_IFREG &&
3627 		 whichfork == XFS_DATA_FORK));
3628 	ifp = XFS_IFORK_PTR(ip, whichfork);
3629 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
3630 	flags = 0;
3631 	error = 0;
3632 	if (ifp->if_bytes) {
3633 		xfs_alloc_arg_t	args;	/* allocation arguments */
3634 		xfs_buf_t	*bp;	/* buffer for extent block */
3635 		xfs_bmbt_rec_host_t *ep;/* extent record pointer */
3636 
3637 		args.tp = tp;
3638 		args.mp = ip->i_mount;
3639 		args.firstblock = *firstblock;
3640 		ASSERT((ifp->if_flags &
3641 			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
3642 		/*
3643 		 * Allocate a block.  We know we need only one, since the
3644 		 * file currently fits in an inode.
3645 		 */
3646 		if (*firstblock == NULLFSBLOCK) {
3647 			args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
3648 			args.type = XFS_ALLOCTYPE_START_BNO;
3649 		} else {
3650 			args.fsbno = *firstblock;
3651 			args.type = XFS_ALLOCTYPE_NEAR_BNO;
3652 		}
3653 		args.total = total;
3654 		args.mod = args.minleft = args.alignment = args.wasdel =
3655 			args.isfl = args.minalignslop = 0;
3656 		args.minlen = args.maxlen = args.prod = 1;
3657 		if ((error = xfs_alloc_vextent(&args)))
3658 			goto done;
3659 		/*
3660 		 * Can't fail, the space was reserved.
3661 		 */
3662 		ASSERT(args.fsbno != NULLFSBLOCK);
3663 		ASSERT(args.len == 1);
3664 		*firstblock = args.fsbno;
3665 		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
3666 		memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
3667 			ifp->if_bytes);
3668 		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
3669 		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
3670 		xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
3671 		xfs_iext_add(ifp, 0, 1);
3672 		ep = xfs_iext_get_ext(ifp, 0);
3673 		xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
3674 		XFS_BMAP_TRACE_POST_UPDATE("new", ip, 0, whichfork);
3675 		XFS_IFORK_NEXT_SET(ip, whichfork, 1);
3676 		ip->i_d.di_nblocks = 1;
3677 		XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
3678 			XFS_TRANS_DQ_BCOUNT, 1L);
3679 		flags |= xfs_ilog_fext(whichfork);
3680 	} else {
3681 		ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
3682 		xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
3683 	}
3684 	ifp->if_flags &= ~XFS_IFINLINE;
3685 	ifp->if_flags |= XFS_IFEXTENTS;
3686 	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
3687 	flags |= XFS_ILOG_CORE;
3688 done:
3689 	*logflagsp = flags;
3690 	return error;
3691 }
3692 
3693 /*
3694  * Search the extent records for the entry containing block bno.
3695  * If bno lies in a hole, point to the next entry.  If bno lies
3696  * past eof, *eofp will be set, and *prevp will contain the last
3697  * entry (null if none).  Else, *lastxp will be set to the index
3698  * of the found entry; *gotp will contain the entry.
3699  */
3700 xfs_bmbt_rec_host_t *			/* pointer to found extent entry */
xfs_bmap_search_multi_extents(xfs_ifork_t * ifp,xfs_fileoff_t bno,int * eofp,xfs_extnum_t * lastxp,xfs_bmbt_irec_t * gotp,xfs_bmbt_irec_t * prevp)3701 xfs_bmap_search_multi_extents(
3702 	xfs_ifork_t	*ifp,		/* inode fork pointer */
3703 	xfs_fileoff_t	bno,		/* block number searched for */
3704 	int		*eofp,		/* out: end of file found */
3705 	xfs_extnum_t	*lastxp,	/* out: last extent index */
3706 	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
3707 	xfs_bmbt_irec_t	*prevp)		/* out: previous extent entry found */
3708 {
3709 	xfs_bmbt_rec_host_t *ep;		/* extent record pointer */
3710 	xfs_extnum_t	lastx;		/* last extent index */
3711 
3712 	/*
3713 	 * Initialize the extent entry structure to catch access to
3714 	 * uninitialized br_startblock field.
3715 	 */
3716 	gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
3717 	gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
3718 	gotp->br_state = XFS_EXT_INVALID;
3719 #if XFS_BIG_BLKNOS
3720 	gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
3721 #else
3722 	gotp->br_startblock = 0xffffa5a5;
3723 #endif
3724 	prevp->br_startoff = NULLFILEOFF;
3725 
3726 	ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
3727 	if (lastx > 0) {
3728 		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
3729 	}
3730 	if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
3731 		xfs_bmbt_get_all(ep, gotp);
3732 		*eofp = 0;
3733 	} else {
3734 		if (lastx > 0) {
3735 			*gotp = *prevp;
3736 		}
3737 		*eofp = 1;
3738 		ep = NULL;
3739 	}
3740 	*lastxp = lastx;
3741 	return ep;
3742 }
3743 
3744 /*
3745  * Search the extents list for the inode, for the extent containing bno.
3746  * If bno lies in a hole, point to the next entry.  If bno lies past eof,
3747  * *eofp will be set, and *prevp will contain the last entry (null if none).
3748  * Else, *lastxp will be set to the index of the found
3749  * entry; *gotp will contain the entry.
3750  */
3751 STATIC xfs_bmbt_rec_host_t *                 /* pointer to found extent entry */
xfs_bmap_search_extents(xfs_inode_t * ip,xfs_fileoff_t bno,int fork,int * eofp,xfs_extnum_t * lastxp,xfs_bmbt_irec_t * gotp,xfs_bmbt_irec_t * prevp)3752 xfs_bmap_search_extents(
3753 	xfs_inode_t     *ip,            /* incore inode pointer */
3754 	xfs_fileoff_t   bno,            /* block number searched for */
3755 	int             fork,      	/* data or attr fork */
3756 	int             *eofp,          /* out: end of file found */
3757 	xfs_extnum_t    *lastxp,        /* out: last extent index */
3758 	xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
3759 	xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
3760 {
3761 	xfs_ifork_t	*ifp;		/* inode fork pointer */
3762 	xfs_bmbt_rec_host_t  *ep;            /* extent record pointer */
3763 
3764 	XFS_STATS_INC(xs_look_exlist);
3765 	ifp = XFS_IFORK_PTR(ip, fork);
3766 
3767 	ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
3768 
3769 	if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
3770 		     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
3771 		xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
3772 				"Access to block zero in inode %llu "
3773 				"start_block: %llx start_off: %llx "
3774 				"blkcnt: %llx extent-state: %x lastx: %x\n",
3775 			(unsigned long long)ip->i_ino,
3776 			(unsigned long long)gotp->br_startblock,
3777 			(unsigned long long)gotp->br_startoff,
3778 			(unsigned long long)gotp->br_blockcount,
3779 			gotp->br_state, *lastxp);
3780 		*lastxp = NULLEXTNUM;
3781 		*eofp = 1;
3782 		return NULL;
3783 	}
3784 	return ep;
3785 }
3786 
3787 
3788 #ifdef XFS_BMAP_TRACE
3789 ktrace_t	*xfs_bmap_trace_buf;
3790 
3791 /*
3792  * Add a bmap trace buffer entry.  Base routine for the others.
3793  */
3794 STATIC void
xfs_bmap_trace_addentry(int opcode,const char * fname,char * desc,xfs_inode_t * ip,xfs_extnum_t idx,xfs_extnum_t cnt,xfs_bmbt_rec_host_t * r1,xfs_bmbt_rec_host_t * r2,int whichfork)3795 xfs_bmap_trace_addentry(
3796 	int		opcode,		/* operation */
3797 	const char	*fname,		/* function name */
3798 	char		*desc,		/* operation description */
3799 	xfs_inode_t	*ip,		/* incore inode pointer */
3800 	xfs_extnum_t	idx,		/* index of entry(ies) */
3801 	xfs_extnum_t	cnt,		/* count of entries, 1 or 2 */
3802 	xfs_bmbt_rec_host_t *r1,	/* first record */
3803 	xfs_bmbt_rec_host_t *r2,	/* second record or null */
3804 	int		whichfork)	/* data or attr fork */
3805 {
3806 	xfs_bmbt_rec_host_t tr2;
3807 
3808 	ASSERT(cnt == 1 || cnt == 2);
3809 	ASSERT(r1 != NULL);
3810 	if (cnt == 1) {
3811 		ASSERT(r2 == NULL);
3812 		r2 = &tr2;
3813 		memset(&tr2, 0, sizeof(tr2));
3814 	} else
3815 		ASSERT(r2 != NULL);
3816 	ktrace_enter(xfs_bmap_trace_buf,
3817 		(void *)(__psint_t)(opcode | (whichfork << 16)),
3818 		(void *)fname, (void *)desc, (void *)ip,
3819 		(void *)(__psint_t)idx,
3820 		(void *)(__psint_t)cnt,
3821 		(void *)(__psunsigned_t)(ip->i_ino >> 32),
3822 		(void *)(__psunsigned_t)(unsigned)ip->i_ino,
3823 		(void *)(__psunsigned_t)(r1->l0 >> 32),
3824 		(void *)(__psunsigned_t)(unsigned)(r1->l0),
3825 		(void *)(__psunsigned_t)(r1->l1 >> 32),
3826 		(void *)(__psunsigned_t)(unsigned)(r1->l1),
3827 		(void *)(__psunsigned_t)(r2->l0 >> 32),
3828 		(void *)(__psunsigned_t)(unsigned)(r2->l0),
3829 		(void *)(__psunsigned_t)(r2->l1 >> 32),
3830 		(void *)(__psunsigned_t)(unsigned)(r2->l1)
3831 		);
3832 	ASSERT(ip->i_xtrace);
3833 	ktrace_enter(ip->i_xtrace,
3834 		(void *)(__psint_t)(opcode | (whichfork << 16)),
3835 		(void *)fname, (void *)desc, (void *)ip,
3836 		(void *)(__psint_t)idx,
3837 		(void *)(__psint_t)cnt,
3838 		(void *)(__psunsigned_t)(ip->i_ino >> 32),
3839 		(void *)(__psunsigned_t)(unsigned)ip->i_ino,
3840 		(void *)(__psunsigned_t)(r1->l0 >> 32),
3841 		(void *)(__psunsigned_t)(unsigned)(r1->l0),
3842 		(void *)(__psunsigned_t)(r1->l1 >> 32),
3843 		(void *)(__psunsigned_t)(unsigned)(r1->l1),
3844 		(void *)(__psunsigned_t)(r2->l0 >> 32),
3845 		(void *)(__psunsigned_t)(unsigned)(r2->l0),
3846 		(void *)(__psunsigned_t)(r2->l1 >> 32),
3847 		(void *)(__psunsigned_t)(unsigned)(r2->l1)
3848 		);
3849 }
3850 
3851 /*
3852  * Add bmap trace entry prior to a call to xfs_iext_remove.
3853  */
3854 STATIC void
xfs_bmap_trace_delete(const char * fname,char * desc,xfs_inode_t * ip,xfs_extnum_t idx,xfs_extnum_t cnt,int whichfork)3855 xfs_bmap_trace_delete(
3856 	const char	*fname,		/* function name */
3857 	char		*desc,		/* operation description */
3858 	xfs_inode_t	*ip,		/* incore inode pointer */
3859 	xfs_extnum_t	idx,		/* index of entry(entries) deleted */
3860 	xfs_extnum_t	cnt,		/* count of entries deleted, 1 or 2 */
3861 	int		whichfork)	/* data or attr fork */
3862 {
3863 	xfs_ifork_t	*ifp;		/* inode fork pointer */
3864 
3865 	ifp = XFS_IFORK_PTR(ip, whichfork);
3866 	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_DELETE, fname, desc, ip, idx,
3867 		cnt, xfs_iext_get_ext(ifp, idx),
3868 		cnt == 2 ? xfs_iext_get_ext(ifp, idx + 1) : NULL,
3869 		whichfork);
3870 }
3871 
3872 /*
3873  * Add bmap trace entry prior to a call to xfs_iext_insert, or
3874  * reading in the extents list from the disk (in the btree).
3875  */
3876 STATIC void
xfs_bmap_trace_insert(const char * fname,char * desc,xfs_inode_t * ip,xfs_extnum_t idx,xfs_extnum_t cnt,xfs_bmbt_irec_t * r1,xfs_bmbt_irec_t * r2,int whichfork)3877 xfs_bmap_trace_insert(
3878 	const char	*fname,		/* function name */
3879 	char		*desc,		/* operation description */
3880 	xfs_inode_t	*ip,		/* incore inode pointer */
3881 	xfs_extnum_t	idx,		/* index of entry(entries) inserted */
3882 	xfs_extnum_t	cnt,		/* count of entries inserted, 1 or 2 */
3883 	xfs_bmbt_irec_t	*r1,		/* inserted record 1 */
3884 	xfs_bmbt_irec_t	*r2,		/* inserted record 2 or null */
3885 	int		whichfork)	/* data or attr fork */
3886 {
3887 	xfs_bmbt_rec_host_t tr1;	/* compressed record 1 */
3888 	xfs_bmbt_rec_host_t tr2;	/* compressed record 2 if needed */
3889 
3890 	xfs_bmbt_set_all(&tr1, r1);
3891 	if (cnt == 2) {
3892 		ASSERT(r2 != NULL);
3893 		xfs_bmbt_set_all(&tr2, r2);
3894 	} else {
3895 		ASSERT(cnt == 1);
3896 		ASSERT(r2 == NULL);
3897 	}
3898 	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_INSERT, fname, desc, ip, idx,
3899 		cnt, &tr1, cnt == 2 ? &tr2 : NULL, whichfork);
3900 }
3901 
3902 /*
3903  * Add bmap trace entry after updating an extent record in place.
3904  */
3905 STATIC void
xfs_bmap_trace_post_update(const char * fname,char * desc,xfs_inode_t * ip,xfs_extnum_t idx,int whichfork)3906 xfs_bmap_trace_post_update(
3907 	const char	*fname,		/* function name */
3908 	char		*desc,		/* operation description */
3909 	xfs_inode_t	*ip,		/* incore inode pointer */
3910 	xfs_extnum_t	idx,		/* index of entry updated */
3911 	int		whichfork)	/* data or attr fork */
3912 {
3913 	xfs_ifork_t	*ifp;		/* inode fork pointer */
3914 
3915 	ifp = XFS_IFORK_PTR(ip, whichfork);
3916 	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_POST_UP, fname, desc, ip, idx,
3917 		1, xfs_iext_get_ext(ifp, idx), NULL, whichfork);
3918 }
3919 
3920 /*
3921  * Add bmap trace entry prior to updating an extent record in place.
3922  */
3923 STATIC void
xfs_bmap_trace_pre_update(const char * fname,char * desc,xfs_inode_t * ip,xfs_extnum_t idx,int whichfork)3924 xfs_bmap_trace_pre_update(
3925 	const char	*fname,		/* function name */
3926 	char		*desc,		/* operation description */
3927 	xfs_inode_t	*ip,		/* incore inode pointer */
3928 	xfs_extnum_t	idx,		/* index of entry to be updated */
3929 	int		whichfork)	/* data or attr fork */
3930 {
3931 	xfs_ifork_t	*ifp;		/* inode fork pointer */
3932 
3933 	ifp = XFS_IFORK_PTR(ip, whichfork);
3934 	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_PRE_UP, fname, desc, ip, idx, 1,
3935 		xfs_iext_get_ext(ifp, idx), NULL, whichfork);
3936 }
3937 #endif	/* XFS_BMAP_TRACE */
3938 
3939 /*
3940  * Compute the worst-case number of indirect blocks that will be used
3941  * for ip's delayed extent of length "len".
3942  */
3943 STATIC xfs_filblks_t
xfs_bmap_worst_indlen(xfs_inode_t * ip,xfs_filblks_t len)3944 xfs_bmap_worst_indlen(
3945 	xfs_inode_t	*ip,		/* incore inode pointer */
3946 	xfs_filblks_t	len)		/* delayed extent length */
3947 {
3948 	int		level;		/* btree level number */
3949 	int		maxrecs;	/* maximum record count at this level */
3950 	xfs_mount_t	*mp;		/* mount structure */
3951 	xfs_filblks_t	rval;		/* return value */
3952 
3953 	mp = ip->i_mount;
3954 	maxrecs = mp->m_bmap_dmxr[0];
3955 	for (level = 0, rval = 0;
3956 	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
3957 	     level++) {
3958 		len += maxrecs - 1;
3959 		do_div(len, maxrecs);
3960 		rval += len;
3961 		if (len == 1)
3962 			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
3963 				level - 1;
3964 		if (level == 0)
3965 			maxrecs = mp->m_bmap_dmxr[1];
3966 	}
3967 	return rval;
3968 }
3969 
3970 #if defined(XFS_RW_TRACE)
3971 STATIC void
xfs_bunmap_trace(xfs_inode_t * ip,xfs_fileoff_t bno,xfs_filblks_t len,int flags,inst_t * ra)3972 xfs_bunmap_trace(
3973 	xfs_inode_t		*ip,
3974 	xfs_fileoff_t		bno,
3975 	xfs_filblks_t		len,
3976 	int			flags,
3977 	inst_t			*ra)
3978 {
3979 	if (ip->i_rwtrace == NULL)
3980 		return;
3981 	ktrace_enter(ip->i_rwtrace,
3982 		(void *)(__psint_t)XFS_BUNMAP,
3983 		(void *)ip,
3984 		(void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff),
3985 		(void *)(__psint_t)(ip->i_d.di_size & 0xffffffff),
3986 		(void *)(__psint_t)(((xfs_dfiloff_t)bno >> 32) & 0xffffffff),
3987 		(void *)(__psint_t)((xfs_dfiloff_t)bno & 0xffffffff),
3988 		(void *)(__psint_t)len,
3989 		(void *)(__psint_t)flags,
3990 		(void *)(unsigned long)current_cpu(),
3991 		(void *)ra,
3992 		(void *)0,
3993 		(void *)0,
3994 		(void *)0,
3995 		(void *)0,
3996 		(void *)0,
3997 		(void *)0);
3998 }
3999 #endif
4000 
4001 /*
4002  * Convert inode from non-attributed to attributed.
4003  * Must not be in a transaction, ip must not be locked.
4004  */
4005 int						/* error code */
xfs_bmap_add_attrfork(xfs_inode_t * ip,int size,int rsvd)4006 xfs_bmap_add_attrfork(
4007 	xfs_inode_t		*ip,		/* incore inode pointer */
4008 	int			size,		/* space new attribute needs */
4009 	int			rsvd)		/* xact may use reserved blks */
4010 {
4011 	xfs_fsblock_t		firstblock;	/* 1st block/ag allocated */
4012 	xfs_bmap_free_t		flist;		/* freed extent records */
4013 	xfs_mount_t		*mp;		/* mount structure */
4014 	xfs_trans_t		*tp;		/* transaction pointer */
4015 	int			blks;		/* space reservation */
4016 	int			version = 1;	/* superblock attr version */
4017 	int			committed;	/* xaction was committed */
4018 	int			logflags;	/* logging flags */
4019 	int			error;		/* error return value */
4020 
4021 	ASSERT(XFS_IFORK_Q(ip) == 0);
4022 	ASSERT(ip->i_df.if_ext_max ==
4023 	       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4024 
4025 	mp = ip->i_mount;
4026 	ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
4027 	tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
4028 	blks = XFS_ADDAFORK_SPACE_RES(mp);
4029 	if (rsvd)
4030 		tp->t_flags |= XFS_TRANS_RESERVE;
4031 	if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
4032 			XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
4033 		goto error0;
4034 	xfs_ilock(ip, XFS_ILOCK_EXCL);
4035 	error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, blks, 0, rsvd ?
4036 			XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
4037 			XFS_QMOPT_RES_REGBLKS);
4038 	if (error) {
4039 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
4040 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
4041 		return error;
4042 	}
4043 	if (XFS_IFORK_Q(ip))
4044 		goto error1;
4045 	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
4046 		/*
4047 		 * For inodes coming from pre-6.2 filesystems.
4048 		 */
4049 		ASSERT(ip->i_d.di_aformat == 0);
4050 		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
4051 	}
4052 	ASSERT(ip->i_d.di_anextents == 0);
4053 	IHOLD(ip);
4054 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
4055 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
4056 	switch (ip->i_d.di_format) {
4057 	case XFS_DINODE_FMT_DEV:
4058 		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
4059 		break;
4060 	case XFS_DINODE_FMT_UUID:
4061 		ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
4062 		break;
4063 	case XFS_DINODE_FMT_LOCAL:
4064 	case XFS_DINODE_FMT_EXTENTS:
4065 	case XFS_DINODE_FMT_BTREE:
4066 		ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
4067 		if (!ip->i_d.di_forkoff)
4068 			ip->i_d.di_forkoff = mp->m_attroffset >> 3;
4069 		else if (mp->m_flags & XFS_MOUNT_ATTR2)
4070 			version = 2;
4071 		break;
4072 	default:
4073 		ASSERT(0);
4074 		error = XFS_ERROR(EINVAL);
4075 		goto error1;
4076 	}
4077 	ip->i_df.if_ext_max =
4078 		XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
4079 	ASSERT(ip->i_afp == NULL);
4080 	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
4081 	ip->i_afp->if_ext_max =
4082 		XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
4083 	ip->i_afp->if_flags = XFS_IFEXTENTS;
4084 	logflags = 0;
4085 	xfs_bmap_init(&flist, &firstblock);
4086 	switch (ip->i_d.di_format) {
4087 	case XFS_DINODE_FMT_LOCAL:
4088 		error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
4089 			&logflags);
4090 		break;
4091 	case XFS_DINODE_FMT_EXTENTS:
4092 		error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
4093 			&flist, &logflags);
4094 		break;
4095 	case XFS_DINODE_FMT_BTREE:
4096 		error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
4097 			&logflags);
4098 		break;
4099 	default:
4100 		error = 0;
4101 		break;
4102 	}
4103 	if (logflags)
4104 		xfs_trans_log_inode(tp, ip, logflags);
4105 	if (error)
4106 		goto error2;
4107 	if (!xfs_sb_version_hasattr(&mp->m_sb) ||
4108 	   (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
4109 		__int64_t sbfields = 0;
4110 
4111 		spin_lock(&mp->m_sb_lock);
4112 		if (!xfs_sb_version_hasattr(&mp->m_sb)) {
4113 			xfs_sb_version_addattr(&mp->m_sb);
4114 			sbfields |= XFS_SB_VERSIONNUM;
4115 		}
4116 		if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {
4117 			xfs_sb_version_addattr2(&mp->m_sb);
4118 			sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
4119 		}
4120 		if (sbfields) {
4121 			spin_unlock(&mp->m_sb_lock);
4122 			xfs_mod_sb(tp, sbfields);
4123 		} else
4124 			spin_unlock(&mp->m_sb_lock);
4125 	}
4126 	if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
4127 		goto error2;
4128 	error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES);
4129 	ASSERT(ip->i_df.if_ext_max ==
4130 	       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4131 	return error;
4132 error2:
4133 	xfs_bmap_cancel(&flist);
4134 error1:
4135 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
4136 error0:
4137 	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
4138 	ASSERT(ip->i_df.if_ext_max ==
4139 	       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4140 	return error;
4141 }
4142 
4143 /*
4144  * Add the extent to the list of extents to be free at transaction end.
4145  * The list is maintained sorted (by block number).
4146  */
4147 /* ARGSUSED */
4148 void
xfs_bmap_add_free(xfs_fsblock_t bno,xfs_filblks_t len,xfs_bmap_free_t * flist,xfs_mount_t * mp)4149 xfs_bmap_add_free(
4150 	xfs_fsblock_t		bno,		/* fs block number of extent */
4151 	xfs_filblks_t		len,		/* length of extent */
4152 	xfs_bmap_free_t		*flist,		/* list of extents */
4153 	xfs_mount_t		*mp)		/* mount point structure */
4154 {
4155 	xfs_bmap_free_item_t	*cur;		/* current (next) element */
4156 	xfs_bmap_free_item_t	*new;		/* new element */
4157 	xfs_bmap_free_item_t	*prev;		/* previous element */
4158 #ifdef DEBUG
4159 	xfs_agnumber_t		agno;
4160 	xfs_agblock_t		agbno;
4161 
4162 	ASSERT(bno != NULLFSBLOCK);
4163 	ASSERT(len > 0);
4164 	ASSERT(len <= MAXEXTLEN);
4165 	ASSERT(!isnullstartblock(bno));
4166 	agno = XFS_FSB_TO_AGNO(mp, bno);
4167 	agbno = XFS_FSB_TO_AGBNO(mp, bno);
4168 	ASSERT(agno < mp->m_sb.sb_agcount);
4169 	ASSERT(agbno < mp->m_sb.sb_agblocks);
4170 	ASSERT(len < mp->m_sb.sb_agblocks);
4171 	ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
4172 #endif
4173 	ASSERT(xfs_bmap_free_item_zone != NULL);
4174 	new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
4175 	new->xbfi_startblock = bno;
4176 	new->xbfi_blockcount = (xfs_extlen_t)len;
4177 	for (prev = NULL, cur = flist->xbf_first;
4178 	     cur != NULL;
4179 	     prev = cur, cur = cur->xbfi_next) {
4180 		if (cur->xbfi_startblock >= bno)
4181 			break;
4182 	}
4183 	if (prev)
4184 		prev->xbfi_next = new;
4185 	else
4186 		flist->xbf_first = new;
4187 	new->xbfi_next = cur;
4188 	flist->xbf_count++;
4189 }
4190 
4191 /*
4192  * Compute and fill in the value of the maximum depth of a bmap btree
4193  * in this filesystem.  Done once, during mount.
4194  */
4195 void
xfs_bmap_compute_maxlevels(xfs_mount_t * mp,int whichfork)4196 xfs_bmap_compute_maxlevels(
4197 	xfs_mount_t	*mp,		/* file system mount structure */
4198 	int		whichfork)	/* data or attr fork */
4199 {
4200 	int		level;		/* btree level */
4201 	uint		maxblocks;	/* max blocks at this level */
4202 	uint		maxleafents;	/* max leaf entries possible */
4203 	int		maxrootrecs;	/* max records in root block */
4204 	int		minleafrecs;	/* min records in leaf block */
4205 	int		minnoderecs;	/* min records in node block */
4206 	int		sz;		/* root block size */
4207 
4208 	/*
4209 	 * The maximum number of extents in a file, hence the maximum
4210 	 * number of leaf entries, is controlled by the type of di_nextents
4211 	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
4212 	 * (a signed 16-bit number, xfs_aextnum_t).
4213 	 *
4214 	 * Note that we can no longer assume that if we are in ATTR1 that
4215 	 * the fork offset of all the inodes will be (m_attroffset >> 3)
4216 	 * because we could have mounted with ATTR2 and then mounted back
4217 	 * with ATTR1, keeping the di_forkoff's fixed but probably at
4218 	 * various positions. Therefore, for both ATTR1 and ATTR2
4219 	 * we have to assume the worst case scenario of a minimum size
4220 	 * available.
4221 	 */
4222 	if (whichfork == XFS_DATA_FORK) {
4223 		maxleafents = MAXEXTNUM;
4224 		sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
4225 	} else {
4226 		maxleafents = MAXAEXTNUM;
4227 		sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
4228 	}
4229 	maxrootrecs = xfs_bmdr_maxrecs(mp, sz, 0);
4230 	minleafrecs = mp->m_bmap_dmnr[0];
4231 	minnoderecs = mp->m_bmap_dmnr[1];
4232 	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
4233 	for (level = 1; maxblocks > 1; level++) {
4234 		if (maxblocks <= maxrootrecs)
4235 			maxblocks = 1;
4236 		else
4237 			maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
4238 	}
4239 	mp->m_bm_maxlevels[whichfork] = level;
4240 }
4241 
4242 /*
4243  * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
4244  * caller.  Frees all the extents that need freeing, which must be done
4245  * last due to locking considerations.  We never free any extents in
4246  * the first transaction.  This is to allow the caller to make the first
4247  * transaction a synchronous one so that the pointers to the data being
4248  * broken in this transaction will be permanent before the data is actually
4249  * freed.  This is necessary to prevent blocks from being reallocated
4250  * and written to before the free and reallocation are actually permanent.
4251  * We do not just make the first transaction synchronous here, because
4252  * there are more efficient ways to gain the same protection in some cases
4253  * (see the file truncation code).
4254  *
4255  * Return 1 if the given transaction was committed and a new one
4256  * started, and 0 otherwise in the committed parameter.
4257  */
4258 /*ARGSUSED*/
4259 int						/* error */
xfs_bmap_finish(xfs_trans_t ** tp,xfs_bmap_free_t * flist,int * committed)4260 xfs_bmap_finish(
4261 	xfs_trans_t		**tp,		/* transaction pointer addr */
4262 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
4263 	int			*committed)	/* xact committed or not */
4264 {
4265 	xfs_efd_log_item_t	*efd;		/* extent free data */
4266 	xfs_efi_log_item_t	*efi;		/* extent free intention */
4267 	int			error;		/* error return value */
4268 	xfs_bmap_free_item_t	*free;		/* free extent item */
4269 	unsigned int		logres;		/* new log reservation */
4270 	unsigned int		logcount;	/* new log count */
4271 	xfs_mount_t		*mp;		/* filesystem mount structure */
4272 	xfs_bmap_free_item_t	*next;		/* next item on free list */
4273 	xfs_trans_t		*ntp;		/* new transaction pointer */
4274 
4275 	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
4276 	if (flist->xbf_count == 0) {
4277 		*committed = 0;
4278 		return 0;
4279 	}
4280 	ntp = *tp;
4281 	efi = xfs_trans_get_efi(ntp, flist->xbf_count);
4282 	for (free = flist->xbf_first; free; free = free->xbfi_next)
4283 		xfs_trans_log_efi_extent(ntp, efi, free->xbfi_startblock,
4284 			free->xbfi_blockcount);
4285 	logres = ntp->t_log_res;
4286 	logcount = ntp->t_log_count;
4287 	ntp = xfs_trans_dup(*tp);
4288 	error = xfs_trans_commit(*tp, 0);
4289 	*tp = ntp;
4290 	*committed = 1;
4291 	/*
4292 	 * We have a new transaction, so we should return committed=1,
4293 	 * even though we're returning an error.
4294 	 */
4295 	if (error)
4296 		return error;
4297 
4298 	/*
4299 	 * transaction commit worked ok so we can drop the extra ticket
4300 	 * reference that we gained in xfs_trans_dup()
4301 	 */
4302 	xfs_log_ticket_put(ntp->t_ticket);
4303 
4304 	if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES,
4305 			logcount)))
4306 		return error;
4307 	efd = xfs_trans_get_efd(ntp, efi, flist->xbf_count);
4308 	for (free = flist->xbf_first; free != NULL; free = next) {
4309 		next = free->xbfi_next;
4310 		if ((error = xfs_free_extent(ntp, free->xbfi_startblock,
4311 				free->xbfi_blockcount))) {
4312 			/*
4313 			 * The bmap free list will be cleaned up at a
4314 			 * higher level.  The EFI will be canceled when
4315 			 * this transaction is aborted.
4316 			 * Need to force shutdown here to make sure it
4317 			 * happens, since this transaction may not be
4318 			 * dirty yet.
4319 			 */
4320 			mp = ntp->t_mountp;
4321 			if (!XFS_FORCED_SHUTDOWN(mp))
4322 				xfs_force_shutdown(mp,
4323 						   (error == EFSCORRUPTED) ?
4324 						   SHUTDOWN_CORRUPT_INCORE :
4325 						   SHUTDOWN_META_IO_ERROR);
4326 			return error;
4327 		}
4328 		xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
4329 			free->xbfi_blockcount);
4330 		xfs_bmap_del_free(flist, NULL, free);
4331 	}
4332 	return 0;
4333 }
4334 
4335 /*
4336  * Free up any items left in the list.
4337  */
4338 void
xfs_bmap_cancel(xfs_bmap_free_t * flist)4339 xfs_bmap_cancel(
4340 	xfs_bmap_free_t		*flist)	/* list of bmap_free_items */
4341 {
4342 	xfs_bmap_free_item_t	*free;	/* free list item */
4343 	xfs_bmap_free_item_t	*next;
4344 
4345 	if (flist->xbf_count == 0)
4346 		return;
4347 	ASSERT(flist->xbf_first != NULL);
4348 	for (free = flist->xbf_first; free; free = next) {
4349 		next = free->xbfi_next;
4350 		xfs_bmap_del_free(flist, NULL, free);
4351 	}
4352 	ASSERT(flist->xbf_count == 0);
4353 }
4354 
4355 /*
4356  * Returns the file-relative block number of the first unused block(s)
4357  * in the file with at least "len" logically contiguous blocks free.
4358  * This is the lowest-address hole if the file has holes, else the first block
4359  * past the end of file.
4360  * Return 0 if the file is currently local (in-inode).
4361  */
4362 int						/* error */
xfs_bmap_first_unused(xfs_trans_t * tp,xfs_inode_t * ip,xfs_extlen_t len,xfs_fileoff_t * first_unused,int whichfork)4363 xfs_bmap_first_unused(
4364 	xfs_trans_t	*tp,			/* transaction pointer */
4365 	xfs_inode_t	*ip,			/* incore inode */
4366 	xfs_extlen_t	len,			/* size of hole to find */
4367 	xfs_fileoff_t	*first_unused,		/* unused block */
4368 	int		whichfork)		/* data or attr fork */
4369 {
4370 	int		error;			/* error return value */
4371 	int		idx;			/* extent record index */
4372 	xfs_ifork_t	*ifp;			/* inode fork pointer */
4373 	xfs_fileoff_t	lastaddr;		/* last block number seen */
4374 	xfs_fileoff_t	lowest;			/* lowest useful block */
4375 	xfs_fileoff_t	max;			/* starting useful block */
4376 	xfs_fileoff_t	off;			/* offset for this block */
4377 	xfs_extnum_t	nextents;		/* number of extent entries */
4378 
4379 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
4380 	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
4381 	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
4382 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4383 		*first_unused = 0;
4384 		return 0;
4385 	}
4386 	ifp = XFS_IFORK_PTR(ip, whichfork);
4387 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4388 	    (error = xfs_iread_extents(tp, ip, whichfork)))
4389 		return error;
4390 	lowest = *first_unused;
4391 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4392 	for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
4393 		xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
4394 		off = xfs_bmbt_get_startoff(ep);
4395 		/*
4396 		 * See if the hole before this extent will work.
4397 		 */
4398 		if (off >= lowest + len && off - max >= len) {
4399 			*first_unused = max;
4400 			return 0;
4401 		}
4402 		lastaddr = off + xfs_bmbt_get_blockcount(ep);
4403 		max = XFS_FILEOFF_MAX(lastaddr, lowest);
4404 	}
4405 	*first_unused = max;
4406 	return 0;
4407 }
4408 
4409 /*
4410  * Returns the file-relative block number of the last block + 1 before
4411  * last_block (input value) in the file.
4412  * This is not based on i_size, it is based on the extent records.
4413  * Returns 0 for local files, as they do not have extent records.
4414  */
4415 int						/* error */
xfs_bmap_last_before(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fileoff_t * last_block,int whichfork)4416 xfs_bmap_last_before(
4417 	xfs_trans_t	*tp,			/* transaction pointer */
4418 	xfs_inode_t	*ip,			/* incore inode */
4419 	xfs_fileoff_t	*last_block,		/* last block */
4420 	int		whichfork)		/* data or attr fork */
4421 {
4422 	xfs_fileoff_t	bno;			/* input file offset */
4423 	int		eof;			/* hit end of file */
4424 	xfs_bmbt_rec_host_t *ep;		/* pointer to last extent */
4425 	int		error;			/* error return value */
4426 	xfs_bmbt_irec_t	got;			/* current extent value */
4427 	xfs_ifork_t	*ifp;			/* inode fork pointer */
4428 	xfs_extnum_t	lastx;			/* last extent used */
4429 	xfs_bmbt_irec_t	prev;			/* previous extent value */
4430 
4431 	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4432 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4433 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
4434 	       return XFS_ERROR(EIO);
4435 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4436 		*last_block = 0;
4437 		return 0;
4438 	}
4439 	ifp = XFS_IFORK_PTR(ip, whichfork);
4440 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4441 	    (error = xfs_iread_extents(tp, ip, whichfork)))
4442 		return error;
4443 	bno = *last_block - 1;
4444 	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4445 		&prev);
4446 	if (eof || xfs_bmbt_get_startoff(ep) > bno) {
4447 		if (prev.br_startoff == NULLFILEOFF)
4448 			*last_block = 0;
4449 		else
4450 			*last_block = prev.br_startoff + prev.br_blockcount;
4451 	}
4452 	/*
4453 	 * Otherwise *last_block is already the right answer.
4454 	 */
4455 	return 0;
4456 }
4457 
4458 /*
4459  * Returns the file-relative block number of the first block past eof in
4460  * the file.  This is not based on i_size, it is based on the extent records.
4461  * Returns 0 for local files, as they do not have extent records.
4462  */
4463 int						/* error */
xfs_bmap_last_offset(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fileoff_t * last_block,int whichfork)4464 xfs_bmap_last_offset(
4465 	xfs_trans_t	*tp,			/* transaction pointer */
4466 	xfs_inode_t	*ip,			/* incore inode */
4467 	xfs_fileoff_t	*last_block,		/* last block */
4468 	int		whichfork)		/* data or attr fork */
4469 {
4470 	xfs_bmbt_rec_host_t *ep;		/* pointer to last extent */
4471 	int		error;			/* error return value */
4472 	xfs_ifork_t	*ifp;			/* inode fork pointer */
4473 	xfs_extnum_t	nextents;		/* number of extent entries */
4474 
4475 	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4476 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4477 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
4478 	       return XFS_ERROR(EIO);
4479 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4480 		*last_block = 0;
4481 		return 0;
4482 	}
4483 	ifp = XFS_IFORK_PTR(ip, whichfork);
4484 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4485 	    (error = xfs_iread_extents(tp, ip, whichfork)))
4486 		return error;
4487 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4488 	if (!nextents) {
4489 		*last_block = 0;
4490 		return 0;
4491 	}
4492 	ep = xfs_iext_get_ext(ifp, nextents - 1);
4493 	*last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep);
4494 	return 0;
4495 }
4496 
4497 /*
4498  * Returns whether the selected fork of the inode has exactly one
4499  * block or not.  For the data fork we check this matches di_size,
4500  * implying the file's range is 0..bsize-1.
4501  */
4502 int					/* 1=>1 block, 0=>otherwise */
xfs_bmap_one_block(xfs_inode_t * ip,int whichfork)4503 xfs_bmap_one_block(
4504 	xfs_inode_t	*ip,		/* incore inode */
4505 	int		whichfork)	/* data or attr fork */
4506 {
4507 	xfs_bmbt_rec_host_t *ep;	/* ptr to fork's extent */
4508 	xfs_ifork_t	*ifp;		/* inode fork pointer */
4509 	int		rval;		/* return value */
4510 	xfs_bmbt_irec_t	s;		/* internal version of extent */
4511 
4512 #ifndef DEBUG
4513 	if (whichfork == XFS_DATA_FORK) {
4514 		return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
4515 			(ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
4516 			(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
4517 	}
4518 #endif	/* !DEBUG */
4519 	if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
4520 		return 0;
4521 	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
4522 		return 0;
4523 	ifp = XFS_IFORK_PTR(ip, whichfork);
4524 	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
4525 	ep = xfs_iext_get_ext(ifp, 0);
4526 	xfs_bmbt_get_all(ep, &s);
4527 	rval = s.br_startoff == 0 && s.br_blockcount == 1;
4528 	if (rval && whichfork == XFS_DATA_FORK)
4529 		ASSERT(ip->i_size == ip->i_mount->m_sb.sb_blocksize);
4530 	return rval;
4531 }
4532 
4533 STATIC int
xfs_bmap_sanity_check(struct xfs_mount * mp,struct xfs_buf * bp,int level)4534 xfs_bmap_sanity_check(
4535 	struct xfs_mount	*mp,
4536 	struct xfs_buf		*bp,
4537 	int			level)
4538 {
4539 	struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
4540 
4541 	if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC ||
4542 	    be16_to_cpu(block->bb_level) != level ||
4543 	    be16_to_cpu(block->bb_numrecs) == 0 ||
4544 	    be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
4545 		return 0;
4546 	return 1;
4547 }
4548 
4549 /*
4550  * Read in the extents to if_extents.
4551  * All inode fields are set up by caller, we just traverse the btree
4552  * and copy the records in. If the file system cannot contain unwritten
4553  * extents, the records are checked for no "state" flags.
4554  */
4555 int					/* error */
xfs_bmap_read_extents(xfs_trans_t * tp,xfs_inode_t * ip,int whichfork)4556 xfs_bmap_read_extents(
4557 	xfs_trans_t		*tp,	/* transaction pointer */
4558 	xfs_inode_t		*ip,	/* incore inode */
4559 	int			whichfork) /* data or attr fork */
4560 {
4561 	struct xfs_btree_block	*block;	/* current btree block */
4562 	xfs_fsblock_t		bno;	/* block # of "block" */
4563 	xfs_buf_t		*bp;	/* buffer for "block" */
4564 	int			error;	/* error return value */
4565 	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
4566 	xfs_extnum_t		i, j;	/* index into the extents list */
4567 	xfs_ifork_t		*ifp;	/* fork structure */
4568 	int			level;	/* btree level, for checking */
4569 	xfs_mount_t		*mp;	/* file system mount structure */
4570 	__be64			*pp;	/* pointer to block address */
4571 	/* REFERENCED */
4572 	xfs_extnum_t		room;	/* number of entries there's room for */
4573 
4574 	bno = NULLFSBLOCK;
4575 	mp = ip->i_mount;
4576 	ifp = XFS_IFORK_PTR(ip, whichfork);
4577 	exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
4578 					XFS_EXTFMT_INODE(ip);
4579 	block = ifp->if_broot;
4580 	/*
4581 	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
4582 	 */
4583 	level = be16_to_cpu(block->bb_level);
4584 	ASSERT(level > 0);
4585 	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
4586 	bno = be64_to_cpu(*pp);
4587 	ASSERT(bno != NULLDFSBNO);
4588 	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
4589 	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
4590 	/*
4591 	 * Go down the tree until leaf level is reached, following the first
4592 	 * pointer (leftmost) at each level.
4593 	 */
4594 	while (level-- > 0) {
4595 		if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
4596 				XFS_BMAP_BTREE_REF)))
4597 			return error;
4598 		block = XFS_BUF_TO_BLOCK(bp);
4599 		XFS_WANT_CORRUPTED_GOTO(
4600 			xfs_bmap_sanity_check(mp, bp, level),
4601 			error0);
4602 		if (level == 0)
4603 			break;
4604 		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
4605 		bno = be64_to_cpu(*pp);
4606 		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
4607 		xfs_trans_brelse(tp, bp);
4608 	}
4609 	/*
4610 	 * Here with bp and block set to the leftmost leaf node in the tree.
4611 	 */
4612 	room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4613 	i = 0;
4614 	/*
4615 	 * Loop over all leaf nodes.  Copy information to the extent records.
4616 	 */
4617 	for (;;) {
4618 		xfs_bmbt_rec_t	*frp;
4619 		xfs_fsblock_t	nextbno;
4620 		xfs_extnum_t	num_recs;
4621 		xfs_extnum_t	start;
4622 
4623 
4624 		num_recs = xfs_btree_get_numrecs(block);
4625 		if (unlikely(i + num_recs > room)) {
4626 			ASSERT(i + num_recs <= room);
4627 			xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
4628 				"corrupt dinode %Lu, (btree extents).",
4629 				(unsigned long long) ip->i_ino);
4630 			XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
4631 					 XFS_ERRLEVEL_LOW,
4632 					ip->i_mount);
4633 			goto error0;
4634 		}
4635 		XFS_WANT_CORRUPTED_GOTO(
4636 			xfs_bmap_sanity_check(mp, bp, 0),
4637 			error0);
4638 		/*
4639 		 * Read-ahead the next leaf block, if any.
4640 		 */
4641 		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
4642 		if (nextbno != NULLFSBLOCK)
4643 			xfs_btree_reada_bufl(mp, nextbno, 1);
4644 		/*
4645 		 * Copy records into the extent records.
4646 		 */
4647 		frp = XFS_BMBT_REC_ADDR(mp, block, 1);
4648 		start = i;
4649 		for (j = 0; j < num_recs; j++, i++, frp++) {
4650 			xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
4651 			trp->l0 = be64_to_cpu(frp->l0);
4652 			trp->l1 = be64_to_cpu(frp->l1);
4653 		}
4654 		if (exntf == XFS_EXTFMT_NOSTATE) {
4655 			/*
4656 			 * Check all attribute bmap btree records and
4657 			 * any "older" data bmap btree records for a
4658 			 * set bit in the "extent flag" position.
4659 			 */
4660 			if (unlikely(xfs_check_nostate_extents(ifp,
4661 					start, num_recs))) {
4662 				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
4663 						 XFS_ERRLEVEL_LOW,
4664 						 ip->i_mount);
4665 				goto error0;
4666 			}
4667 		}
4668 		xfs_trans_brelse(tp, bp);
4669 		bno = nextbno;
4670 		/*
4671 		 * If we've reached the end, stop.
4672 		 */
4673 		if (bno == NULLFSBLOCK)
4674 			break;
4675 		if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
4676 				XFS_BMAP_BTREE_REF)))
4677 			return error;
4678 		block = XFS_BUF_TO_BLOCK(bp);
4679 	}
4680 	ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
4681 	ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
4682 	XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
4683 	return 0;
4684 error0:
4685 	xfs_trans_brelse(tp, bp);
4686 	return XFS_ERROR(EFSCORRUPTED);
4687 }
4688 
4689 #ifdef XFS_BMAP_TRACE
4690 /*
4691  * Add bmap trace insert entries for all the contents of the extent records.
4692  */
4693 void
xfs_bmap_trace_exlist(const char * fname,xfs_inode_t * ip,xfs_extnum_t cnt,int whichfork)4694 xfs_bmap_trace_exlist(
4695 	const char	*fname,		/* function name */
4696 	xfs_inode_t	*ip,		/* incore inode pointer */
4697 	xfs_extnum_t	cnt,		/* count of entries in the list */
4698 	int		whichfork)	/* data or attr fork */
4699 {
4700 	xfs_bmbt_rec_host_t *ep;	/* current extent record */
4701 	xfs_extnum_t	idx;		/* extent record index */
4702 	xfs_ifork_t	*ifp;		/* inode fork pointer */
4703 	xfs_bmbt_irec_t	s;		/* file extent record */
4704 
4705 	ifp = XFS_IFORK_PTR(ip, whichfork);
4706 	ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
4707 	for (idx = 0; idx < cnt; idx++) {
4708 		ep = xfs_iext_get_ext(ifp, idx);
4709 		xfs_bmbt_get_all(ep, &s);
4710 		XFS_BMAP_TRACE_INSERT("exlist", ip, idx, 1, &s, NULL,
4711 			whichfork);
4712 	}
4713 }
4714 #endif
4715 
4716 #ifdef DEBUG
4717 /*
4718  * Validate that the bmbt_irecs being returned from bmapi are valid
4719  * given the callers original parameters.  Specifically check the
4720  * ranges of the returned irecs to ensure that they only extent beyond
4721  * the given parameters if the XFS_BMAPI_ENTIRE flag was set.
4722  */
4723 STATIC void
xfs_bmap_validate_ret(xfs_fileoff_t bno,xfs_filblks_t len,int flags,xfs_bmbt_irec_t * mval,int nmap,int ret_nmap)4724 xfs_bmap_validate_ret(
4725 	xfs_fileoff_t		bno,
4726 	xfs_filblks_t		len,
4727 	int			flags,
4728 	xfs_bmbt_irec_t		*mval,
4729 	int			nmap,
4730 	int			ret_nmap)
4731 {
4732 	int			i;		/* index to map values */
4733 
4734 	ASSERT(ret_nmap <= nmap);
4735 
4736 	for (i = 0; i < ret_nmap; i++) {
4737 		ASSERT(mval[i].br_blockcount > 0);
4738 		if (!(flags & XFS_BMAPI_ENTIRE)) {
4739 			ASSERT(mval[i].br_startoff >= bno);
4740 			ASSERT(mval[i].br_blockcount <= len);
4741 			ASSERT(mval[i].br_startoff + mval[i].br_blockcount <=
4742 			       bno + len);
4743 		} else {
4744 			ASSERT(mval[i].br_startoff < bno + len);
4745 			ASSERT(mval[i].br_startoff + mval[i].br_blockcount >
4746 			       bno);
4747 		}
4748 		ASSERT(i == 0 ||
4749 		       mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
4750 		       mval[i].br_startoff);
4751 		if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY))
4752 			ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
4753 			       mval[i].br_startblock != HOLESTARTBLOCK);
4754 		ASSERT(mval[i].br_state == XFS_EXT_NORM ||
4755 		       mval[i].br_state == XFS_EXT_UNWRITTEN);
4756 	}
4757 }
4758 #endif /* DEBUG */
4759 
4760 
4761 /*
4762  * Map file blocks to filesystem blocks.
4763  * File range is given by the bno/len pair.
4764  * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
4765  * into a hole or past eof.
4766  * Only allocates blocks from a single allocation group,
4767  * to avoid locking problems.
4768  * The returned value in "firstblock" from the first call in a transaction
4769  * must be remembered and presented to subsequent calls in "firstblock".
4770  * An upper bound for the number of blocks to be allocated is supplied to
4771  * the first call in "total"; if no allocation group has that many free
4772  * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
4773  */
4774 int					/* error */
xfs_bmapi(xfs_trans_t * tp,xfs_inode_t * ip,xfs_fileoff_t bno,xfs_filblks_t len,int flags,xfs_fsblock_t * firstblock,xfs_extlen_t total,xfs_bmbt_irec_t * mval,int * nmap,xfs_bmap_free_t * flist,xfs_extdelta_t * delta)4775 xfs_bmapi(
4776 	xfs_trans_t	*tp,		/* transaction pointer */
4777 	xfs_inode_t	*ip,		/* incore inode */
4778 	xfs_fileoff_t	bno,		/* starting file offs. mapped */
4779 	xfs_filblks_t	len,		/* length to map in file */
4780 	int		flags,		/* XFS_BMAPI_... */
4781 	xfs_fsblock_t	*firstblock,	/* first allocated block
4782 					   controls a.g. for allocs */
4783 	xfs_extlen_t	total,		/* total blocks needed */
4784 	xfs_bmbt_irec_t	*mval,		/* output: map values */
4785 	int		*nmap,		/* i/o: mval size/count */
4786 	xfs_bmap_free_t	*flist,		/* i/o: list extents to free */
4787 	xfs_extdelta_t	*delta)		/* o: change made to incore extents */
4788 {
4789 	xfs_fsblock_t	abno;		/* allocated block number */
4790 	xfs_extlen_t	alen;		/* allocated extent length */
4791 	xfs_fileoff_t	aoff;		/* allocated file offset */
4792 	xfs_bmalloca_t	bma;		/* args for xfs_bmap_alloc */
4793 	xfs_btree_cur_t	*cur;		/* bmap btree cursor */
4794 	xfs_fileoff_t	end;		/* end of mapped file region */
4795 	int		eof;		/* we've hit the end of extents */
4796 	xfs_bmbt_rec_host_t *ep;	/* extent record pointer */
4797 	int		error;		/* error return */
4798 	xfs_bmbt_irec_t	got;		/* current file extent record */
4799 	xfs_ifork_t	*ifp;		/* inode fork pointer */
4800 	xfs_extlen_t	indlen;		/* indirect blocks length */
4801 	xfs_extnum_t	lastx;		/* last useful extent number */
4802 	int		logflags;	/* flags for transaction logging */
4803 	xfs_extlen_t	minleft;	/* min blocks left after allocation */
4804 	xfs_extlen_t	minlen;		/* min allocation size */
4805 	xfs_mount_t	*mp;		/* xfs mount structure */
4806 	int		n;		/* current extent index */
4807 	int		nallocs;	/* number of extents alloc\'d */
4808 	xfs_extnum_t	nextents;	/* number of extents in file */
4809 	xfs_fileoff_t	obno;		/* old block number (offset) */
4810 	xfs_bmbt_irec_t	prev;		/* previous file extent record */
4811 	int		tmp_logflags;	/* temp flags holder */
4812 	int		whichfork;	/* data or attr fork */
4813 	char		inhole;		/* current location is hole in file */
4814 	char		wasdelay;	/* old extent was delayed */
4815 	char		wr;		/* this is a write request */
4816 	char		rt;		/* this is a realtime file */
4817 #ifdef DEBUG
4818 	xfs_fileoff_t	orig_bno;	/* original block number value */
4819 	int		orig_flags;	/* original flags arg value */
4820 	xfs_filblks_t	orig_len;	/* original value of len arg */
4821 	xfs_bmbt_irec_t	*orig_mval;	/* original value of mval */
4822 	int		orig_nmap;	/* original value of *nmap */
4823 
4824 	orig_bno = bno;
4825 	orig_len = len;
4826 	orig_flags = flags;
4827 	orig_mval = mval;
4828 	orig_nmap = *nmap;
4829 #endif
4830 	ASSERT(*nmap >= 1);
4831 	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
4832 	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4833 		XFS_ATTR_FORK : XFS_DATA_FORK;
4834 	mp = ip->i_mount;
4835 	if (unlikely(XFS_TEST_ERROR(
4836 	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4837 	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4838 	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
4839 	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
4840 		XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp);
4841 		return XFS_ERROR(EFSCORRUPTED);
4842 	}
4843 	if (XFS_FORCED_SHUTDOWN(mp))
4844 		return XFS_ERROR(EIO);
4845 	rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
4846 	ifp = XFS_IFORK_PTR(ip, whichfork);
4847 	ASSERT(ifp->if_ext_max ==
4848 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4849 	if ((wr = (flags & XFS_BMAPI_WRITE)) != 0)
4850 		XFS_STATS_INC(xs_blk_mapw);
4851 	else
4852 		XFS_STATS_INC(xs_blk_mapr);
4853 	/*
4854 	 * IGSTATE flag is used to combine extents which
4855 	 * differ only due to the state of the extents.
4856 	 * This technique is used from xfs_getbmap()
4857 	 * when the caller does not wish to see the
4858 	 * separation (which is the default).
4859 	 *
4860 	 * This technique is also used when writing a
4861 	 * buffer which has been partially written,
4862 	 * (usually by being flushed during a chunkread),
4863 	 * to ensure one write takes place. This also
4864 	 * prevents a change in the xfs inode extents at
4865 	 * this time, intentionally. This change occurs
4866 	 * on completion of the write operation, in
4867 	 * xfs_strat_comp(), where the xfs_bmapi() call
4868 	 * is transactioned, and the extents combined.
4869 	 */
4870 	if ((flags & XFS_BMAPI_IGSTATE) && wr)	/* if writing unwritten space */
4871 		wr = 0;				/* no allocations are allowed */
4872 	ASSERT(wr || !(flags & XFS_BMAPI_DELAY));
4873 	logflags = 0;
4874 	nallocs = 0;
4875 	cur = NULL;
4876 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4877 		ASSERT(wr && tp);
4878 		if ((error = xfs_bmap_local_to_extents(tp, ip,
4879 				firstblock, total, &logflags, whichfork)))
4880 			goto error0;
4881 	}
4882 	if (wr && *firstblock == NULLFSBLOCK) {
4883 		if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
4884 			minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
4885 		else
4886 			minleft = 1;
4887 	} else
4888 		minleft = 0;
4889 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4890 	    (error = xfs_iread_extents(tp, ip, whichfork)))
4891 		goto error0;
4892 	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4893 		&prev);
4894 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4895 	n = 0;
4896 	end = bno + len;
4897 	obno = bno;
4898 	bma.ip = NULL;
4899 	if (delta) {
4900 		delta->xed_startoff = NULLFILEOFF;
4901 		delta->xed_blockcount = 0;
4902 	}
4903 	while (bno < end && n < *nmap) {
4904 		/*
4905 		 * Reading past eof, act as though there's a hole
4906 		 * up to end.
4907 		 */
4908 		if (eof && !wr)
4909 			got.br_startoff = end;
4910 		inhole = eof || got.br_startoff > bno;
4911 		wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) &&
4912 			isnullstartblock(got.br_startblock);
4913 		/*
4914 		 * First, deal with the hole before the allocated space
4915 		 * that we found, if any.
4916 		 */
4917 		if (wr && (inhole || wasdelay)) {
4918 			/*
4919 			 * For the wasdelay case, we could also just
4920 			 * allocate the stuff asked for in this bmap call
4921 			 * but that wouldn't be as good.
4922 			 */
4923 			if (wasdelay && !(flags & XFS_BMAPI_EXACT)) {
4924 				alen = (xfs_extlen_t)got.br_blockcount;
4925 				aoff = got.br_startoff;
4926 				if (lastx != NULLEXTNUM && lastx) {
4927 					ep = xfs_iext_get_ext(ifp, lastx - 1);
4928 					xfs_bmbt_get_all(ep, &prev);
4929 				}
4930 			} else if (wasdelay) {
4931 				alen = (xfs_extlen_t)
4932 					XFS_FILBLKS_MIN(len,
4933 						(got.br_startoff +
4934 						 got.br_blockcount) - bno);
4935 				aoff = bno;
4936 			} else {
4937 				alen = (xfs_extlen_t)
4938 					XFS_FILBLKS_MIN(len, MAXEXTLEN);
4939 				if (!eof)
4940 					alen = (xfs_extlen_t)
4941 						XFS_FILBLKS_MIN(alen,
4942 							got.br_startoff - bno);
4943 				aoff = bno;
4944 			}
4945 			minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4946 			if (flags & XFS_BMAPI_DELAY) {
4947 				xfs_extlen_t	extsz;
4948 
4949 				/* Figure out the extent size, adjust alen */
4950 				extsz = xfs_get_extsz_hint(ip);
4951 				if (extsz) {
4952 					error = xfs_bmap_extsize_align(mp,
4953 							&got, &prev, extsz,
4954 							rt, eof,
4955 							flags&XFS_BMAPI_DELAY,
4956 							flags&XFS_BMAPI_CONVERT,
4957 							&aoff, &alen);
4958 					ASSERT(!error);
4959 				}
4960 
4961 				if (rt)
4962 					extsz = alen / mp->m_sb.sb_rextsize;
4963 
4964 				/*
4965 				 * Make a transaction-less quota reservation for
4966 				 * delayed allocation blocks. This number gets
4967 				 * adjusted later.  We return if we haven't
4968 				 * allocated blocks already inside this loop.
4969 				 */
4970 				if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
4971 						mp, NULL, ip, (long)alen, 0,
4972 						rt ? XFS_QMOPT_RES_RTBLKS :
4973 						     XFS_QMOPT_RES_REGBLKS))) {
4974 					if (n == 0) {
4975 						*nmap = 0;
4976 						ASSERT(cur == NULL);
4977 						return error;
4978 					}
4979 					break;
4980 				}
4981 
4982 				/*
4983 				 * Split changing sb for alen and indlen since
4984 				 * they could be coming from different places.
4985 				 */
4986 				indlen = (xfs_extlen_t)
4987 					xfs_bmap_worst_indlen(ip, alen);
4988 				ASSERT(indlen > 0);
4989 
4990 				if (rt) {
4991 					error = xfs_mod_incore_sb(mp,
4992 							XFS_SBS_FREXTENTS,
4993 							-((int64_t)extsz), (flags &
4994 							XFS_BMAPI_RSVBLOCKS));
4995 				} else {
4996 					error = xfs_mod_incore_sb(mp,
4997 							XFS_SBS_FDBLOCKS,
4998 							-((int64_t)alen), (flags &
4999 							XFS_BMAPI_RSVBLOCKS));
5000 				}
5001 				if (!error) {
5002 					error = xfs_mod_incore_sb(mp,
5003 							XFS_SBS_FDBLOCKS,
5004 							-((int64_t)indlen), (flags &
5005 							XFS_BMAPI_RSVBLOCKS));
5006 					if (error && rt)
5007 						xfs_mod_incore_sb(mp,
5008 							XFS_SBS_FREXTENTS,
5009 							(int64_t)extsz, (flags &
5010 							XFS_BMAPI_RSVBLOCKS));
5011 					else if (error)
5012 						xfs_mod_incore_sb(mp,
5013 							XFS_SBS_FDBLOCKS,
5014 							(int64_t)alen, (flags &
5015 							XFS_BMAPI_RSVBLOCKS));
5016 				}
5017 
5018 				if (error) {
5019 					if (XFS_IS_QUOTA_ON(mp))
5020 						/* unreserve the blocks now */
5021 						(void)
5022 						XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
5023 							mp, NULL, ip,
5024 							(long)alen, 0, rt ?
5025 							XFS_QMOPT_RES_RTBLKS :
5026 							XFS_QMOPT_RES_REGBLKS);
5027 					break;
5028 				}
5029 
5030 				ip->i_delayed_blks += alen;
5031 				abno = nullstartblock(indlen);
5032 			} else {
5033 				/*
5034 				 * If first time, allocate and fill in
5035 				 * once-only bma fields.
5036 				 */
5037 				if (bma.ip == NULL) {
5038 					bma.tp = tp;
5039 					bma.ip = ip;
5040 					bma.prevp = &prev;
5041 					bma.gotp = &got;
5042 					bma.total = total;
5043 					bma.userdata = 0;
5044 				}
5045 				/* Indicate if this is the first user data
5046 				 * in the file, or just any user data.
5047 				 */
5048 				if (!(flags & XFS_BMAPI_METADATA)) {
5049 					bma.userdata = (aoff == 0) ?
5050 						XFS_ALLOC_INITIAL_USER_DATA :
5051 						XFS_ALLOC_USERDATA;
5052 				}
5053 				/*
5054 				 * Fill in changeable bma fields.
5055 				 */
5056 				bma.eof = eof;
5057 				bma.firstblock = *firstblock;
5058 				bma.alen = alen;
5059 				bma.off = aoff;
5060 				bma.conv = !!(flags & XFS_BMAPI_CONVERT);
5061 				bma.wasdel = wasdelay;
5062 				bma.minlen = minlen;
5063 				bma.low = flist->xbf_low;
5064 				bma.minleft = minleft;
5065 				/*
5066 				 * Only want to do the alignment at the
5067 				 * eof if it is userdata and allocation length
5068 				 * is larger than a stripe unit.
5069 				 */
5070 				if (mp->m_dalign && alen >= mp->m_dalign &&
5071 				    (!(flags & XFS_BMAPI_METADATA)) &&
5072 				    (whichfork == XFS_DATA_FORK)) {
5073 					if ((error = xfs_bmap_isaeof(ip, aoff,
5074 							whichfork, &bma.aeof)))
5075 						goto error0;
5076 				} else
5077 					bma.aeof = 0;
5078 				/*
5079 				 * Call allocator.
5080 				 */
5081 				if ((error = xfs_bmap_alloc(&bma)))
5082 					goto error0;
5083 				/*
5084 				 * Copy out result fields.
5085 				 */
5086 				abno = bma.rval;
5087 				if ((flist->xbf_low = bma.low))
5088 					minleft = 0;
5089 				alen = bma.alen;
5090 				aoff = bma.off;
5091 				ASSERT(*firstblock == NULLFSBLOCK ||
5092 				       XFS_FSB_TO_AGNO(mp, *firstblock) ==
5093 				       XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
5094 				       (flist->xbf_low &&
5095 					XFS_FSB_TO_AGNO(mp, *firstblock) <
5096 					XFS_FSB_TO_AGNO(mp, bma.firstblock)));
5097 				*firstblock = bma.firstblock;
5098 				if (cur)
5099 					cur->bc_private.b.firstblock =
5100 						*firstblock;
5101 				if (abno == NULLFSBLOCK)
5102 					break;
5103 				if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5104 					cur = xfs_bmbt_init_cursor(mp, tp,
5105 						ip, whichfork);
5106 					cur->bc_private.b.firstblock =
5107 						*firstblock;
5108 					cur->bc_private.b.flist = flist;
5109 				}
5110 				/*
5111 				 * Bump the number of extents we've allocated
5112 				 * in this call.
5113 				 */
5114 				nallocs++;
5115 			}
5116 			if (cur)
5117 				cur->bc_private.b.flags =
5118 					wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
5119 			got.br_startoff = aoff;
5120 			got.br_startblock = abno;
5121 			got.br_blockcount = alen;
5122 			got.br_state = XFS_EXT_NORM;	/* assume normal */
5123 			/*
5124 			 * Determine state of extent, and the filesystem.
5125 			 * A wasdelay extent has been initialized, so
5126 			 * shouldn't be flagged as unwritten.
5127 			 */
5128 			if (wr && xfs_sb_version_hasextflgbit(&mp->m_sb)) {
5129 				if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
5130 					got.br_state = XFS_EXT_UNWRITTEN;
5131 			}
5132 			error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
5133 				firstblock, flist, &tmp_logflags, delta,
5134 				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
5135 			logflags |= tmp_logflags;
5136 			if (error)
5137 				goto error0;
5138 			lastx = ifp->if_lastex;
5139 			ep = xfs_iext_get_ext(ifp, lastx);
5140 			nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5141 			xfs_bmbt_get_all(ep, &got);
5142 			ASSERT(got.br_startoff <= aoff);
5143 			ASSERT(got.br_startoff + got.br_blockcount >=
5144 				aoff + alen);
5145 #ifdef DEBUG
5146 			if (flags & XFS_BMAPI_DELAY) {
5147 				ASSERT(isnullstartblock(got.br_startblock));
5148 				ASSERT(startblockval(got.br_startblock) > 0);
5149 			}
5150 			ASSERT(got.br_state == XFS_EXT_NORM ||
5151 			       got.br_state == XFS_EXT_UNWRITTEN);
5152 #endif
5153 			/*
5154 			 * Fall down into the found allocated space case.
5155 			 */
5156 		} else if (inhole) {
5157 			/*
5158 			 * Reading in a hole.
5159 			 */
5160 			mval->br_startoff = bno;
5161 			mval->br_startblock = HOLESTARTBLOCK;
5162 			mval->br_blockcount =
5163 				XFS_FILBLKS_MIN(len, got.br_startoff - bno);
5164 			mval->br_state = XFS_EXT_NORM;
5165 			bno += mval->br_blockcount;
5166 			len -= mval->br_blockcount;
5167 			mval++;
5168 			n++;
5169 			continue;
5170 		}
5171 		/*
5172 		 * Then deal with the allocated space we found.
5173 		 */
5174 		ASSERT(ep != NULL);
5175 		if (!(flags & XFS_BMAPI_ENTIRE) &&
5176 		    (got.br_startoff + got.br_blockcount > obno)) {
5177 			if (obno > bno)
5178 				bno = obno;
5179 			ASSERT((bno >= obno) || (n == 0));
5180 			ASSERT(bno < end);
5181 			mval->br_startoff = bno;
5182 			if (isnullstartblock(got.br_startblock)) {
5183 				ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
5184 				mval->br_startblock = DELAYSTARTBLOCK;
5185 			} else
5186 				mval->br_startblock =
5187 					got.br_startblock +
5188 					(bno - got.br_startoff);
5189 			/*
5190 			 * Return the minimum of what we got and what we
5191 			 * asked for for the length.  We can use the len
5192 			 * variable here because it is modified below
5193 			 * and we could have been there before coming
5194 			 * here if the first part of the allocation
5195 			 * didn't overlap what was asked for.
5196 			 */
5197 			mval->br_blockcount =
5198 				XFS_FILBLKS_MIN(end - bno, got.br_blockcount -
5199 					(bno - got.br_startoff));
5200 			mval->br_state = got.br_state;
5201 			ASSERT(mval->br_blockcount <= len);
5202 		} else {
5203 			*mval = got;
5204 			if (isnullstartblock(mval->br_startblock)) {
5205 				ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
5206 				mval->br_startblock = DELAYSTARTBLOCK;
5207 			}
5208 		}
5209 
5210 		/*
5211 		 * Check if writing previously allocated but
5212 		 * unwritten extents.
5213 		 */
5214 		if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
5215 		    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
5216 			/*
5217 			 * Modify (by adding) the state flag, if writing.
5218 			 */
5219 			ASSERT(mval->br_blockcount <= len);
5220 			if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5221 				cur = xfs_bmbt_init_cursor(mp,
5222 					tp, ip, whichfork);
5223 				cur->bc_private.b.firstblock =
5224 					*firstblock;
5225 				cur->bc_private.b.flist = flist;
5226 			}
5227 			mval->br_state = XFS_EXT_NORM;
5228 			error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
5229 				firstblock, flist, &tmp_logflags, delta,
5230 				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
5231 			logflags |= tmp_logflags;
5232 			if (error)
5233 				goto error0;
5234 			lastx = ifp->if_lastex;
5235 			ep = xfs_iext_get_ext(ifp, lastx);
5236 			nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5237 			xfs_bmbt_get_all(ep, &got);
5238 			/*
5239 			 * We may have combined previously unwritten
5240 			 * space with written space, so generate
5241 			 * another request.
5242 			 */
5243 			if (mval->br_blockcount < len)
5244 				continue;
5245 		}
5246 
5247 		ASSERT((flags & XFS_BMAPI_ENTIRE) ||
5248 		       ((mval->br_startoff + mval->br_blockcount) <= end));
5249 		ASSERT((flags & XFS_BMAPI_ENTIRE) ||
5250 		       (mval->br_blockcount <= len) ||
5251 		       (mval->br_startoff < obno));
5252 		bno = mval->br_startoff + mval->br_blockcount;
5253 		len = end - bno;
5254 		if (n > 0 && mval->br_startoff == mval[-1].br_startoff) {
5255 			ASSERT(mval->br_startblock == mval[-1].br_startblock);
5256 			ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
5257 			ASSERT(mval->br_state == mval[-1].br_state);
5258 			mval[-1].br_blockcount = mval->br_blockcount;
5259 			mval[-1].br_state = mval->br_state;
5260 		} else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
5261 			   mval[-1].br_startblock != DELAYSTARTBLOCK &&
5262 			   mval[-1].br_startblock != HOLESTARTBLOCK &&
5263 			   mval->br_startblock ==
5264 			   mval[-1].br_startblock + mval[-1].br_blockcount &&
5265 			   ((flags & XFS_BMAPI_IGSTATE) ||
5266 				mval[-1].br_state == mval->br_state)) {
5267 			ASSERT(mval->br_startoff ==
5268 			       mval[-1].br_startoff + mval[-1].br_blockcount);
5269 			mval[-1].br_blockcount += mval->br_blockcount;
5270 		} else if (n > 0 &&
5271 			   mval->br_startblock == DELAYSTARTBLOCK &&
5272 			   mval[-1].br_startblock == DELAYSTARTBLOCK &&
5273 			   mval->br_startoff ==
5274 			   mval[-1].br_startoff + mval[-1].br_blockcount) {
5275 			mval[-1].br_blockcount += mval->br_blockcount;
5276 			mval[-1].br_state = mval->br_state;
5277 		} else if (!((n == 0) &&
5278 			     ((mval->br_startoff + mval->br_blockcount) <=
5279 			      obno))) {
5280 			mval++;
5281 			n++;
5282 		}
5283 		/*
5284 		 * If we're done, stop now.  Stop when we've allocated
5285 		 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
5286 		 * the transaction may get too big.
5287 		 */
5288 		if (bno >= end || n >= *nmap || nallocs >= *nmap)
5289 			break;
5290 		/*
5291 		 * Else go on to the next record.
5292 		 */
5293 		ep = xfs_iext_get_ext(ifp, ++lastx);
5294 		prev = got;
5295 		if (lastx >= nextents)
5296 			eof = 1;
5297 		else
5298 			xfs_bmbt_get_all(ep, &got);
5299 	}
5300 	ifp->if_lastex = lastx;
5301 	*nmap = n;
5302 	/*
5303 	 * Transform from btree to extents, give it cur.
5304 	 */
5305 	if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5306 	    XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5307 		ASSERT(wr && cur);
5308 		error = xfs_bmap_btree_to_extents(tp, ip, cur,
5309 			&tmp_logflags, whichfork);
5310 		logflags |= tmp_logflags;
5311 		if (error)
5312 			goto error0;
5313 	}
5314 	ASSERT(ifp->if_ext_max ==
5315 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5316 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
5317 	       XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
5318 	error = 0;
5319 	if (delta && delta->xed_startoff != NULLFILEOFF) {
5320 		/* A change was actually made.
5321 		 * Note that delta->xed_blockount is an offset at this
5322 		 * point and needs to be converted to a block count.
5323 		 */
5324 		ASSERT(delta->xed_blockcount > delta->xed_startoff);
5325 		delta->xed_blockcount -= delta->xed_startoff;
5326 	}
5327 error0:
5328 	/*
5329 	 * Log everything.  Do this after conversion, there's no point in
5330 	 * logging the extent records if we've converted to btree format.
5331 	 */
5332 	if ((logflags & xfs_ilog_fext(whichfork)) &&
5333 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
5334 		logflags &= ~xfs_ilog_fext(whichfork);
5335 	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
5336 		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
5337 		logflags &= ~xfs_ilog_fbroot(whichfork);
5338 	/*
5339 	 * Log whatever the flags say, even if error.  Otherwise we might miss
5340 	 * detecting a case where the data is changed, there's an error,
5341 	 * and it's not logged so we don't shutdown when we should.
5342 	 */
5343 	if (logflags) {
5344 		ASSERT(tp && wr);
5345 		xfs_trans_log_inode(tp, ip, logflags);
5346 	}
5347 	if (cur) {
5348 		if (!error) {
5349 			ASSERT(*firstblock == NULLFSBLOCK ||
5350 			       XFS_FSB_TO_AGNO(mp, *firstblock) ==
5351 			       XFS_FSB_TO_AGNO(mp,
5352 				       cur->bc_private.b.firstblock) ||
5353 			       (flist->xbf_low &&
5354 				XFS_FSB_TO_AGNO(mp, *firstblock) <
5355 				XFS_FSB_TO_AGNO(mp,
5356 					cur->bc_private.b.firstblock)));
5357 			*firstblock = cur->bc_private.b.firstblock;
5358 		}
5359 		xfs_btree_del_cursor(cur,
5360 			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5361 	}
5362 	if (!error)
5363 		xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
5364 			orig_nmap, *nmap);
5365 	return error;
5366 }
5367 
5368 /*
5369  * Map file blocks to filesystem blocks, simple version.
5370  * One block (extent) only, read-only.
5371  * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
5372  * For the other flag values, the effect is as if XFS_BMAPI_METADATA
5373  * was set and all the others were clear.
5374  */
5375 int						/* error */
xfs_bmapi_single(xfs_trans_t * tp,xfs_inode_t * ip,int whichfork,xfs_fsblock_t * fsb,xfs_fileoff_t bno)5376 xfs_bmapi_single(
5377 	xfs_trans_t	*tp,		/* transaction pointer */
5378 	xfs_inode_t	*ip,		/* incore inode */
5379 	int		whichfork,	/* data or attr fork */
5380 	xfs_fsblock_t	*fsb,		/* output: mapped block */
5381 	xfs_fileoff_t	bno)		/* starting file offs. mapped */
5382 {
5383 	int		eof;		/* we've hit the end of extents */
5384 	int		error;		/* error return */
5385 	xfs_bmbt_irec_t	got;		/* current file extent record */
5386 	xfs_ifork_t	*ifp;		/* inode fork pointer */
5387 	xfs_extnum_t	lastx;		/* last useful extent number */
5388 	xfs_bmbt_irec_t	prev;		/* previous file extent record */
5389 
5390 	ifp = XFS_IFORK_PTR(ip, whichfork);
5391 	if (unlikely(
5392 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
5393 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) {
5394 	       XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW,
5395 				ip->i_mount);
5396 	       return XFS_ERROR(EFSCORRUPTED);
5397 	}
5398 	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
5399 		return XFS_ERROR(EIO);
5400 	XFS_STATS_INC(xs_blk_mapr);
5401 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5402 	    (error = xfs_iread_extents(tp, ip, whichfork)))
5403 		return error;
5404 	(void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5405 		&prev);
5406 	/*
5407 	 * Reading past eof, act as though there's a hole
5408 	 * up to end.
5409 	 */
5410 	if (eof || got.br_startoff > bno) {
5411 		*fsb = NULLFSBLOCK;
5412 		return 0;
5413 	}
5414 	ASSERT(!isnullstartblock(got.br_startblock));
5415 	ASSERT(bno < got.br_startoff + got.br_blockcount);
5416 	*fsb = got.br_startblock + (bno - got.br_startoff);
5417 	ifp->if_lastex = lastx;
5418 	return 0;
5419 }
5420 
5421 /*
5422  * Unmap (remove) blocks from a file.
5423  * If nexts is nonzero then the number of extents to remove is limited to
5424  * that value.  If not all extents in the block range can be removed then
5425  * *done is set.
5426  */
5427 int						/* error */
xfs_bunmapi(xfs_trans_t * tp,struct xfs_inode * ip,xfs_fileoff_t bno,xfs_filblks_t len,int flags,xfs_extnum_t nexts,xfs_fsblock_t * firstblock,xfs_bmap_free_t * flist,xfs_extdelta_t * delta,int * done)5428 xfs_bunmapi(
5429 	xfs_trans_t		*tp,		/* transaction pointer */
5430 	struct xfs_inode	*ip,		/* incore inode */
5431 	xfs_fileoff_t		bno,		/* starting offset to unmap */
5432 	xfs_filblks_t		len,		/* length to unmap in file */
5433 	int			flags,		/* misc flags */
5434 	xfs_extnum_t		nexts,		/* number of extents max */
5435 	xfs_fsblock_t		*firstblock,	/* first allocated block
5436 						   controls a.g. for allocs */
5437 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
5438 	xfs_extdelta_t		*delta,		/* o: change made to incore
5439 						   extents */
5440 	int			*done)		/* set if not done yet */
5441 {
5442 	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
5443 	xfs_bmbt_irec_t		del;		/* extent being deleted */
5444 	int			eof;		/* is deleting at eof */
5445 	xfs_bmbt_rec_host_t	*ep;		/* extent record pointer */
5446 	int			error;		/* error return value */
5447 	xfs_extnum_t		extno;		/* extent number in list */
5448 	xfs_bmbt_irec_t		got;		/* current extent record */
5449 	xfs_ifork_t		*ifp;		/* inode fork pointer */
5450 	int			isrt;		/* freeing in rt area */
5451 	xfs_extnum_t		lastx;		/* last extent index used */
5452 	int			logflags;	/* transaction logging flags */
5453 	xfs_extlen_t		mod;		/* rt extent offset */
5454 	xfs_mount_t		*mp;		/* mount structure */
5455 	xfs_extnum_t		nextents;	/* number of file extents */
5456 	xfs_bmbt_irec_t		prev;		/* previous extent record */
5457 	xfs_fileoff_t		start;		/* first file offset deleted */
5458 	int			tmp_logflags;	/* partial logging flags */
5459 	int			wasdel;		/* was a delayed alloc extent */
5460 	int			whichfork;	/* data or attribute fork */
5461 	int			rsvd;		/* OK to allocate reserved blocks */
5462 	xfs_fsblock_t		sum;
5463 
5464 	xfs_bunmap_trace(ip, bno, len, flags, (inst_t *)__return_address);
5465 	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
5466 		XFS_ATTR_FORK : XFS_DATA_FORK;
5467 	ifp = XFS_IFORK_PTR(ip, whichfork);
5468 	if (unlikely(
5469 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
5470 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
5471 		XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
5472 				 ip->i_mount);
5473 		return XFS_ERROR(EFSCORRUPTED);
5474 	}
5475 	mp = ip->i_mount;
5476 	if (XFS_FORCED_SHUTDOWN(mp))
5477 		return XFS_ERROR(EIO);
5478 	rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
5479 	ASSERT(len > 0);
5480 	ASSERT(nexts >= 0);
5481 	ASSERT(ifp->if_ext_max ==
5482 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5483 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5484 	    (error = xfs_iread_extents(tp, ip, whichfork)))
5485 		return error;
5486 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5487 	if (nextents == 0) {
5488 		*done = 1;
5489 		return 0;
5490 	}
5491 	XFS_STATS_INC(xs_blk_unmap);
5492 	isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
5493 	start = bno;
5494 	bno = start + len - 1;
5495 	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5496 		&prev);
5497 	if (delta) {
5498 		delta->xed_startoff = NULLFILEOFF;
5499 		delta->xed_blockcount = 0;
5500 	}
5501 	/*
5502 	 * Check to see if the given block number is past the end of the
5503 	 * file, back up to the last block if so...
5504 	 */
5505 	if (eof) {
5506 		ep = xfs_iext_get_ext(ifp, --lastx);
5507 		xfs_bmbt_get_all(ep, &got);
5508 		bno = got.br_startoff + got.br_blockcount - 1;
5509 	}
5510 	logflags = 0;
5511 	if (ifp->if_flags & XFS_IFBROOT) {
5512 		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
5513 		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
5514 		cur->bc_private.b.firstblock = *firstblock;
5515 		cur->bc_private.b.flist = flist;
5516 		cur->bc_private.b.flags = 0;
5517 	} else
5518 		cur = NULL;
5519 	extno = 0;
5520 	while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
5521 	       (nexts == 0 || extno < nexts)) {
5522 		/*
5523 		 * Is the found extent after a hole in which bno lives?
5524 		 * Just back up to the previous extent, if so.
5525 		 */
5526 		if (got.br_startoff > bno) {
5527 			if (--lastx < 0)
5528 				break;
5529 			ep = xfs_iext_get_ext(ifp, lastx);
5530 			xfs_bmbt_get_all(ep, &got);
5531 		}
5532 		/*
5533 		 * Is the last block of this extent before the range
5534 		 * we're supposed to delete?  If so, we're done.
5535 		 */
5536 		bno = XFS_FILEOFF_MIN(bno,
5537 			got.br_startoff + got.br_blockcount - 1);
5538 		if (bno < start)
5539 			break;
5540 		/*
5541 		 * Then deal with the (possibly delayed) allocated space
5542 		 * we found.
5543 		 */
5544 		ASSERT(ep != NULL);
5545 		del = got;
5546 		wasdel = isnullstartblock(del.br_startblock);
5547 		if (got.br_startoff < start) {
5548 			del.br_startoff = start;
5549 			del.br_blockcount -= start - got.br_startoff;
5550 			if (!wasdel)
5551 				del.br_startblock += start - got.br_startoff;
5552 		}
5553 		if (del.br_startoff + del.br_blockcount > bno + 1)
5554 			del.br_blockcount = bno + 1 - del.br_startoff;
5555 		sum = del.br_startblock + del.br_blockcount;
5556 		if (isrt &&
5557 		    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
5558 			/*
5559 			 * Realtime extent not lined up at the end.
5560 			 * The extent could have been split into written
5561 			 * and unwritten pieces, or we could just be
5562 			 * unmapping part of it.  But we can't really
5563 			 * get rid of part of a realtime extent.
5564 			 */
5565 			if (del.br_state == XFS_EXT_UNWRITTEN ||
5566 			    !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
5567 				/*
5568 				 * This piece is unwritten, or we're not
5569 				 * using unwritten extents.  Skip over it.
5570 				 */
5571 				ASSERT(bno >= mod);
5572 				bno -= mod > del.br_blockcount ?
5573 					del.br_blockcount : mod;
5574 				if (bno < got.br_startoff) {
5575 					if (--lastx >= 0)
5576 						xfs_bmbt_get_all(xfs_iext_get_ext(
5577 							ifp, lastx), &got);
5578 				}
5579 				continue;
5580 			}
5581 			/*
5582 			 * It's written, turn it unwritten.
5583 			 * This is better than zeroing it.
5584 			 */
5585 			ASSERT(del.br_state == XFS_EXT_NORM);
5586 			ASSERT(xfs_trans_get_block_res(tp) > 0);
5587 			/*
5588 			 * If this spans a realtime extent boundary,
5589 			 * chop it back to the start of the one we end at.
5590 			 */
5591 			if (del.br_blockcount > mod) {
5592 				del.br_startoff += del.br_blockcount - mod;
5593 				del.br_startblock += del.br_blockcount - mod;
5594 				del.br_blockcount = mod;
5595 			}
5596 			del.br_state = XFS_EXT_UNWRITTEN;
5597 			error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
5598 				firstblock, flist, &logflags, delta,
5599 				XFS_DATA_FORK, 0);
5600 			if (error)
5601 				goto error0;
5602 			goto nodelete;
5603 		}
5604 		if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
5605 			/*
5606 			 * Realtime extent is lined up at the end but not
5607 			 * at the front.  We'll get rid of full extents if
5608 			 * we can.
5609 			 */
5610 			mod = mp->m_sb.sb_rextsize - mod;
5611 			if (del.br_blockcount > mod) {
5612 				del.br_blockcount -= mod;
5613 				del.br_startoff += mod;
5614 				del.br_startblock += mod;
5615 			} else if ((del.br_startoff == start &&
5616 				    (del.br_state == XFS_EXT_UNWRITTEN ||
5617 				     xfs_trans_get_block_res(tp) == 0)) ||
5618 				   !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
5619 				/*
5620 				 * Can't make it unwritten.  There isn't
5621 				 * a full extent here so just skip it.
5622 				 */
5623 				ASSERT(bno >= del.br_blockcount);
5624 				bno -= del.br_blockcount;
5625 				if (bno < got.br_startoff) {
5626 					if (--lastx >= 0)
5627 						xfs_bmbt_get_all(--ep, &got);
5628 				}
5629 				continue;
5630 			} else if (del.br_state == XFS_EXT_UNWRITTEN) {
5631 				/*
5632 				 * This one is already unwritten.
5633 				 * It must have a written left neighbor.
5634 				 * Unwrite the killed part of that one and
5635 				 * try again.
5636 				 */
5637 				ASSERT(lastx > 0);
5638 				xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
5639 						lastx - 1), &prev);
5640 				ASSERT(prev.br_state == XFS_EXT_NORM);
5641 				ASSERT(!isnullstartblock(prev.br_startblock));
5642 				ASSERT(del.br_startblock ==
5643 				       prev.br_startblock + prev.br_blockcount);
5644 				if (prev.br_startoff < start) {
5645 					mod = start - prev.br_startoff;
5646 					prev.br_blockcount -= mod;
5647 					prev.br_startblock += mod;
5648 					prev.br_startoff = start;
5649 				}
5650 				prev.br_state = XFS_EXT_UNWRITTEN;
5651 				error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
5652 					&prev, firstblock, flist, &logflags,
5653 					delta, XFS_DATA_FORK, 0);
5654 				if (error)
5655 					goto error0;
5656 				goto nodelete;
5657 			} else {
5658 				ASSERT(del.br_state == XFS_EXT_NORM);
5659 				del.br_state = XFS_EXT_UNWRITTEN;
5660 				error = xfs_bmap_add_extent(ip, lastx, &cur,
5661 					&del, firstblock, flist, &logflags,
5662 					delta, XFS_DATA_FORK, 0);
5663 				if (error)
5664 					goto error0;
5665 				goto nodelete;
5666 			}
5667 		}
5668 		if (wasdel) {
5669 			ASSERT(startblockval(del.br_startblock) > 0);
5670 			/* Update realtime/data freespace, unreserve quota */
5671 			if (isrt) {
5672 				xfs_filblks_t rtexts;
5673 
5674 				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5675 				do_div(rtexts, mp->m_sb.sb_rextsize);
5676 				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
5677 						(int64_t)rtexts, rsvd);
5678 				(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
5679 					NULL, ip, -((long)del.br_blockcount), 0,
5680 					XFS_QMOPT_RES_RTBLKS);
5681 			} else {
5682 				xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
5683 						(int64_t)del.br_blockcount, rsvd);
5684 				(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
5685 					NULL, ip, -((long)del.br_blockcount), 0,
5686 					XFS_QMOPT_RES_REGBLKS);
5687 			}
5688 			ip->i_delayed_blks -= del.br_blockcount;
5689 			if (cur)
5690 				cur->bc_private.b.flags |=
5691 					XFS_BTCUR_BPRV_WASDEL;
5692 		} else if (cur)
5693 			cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
5694 		/*
5695 		 * If it's the case where the directory code is running
5696 		 * with no block reservation, and the deleted block is in
5697 		 * the middle of its extent, and the resulting insert
5698 		 * of an extent would cause transformation to btree format,
5699 		 * then reject it.  The calling code will then swap
5700 		 * blocks around instead.
5701 		 * We have to do this now, rather than waiting for the
5702 		 * conversion to btree format, since the transaction
5703 		 * will be dirty.
5704 		 */
5705 		if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
5706 		    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
5707 		    XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
5708 		    del.br_startoff > got.br_startoff &&
5709 		    del.br_startoff + del.br_blockcount <
5710 		    got.br_startoff + got.br_blockcount) {
5711 			error = XFS_ERROR(ENOSPC);
5712 			goto error0;
5713 		}
5714 		error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
5715 				&tmp_logflags, delta, whichfork, rsvd);
5716 		logflags |= tmp_logflags;
5717 		if (error)
5718 			goto error0;
5719 		bno = del.br_startoff - 1;
5720 nodelete:
5721 		lastx = ifp->if_lastex;
5722 		/*
5723 		 * If not done go on to the next (previous) record.
5724 		 * Reset ep in case the extents array was re-alloced.
5725 		 */
5726 		ep = xfs_iext_get_ext(ifp, lastx);
5727 		if (bno != (xfs_fileoff_t)-1 && bno >= start) {
5728 			if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) ||
5729 			    xfs_bmbt_get_startoff(ep) > bno) {
5730 				if (--lastx >= 0)
5731 					ep = xfs_iext_get_ext(ifp, lastx);
5732 			}
5733 			if (lastx >= 0)
5734 				xfs_bmbt_get_all(ep, &got);
5735 			extno++;
5736 		}
5737 	}
5738 	ifp->if_lastex = lastx;
5739 	*done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
5740 	ASSERT(ifp->if_ext_max ==
5741 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5742 	/*
5743 	 * Convert to a btree if necessary.
5744 	 */
5745 	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
5746 	    XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
5747 		ASSERT(cur == NULL);
5748 		error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
5749 			&cur, 0, &tmp_logflags, whichfork);
5750 		logflags |= tmp_logflags;
5751 		if (error)
5752 			goto error0;
5753 	}
5754 	/*
5755 	 * transform from btree to extents, give it cur
5756 	 */
5757 	else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5758 		 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5759 		ASSERT(cur != NULL);
5760 		error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
5761 			whichfork);
5762 		logflags |= tmp_logflags;
5763 		if (error)
5764 			goto error0;
5765 	}
5766 	/*
5767 	 * transform from extents to local?
5768 	 */
5769 	ASSERT(ifp->if_ext_max ==
5770 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5771 	error = 0;
5772 	if (delta && delta->xed_startoff != NULLFILEOFF) {
5773 		/* A change was actually made.
5774 		 * Note that delta->xed_blockount is an offset at this
5775 		 * point and needs to be converted to a block count.
5776 		 */
5777 		ASSERT(delta->xed_blockcount > delta->xed_startoff);
5778 		delta->xed_blockcount -= delta->xed_startoff;
5779 	}
5780 error0:
5781 	/*
5782 	 * Log everything.  Do this after conversion, there's no point in
5783 	 * logging the extent records if we've converted to btree format.
5784 	 */
5785 	if ((logflags & xfs_ilog_fext(whichfork)) &&
5786 	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
5787 		logflags &= ~xfs_ilog_fext(whichfork);
5788 	else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
5789 		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
5790 		logflags &= ~xfs_ilog_fbroot(whichfork);
5791 	/*
5792 	 * Log inode even in the error case, if the transaction
5793 	 * is dirty we'll need to shut down the filesystem.
5794 	 */
5795 	if (logflags)
5796 		xfs_trans_log_inode(tp, ip, logflags);
5797 	if (cur) {
5798 		if (!error) {
5799 			*firstblock = cur->bc_private.b.firstblock;
5800 			cur->bc_private.b.allocated = 0;
5801 		}
5802 		xfs_btree_del_cursor(cur,
5803 			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5804 	}
5805 	return error;
5806 }
5807 
5808 /*
5809  * returns 1 for success, 0 if we failed to map the extent.
5810  */
5811 STATIC int
xfs_getbmapx_fix_eof_hole(xfs_inode_t * ip,struct getbmapx * out,int prealloced,__int64_t end,xfs_fsblock_t startblock)5812 xfs_getbmapx_fix_eof_hole(
5813 	xfs_inode_t		*ip,		/* xfs incore inode pointer */
5814 	struct getbmapx		*out,		/* output structure */
5815 	int			prealloced,	/* this is a file with
5816 						 * preallocated data space */
5817 	__int64_t		end,		/* last block requested */
5818 	xfs_fsblock_t		startblock)
5819 {
5820 	__int64_t		fixlen;
5821 	xfs_mount_t		*mp;		/* file system mount point */
5822 	xfs_ifork_t		*ifp;		/* inode fork pointer */
5823 	xfs_extnum_t		lastx;		/* last extent pointer */
5824 	xfs_fileoff_t		fileblock;
5825 
5826 	if (startblock == HOLESTARTBLOCK) {
5827 		mp = ip->i_mount;
5828 		out->bmv_block = -1;
5829 		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
5830 		fixlen -= out->bmv_offset;
5831 		if (prealloced && out->bmv_offset + out->bmv_length == end) {
5832 			/* Came to hole at EOF. Trim it. */
5833 			if (fixlen <= 0)
5834 				return 0;
5835 			out->bmv_length = fixlen;
5836 		}
5837 	} else {
5838 		if (startblock == DELAYSTARTBLOCK)
5839 			out->bmv_block = -2;
5840 		else
5841 			out->bmv_block = xfs_fsb_to_db(ip, startblock);
5842 		fileblock = XFS_BB_TO_FSB(ip->i_mount, out->bmv_offset);
5843 		ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
5844 		if (xfs_iext_bno_to_ext(ifp, fileblock, &lastx) &&
5845 		   (lastx == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))-1))
5846 			out->bmv_oflags |= BMV_OF_LAST;
5847 	}
5848 
5849 	return 1;
5850 }
5851 
5852 /*
5853  * Get inode's extents as described in bmv, and format for output.
5854  * Calls formatter to fill the user's buffer until all extents
5855  * are mapped, until the passed-in bmv->bmv_count slots have
5856  * been filled, or until the formatter short-circuits the loop,
5857  * if it is tracking filled-in extents on its own.
5858  */
5859 int						/* error code */
xfs_getbmap(xfs_inode_t * ip,struct getbmapx * bmv,xfs_bmap_format_t formatter,void * arg)5860 xfs_getbmap(
5861 	xfs_inode_t		*ip,
5862 	struct getbmapx		*bmv,		/* user bmap structure */
5863 	xfs_bmap_format_t	formatter,	/* format to user */
5864 	void			*arg)		/* formatter arg */
5865 {
5866 	__int64_t		bmvend;		/* last block requested */
5867 	int			error;		/* return value */
5868 	__int64_t		fixlen;		/* length for -1 case */
5869 	int			i;		/* extent number */
5870 	int			lock;		/* lock state */
5871 	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
5872 	xfs_mount_t		*mp;		/* file system mount point */
5873 	int			nex;		/* # of user extents can do */
5874 	int			nexleft;	/* # of user extents left */
5875 	int			subnex;		/* # of bmapi's can do */
5876 	int			nmap;		/* number of map entries */
5877 	struct getbmapx		out;		/* output structure */
5878 	int			whichfork;	/* data or attr fork */
5879 	int			prealloced;	/* this is a file with
5880 						 * preallocated data space */
5881 	int			iflags;		/* interface flags */
5882 	int			bmapi_flags;	/* flags for xfs_bmapi */
5883 
5884 	mp = ip->i_mount;
5885 	iflags = bmv->bmv_iflags;
5886 
5887 	whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
5888 
5889 	/*	If the BMV_IF_NO_DMAPI_READ interface bit specified, do not
5890 	 *	generate a DMAPI read event.  Otherwise, if the DM_EVENT_READ
5891 	 *	bit is set for the file, generate a read event in order
5892 	 *	that the DMAPI application may do its thing before we return
5893 	 *	the extents.  Usually this means restoring user file data to
5894 	 *	regions of the file that look like holes.
5895 	 *
5896 	 *	The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
5897 	 *	BMV_IF_NO_DMAPI_READ so that read events are generated.
5898 	 *	If this were not true, callers of ioctl( XFS_IOC_GETBMAP )
5899 	 *	could misinterpret holes in a DMAPI file as true holes,
5900 	 *	when in fact they may represent offline user data.
5901 	 */
5902 	if ((iflags & BMV_IF_NO_DMAPI_READ) == 0 &&
5903 	    DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
5904 	    whichfork == XFS_DATA_FORK) {
5905 		error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
5906 		if (error)
5907 			return XFS_ERROR(error);
5908 	}
5909 
5910 	if (whichfork == XFS_ATTR_FORK) {
5911 		if (XFS_IFORK_Q(ip)) {
5912 			if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
5913 			    ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
5914 			    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
5915 				return XFS_ERROR(EINVAL);
5916 		} else if (unlikely(
5917 			   ip->i_d.di_aformat != 0 &&
5918 			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
5919 			XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
5920 					 ip->i_mount);
5921 			return XFS_ERROR(EFSCORRUPTED);
5922 		}
5923 	} else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
5924 		   ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
5925 		   ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
5926 		return XFS_ERROR(EINVAL);
5927 	if (whichfork == XFS_DATA_FORK) {
5928 		if (xfs_get_extsz_hint(ip) ||
5929 		    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
5930 			prealloced = 1;
5931 			fixlen = XFS_MAXIOFFSET(mp);
5932 		} else {
5933 			prealloced = 0;
5934 			fixlen = ip->i_size;
5935 		}
5936 	} else {
5937 		prealloced = 0;
5938 		fixlen = 1LL << 32;
5939 	}
5940 
5941 	if (bmv->bmv_length == -1) {
5942 		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
5943 		bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset),
5944 					(__int64_t)0);
5945 	} else if (bmv->bmv_length < 0)
5946 		return XFS_ERROR(EINVAL);
5947 	if (bmv->bmv_length == 0) {
5948 		bmv->bmv_entries = 0;
5949 		return 0;
5950 	}
5951 	nex = bmv->bmv_count - 1;
5952 	if (nex <= 0)
5953 		return XFS_ERROR(EINVAL);
5954 	bmvend = bmv->bmv_offset + bmv->bmv_length;
5955 
5956 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
5957 
5958 	if (((iflags & BMV_IF_DELALLOC) == 0) &&
5959 	    (whichfork == XFS_DATA_FORK) &&
5960 	    (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
5961 		/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
5962 		error = xfs_flush_pages(ip, (xfs_off_t)0,
5963 					       -1, 0, FI_REMAPF);
5964 		if (error) {
5965 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
5966 		return error;
5967 		}
5968 	}
5969 
5970 	ASSERT(whichfork == XFS_ATTR_FORK || (iflags & BMV_IF_DELALLOC) ||
5971 	       ip->i_delayed_blks == 0);
5972 
5973 	lock = xfs_ilock_map_shared(ip);
5974 
5975 	/*
5976 	 * Don't let nex be bigger than the number of extents
5977 	 * we can have assuming alternating holes and real extents.
5978 	 */
5979 	if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
5980 		nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
5981 
5982 	bmapi_flags = xfs_bmapi_aflag(whichfork) |
5983 			((iflags & BMV_IF_PREALLOC) ? 0 : XFS_BMAPI_IGSTATE);
5984 
5985 	/*
5986 	 * Allocate enough space to handle "subnex" maps at a time.
5987 	 */
5988 	subnex = 16;
5989 	map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP);
5990 
5991 	bmv->bmv_entries = 0;
5992 
5993 	if ((XFS_IFORK_NEXTENTS(ip, whichfork) == 0)) {
5994 		if (((iflags & BMV_IF_DELALLOC) == 0) ||
5995 		    whichfork == XFS_ATTR_FORK) {
5996 			error = 0;
5997 			goto unlock_and_return;
5998 		}
5999 	}
6000 
6001 	nexleft = nex;
6002 
6003 	do {
6004 		nmap = (nexleft > subnex) ? subnex : nexleft;
6005 		error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
6006 				  XFS_BB_TO_FSB(mp, bmv->bmv_length),
6007 				  bmapi_flags, NULL, 0, map, &nmap,
6008 				  NULL, NULL);
6009 		if (error)
6010 			goto unlock_and_return;
6011 		ASSERT(nmap <= subnex);
6012 
6013 		for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
6014 			out.bmv_oflags = 0;
6015 			if (map[i].br_state == XFS_EXT_UNWRITTEN)
6016 				out.bmv_oflags |= BMV_OF_PREALLOC;
6017 			else if (map[i].br_startblock == DELAYSTARTBLOCK)
6018 				out.bmv_oflags |= BMV_OF_DELALLOC;
6019 			out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);
6020 			out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
6021 			out.bmv_unused1 = out.bmv_unused2 = 0;
6022 			ASSERT(((iflags & BMV_IF_DELALLOC) != 0) ||
6023 			      (map[i].br_startblock != DELAYSTARTBLOCK));
6024                         if (map[i].br_startblock == HOLESTARTBLOCK &&
6025 			    whichfork == XFS_ATTR_FORK) {
6026 				/* came to the end of attribute fork */
6027 				out.bmv_oflags |= BMV_OF_LAST;
6028 				goto unlock_and_return;
6029 			} else {
6030 				int full = 0;	/* user array is full */
6031 
6032 				if (!xfs_getbmapx_fix_eof_hole(ip, &out,
6033 							prealloced, bmvend,
6034 							map[i].br_startblock)) {
6035 					goto unlock_and_return;
6036 				}
6037 
6038 				/* format results & advance arg */
6039 				error = formatter(&arg, &out, &full);
6040 				if (error || full)
6041 					goto unlock_and_return;
6042 				nexleft--;
6043 				bmv->bmv_offset =
6044 					out.bmv_offset + out.bmv_length;
6045 				bmv->bmv_length = MAX((__int64_t)0,
6046 					(__int64_t)(bmvend - bmv->bmv_offset));
6047 				bmv->bmv_entries++;
6048 			}
6049 		}
6050 	} while (nmap && nexleft && bmv->bmv_length);
6051 
6052 unlock_and_return:
6053 	xfs_iunlock_map_shared(ip, lock);
6054 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
6055 
6056 	kmem_free(map);
6057 
6058 	return error;
6059 }
6060 
6061 /*
6062  * Check the last inode extent to determine whether this allocation will result
6063  * in blocks being allocated at the end of the file. When we allocate new data
6064  * blocks at the end of the file which do not start at the previous data block,
6065  * we will try to align the new blocks at stripe unit boundaries.
6066  */
6067 STATIC int				/* error */
xfs_bmap_isaeof(xfs_inode_t * ip,xfs_fileoff_t off,int whichfork,char * aeof)6068 xfs_bmap_isaeof(
6069 	xfs_inode_t	*ip,		/* incore inode pointer */
6070 	xfs_fileoff_t   off,		/* file offset in fsblocks */
6071 	int             whichfork,	/* data or attribute fork */
6072 	char		*aeof)		/* return value */
6073 {
6074 	int		error;		/* error return value */
6075 	xfs_ifork_t	*ifp;		/* inode fork pointer */
6076 	xfs_bmbt_rec_host_t *lastrec;	/* extent record pointer */
6077 	xfs_extnum_t	nextents;	/* number of file extents */
6078 	xfs_bmbt_irec_t	s;		/* expanded extent record */
6079 
6080 	ASSERT(whichfork == XFS_DATA_FORK);
6081 	ifp = XFS_IFORK_PTR(ip, whichfork);
6082 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
6083 	    (error = xfs_iread_extents(NULL, ip, whichfork)))
6084 		return error;
6085 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
6086 	if (nextents == 0) {
6087 		*aeof = 1;
6088 		return 0;
6089 	}
6090 	/*
6091 	 * Go to the last extent
6092 	 */
6093 	lastrec = xfs_iext_get_ext(ifp, nextents - 1);
6094 	xfs_bmbt_get_all(lastrec, &s);
6095 	/*
6096 	 * Check we are allocating in the last extent (for delayed allocations)
6097 	 * or past the last extent for non-delayed allocations.
6098 	 */
6099 	*aeof = (off >= s.br_startoff &&
6100 		 off < s.br_startoff + s.br_blockcount &&
6101 		 isnullstartblock(s.br_startblock)) ||
6102 		off >= s.br_startoff + s.br_blockcount;
6103 	return 0;
6104 }
6105 
6106 /*
6107  * Check if the endoff is outside the last extent. If so the caller will grow
6108  * the allocation to a stripe unit boundary.
6109  */
6110 int					/* error */
xfs_bmap_eof(xfs_inode_t * ip,xfs_fileoff_t endoff,int whichfork,int * eof)6111 xfs_bmap_eof(
6112 	xfs_inode_t	*ip,		/* incore inode pointer */
6113 	xfs_fileoff_t	endoff,		/* file offset in fsblocks */
6114 	int		whichfork,	/* data or attribute fork */
6115 	int		*eof)		/* result value */
6116 {
6117 	xfs_fsblock_t	blockcount;	/* extent block count */
6118 	int		error;		/* error return value */
6119 	xfs_ifork_t	*ifp;		/* inode fork pointer */
6120 	xfs_bmbt_rec_host_t *lastrec;	/* extent record pointer */
6121 	xfs_extnum_t	nextents;	/* number of file extents */
6122 	xfs_fileoff_t	startoff;	/* extent starting file offset */
6123 
6124 	ASSERT(whichfork == XFS_DATA_FORK);
6125 	ifp = XFS_IFORK_PTR(ip, whichfork);
6126 	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
6127 	    (error = xfs_iread_extents(NULL, ip, whichfork)))
6128 		return error;
6129 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
6130 	if (nextents == 0) {
6131 		*eof = 1;
6132 		return 0;
6133 	}
6134 	/*
6135 	 * Go to the last extent
6136 	 */
6137 	lastrec = xfs_iext_get_ext(ifp, nextents - 1);
6138 	startoff = xfs_bmbt_get_startoff(lastrec);
6139 	blockcount = xfs_bmbt_get_blockcount(lastrec);
6140 	*eof = endoff >= startoff + blockcount;
6141 	return 0;
6142 }
6143 
6144 #ifdef DEBUG
6145 STATIC
6146 xfs_buf_t *
xfs_bmap_get_bp(xfs_btree_cur_t * cur,xfs_fsblock_t bno)6147 xfs_bmap_get_bp(
6148 	xfs_btree_cur_t         *cur,
6149 	xfs_fsblock_t		bno)
6150 {
6151 	int i;
6152 	xfs_buf_t *bp;
6153 
6154 	if (!cur)
6155 		return(NULL);
6156 
6157 	bp = NULL;
6158 	for(i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
6159 		bp = cur->bc_bufs[i];
6160 		if (!bp) break;
6161 		if (XFS_BUF_ADDR(bp) == bno)
6162 			break;	/* Found it */
6163 	}
6164 	if (i == XFS_BTREE_MAXLEVELS)
6165 		bp = NULL;
6166 
6167 	if (!bp) { /* Chase down all the log items to see if the bp is there */
6168 		xfs_log_item_chunk_t    *licp;
6169 		xfs_trans_t		*tp;
6170 
6171 		tp = cur->bc_tp;
6172 		licp = &tp->t_items;
6173 		while (!bp && licp != NULL) {
6174 			if (xfs_lic_are_all_free(licp)) {
6175 				licp = licp->lic_next;
6176 				continue;
6177 			}
6178 			for (i = 0; i < licp->lic_unused; i++) {
6179 				xfs_log_item_desc_t	*lidp;
6180 				xfs_log_item_t		*lip;
6181 				xfs_buf_log_item_t	*bip;
6182 				xfs_buf_t		*lbp;
6183 
6184 				if (xfs_lic_isfree(licp, i)) {
6185 					continue;
6186 				}
6187 
6188 				lidp = xfs_lic_slot(licp, i);
6189 				lip = lidp->lid_item;
6190 				if (lip->li_type != XFS_LI_BUF)
6191 					continue;
6192 
6193 				bip = (xfs_buf_log_item_t *)lip;
6194 				lbp = bip->bli_buf;
6195 
6196 				if (XFS_BUF_ADDR(lbp) == bno) {
6197 					bp = lbp;
6198 					break; /* Found it */
6199 				}
6200 			}
6201 			licp = licp->lic_next;
6202 		}
6203 	}
6204 	return(bp);
6205 }
6206 
6207 void
xfs_check_block(struct xfs_btree_block * block,xfs_mount_t * mp,int root,short sz)6208 xfs_check_block(
6209 	struct xfs_btree_block	*block,
6210 	xfs_mount_t		*mp,
6211 	int			root,
6212 	short			sz)
6213 {
6214 	int			i, j, dmxr;
6215 	__be64			*pp, *thispa;	/* pointer to block address */
6216 	xfs_bmbt_key_t		*prevp, *keyp;
6217 
6218 	ASSERT(be16_to_cpu(block->bb_level) > 0);
6219 
6220 	prevp = NULL;
6221 	for( i = 1; i <= xfs_btree_get_numrecs(block); i++) {
6222 		dmxr = mp->m_bmap_dmxr[0];
6223 		keyp = XFS_BMBT_KEY_ADDR(mp, block, i);
6224 
6225 		if (prevp) {
6226 			ASSERT(be64_to_cpu(prevp->br_startoff) <
6227 			       be64_to_cpu(keyp->br_startoff));
6228 		}
6229 		prevp = keyp;
6230 
6231 		/*
6232 		 * Compare the block numbers to see if there are dups.
6233 		 */
6234 		if (root)
6235 			pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, i, sz);
6236 		else
6237 			pp = XFS_BMBT_PTR_ADDR(mp, block, i, dmxr);
6238 
6239 		for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
6240 			if (root)
6241 				thispa = XFS_BMAP_BROOT_PTR_ADDR(mp, block, j, sz);
6242 			else
6243 				thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
6244 			if (*thispa == *pp) {
6245 				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
6246 					__func__, j, i,
6247 					(unsigned long long)be64_to_cpu(*thispa));
6248 				panic("%s: ptrs are equal in node\n",
6249 					__func__);
6250 			}
6251 		}
6252 	}
6253 }
6254 
6255 /*
6256  * Check that the extents for the inode ip are in the right order in all
6257  * btree leaves.
6258  */
6259 
6260 STATIC void
xfs_bmap_check_leaf_extents(xfs_btree_cur_t * cur,xfs_inode_t * ip,int whichfork)6261 xfs_bmap_check_leaf_extents(
6262 	xfs_btree_cur_t		*cur,	/* btree cursor or null */
6263 	xfs_inode_t		*ip,		/* incore inode pointer */
6264 	int			whichfork)	/* data or attr fork */
6265 {
6266 	struct xfs_btree_block	*block;	/* current btree block */
6267 	xfs_fsblock_t		bno;	/* block # of "block" */
6268 	xfs_buf_t		*bp;	/* buffer for "block" */
6269 	int			error;	/* error return value */
6270 	xfs_extnum_t		i=0, j;	/* index into the extents list */
6271 	xfs_ifork_t		*ifp;	/* fork structure */
6272 	int			level;	/* btree level, for checking */
6273 	xfs_mount_t		*mp;	/* file system mount structure */
6274 	__be64			*pp;	/* pointer to block address */
6275 	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
6276 	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
6277 	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
6278 	int			bp_release = 0;
6279 
6280 	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
6281 		return;
6282 	}
6283 
6284 	bno = NULLFSBLOCK;
6285 	mp = ip->i_mount;
6286 	ifp = XFS_IFORK_PTR(ip, whichfork);
6287 	block = ifp->if_broot;
6288 	/*
6289 	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
6290 	 */
6291 	level = be16_to_cpu(block->bb_level);
6292 	ASSERT(level > 0);
6293 	xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
6294 	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
6295 	bno = be64_to_cpu(*pp);
6296 
6297 	ASSERT(bno != NULLDFSBNO);
6298 	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
6299 	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
6300 
6301 	/*
6302 	 * Go down the tree until leaf level is reached, following the first
6303 	 * pointer (leftmost) at each level.
6304 	 */
6305 	while (level-- > 0) {
6306 		/* See if buf is in cur first */
6307 		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
6308 		if (bp) {
6309 			bp_release = 0;
6310 		} else {
6311 			bp_release = 1;
6312 		}
6313 		if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
6314 				XFS_BMAP_BTREE_REF)))
6315 			goto error_norelse;
6316 		block = XFS_BUF_TO_BLOCK(bp);
6317 		XFS_WANT_CORRUPTED_GOTO(
6318 			xfs_bmap_sanity_check(mp, bp, level),
6319 			error0);
6320 		if (level == 0)
6321 			break;
6322 
6323 		/*
6324 		 * Check this block for basic sanity (increasing keys and
6325 		 * no duplicate blocks).
6326 		 */
6327 
6328 		xfs_check_block(block, mp, 0, 0);
6329 		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
6330 		bno = be64_to_cpu(*pp);
6331 		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
6332 		if (bp_release) {
6333 			bp_release = 0;
6334 			xfs_trans_brelse(NULL, bp);
6335 		}
6336 	}
6337 
6338 	/*
6339 	 * Here with bp and block set to the leftmost leaf node in the tree.
6340 	 */
6341 	i = 0;
6342 
6343 	/*
6344 	 * Loop over all leaf nodes checking that all extents are in the right order.
6345 	 */
6346 	for (;;) {
6347 		xfs_fsblock_t	nextbno;
6348 		xfs_extnum_t	num_recs;
6349 
6350 
6351 		num_recs = xfs_btree_get_numrecs(block);
6352 
6353 		/*
6354 		 * Read-ahead the next leaf block, if any.
6355 		 */
6356 
6357 		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
6358 
6359 		/*
6360 		 * Check all the extents to make sure they are OK.
6361 		 * If we had a previous block, the last entry should
6362 		 * conform with the first entry in this one.
6363 		 */
6364 
6365 		ep = XFS_BMBT_REC_ADDR(mp, block, 1);
6366 		if (i) {
6367 			ASSERT(xfs_bmbt_disk_get_startoff(&last) +
6368 			       xfs_bmbt_disk_get_blockcount(&last) <=
6369 			       xfs_bmbt_disk_get_startoff(ep));
6370 		}
6371 		for (j = 1; j < num_recs; j++) {
6372 			nextp = XFS_BMBT_REC_ADDR(mp, block, j + 1);
6373 			ASSERT(xfs_bmbt_disk_get_startoff(ep) +
6374 			       xfs_bmbt_disk_get_blockcount(ep) <=
6375 			       xfs_bmbt_disk_get_startoff(nextp));
6376 			ep = nextp;
6377 		}
6378 
6379 		last = *ep;
6380 		i += num_recs;
6381 		if (bp_release) {
6382 			bp_release = 0;
6383 			xfs_trans_brelse(NULL, bp);
6384 		}
6385 		bno = nextbno;
6386 		/*
6387 		 * If we've reached the end, stop.
6388 		 */
6389 		if (bno == NULLFSBLOCK)
6390 			break;
6391 
6392 		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
6393 		if (bp) {
6394 			bp_release = 0;
6395 		} else {
6396 			bp_release = 1;
6397 		}
6398 		if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
6399 				XFS_BMAP_BTREE_REF)))
6400 			goto error_norelse;
6401 		block = XFS_BUF_TO_BLOCK(bp);
6402 	}
6403 	if (bp_release) {
6404 		bp_release = 0;
6405 		xfs_trans_brelse(NULL, bp);
6406 	}
6407 	return;
6408 
6409 error0:
6410 	cmn_err(CE_WARN, "%s: at error0", __func__);
6411 	if (bp_release)
6412 		xfs_trans_brelse(NULL, bp);
6413 error_norelse:
6414 	cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
6415 		__func__, i);
6416 	panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
6417 	return;
6418 }
6419 #endif
6420 
6421 /*
6422  * Count fsblocks of the given fork.
6423  */
6424 int						/* error */
xfs_bmap_count_blocks(xfs_trans_t * tp,xfs_inode_t * ip,int whichfork,int * count)6425 xfs_bmap_count_blocks(
6426 	xfs_trans_t		*tp,		/* transaction pointer */
6427 	xfs_inode_t		*ip,		/* incore inode */
6428 	int			whichfork,	/* data or attr fork */
6429 	int			*count)		/* out: count of blocks */
6430 {
6431 	struct xfs_btree_block	*block;	/* current btree block */
6432 	xfs_fsblock_t		bno;	/* block # of "block" */
6433 	xfs_ifork_t		*ifp;	/* fork structure */
6434 	int			level;	/* btree level, for checking */
6435 	xfs_mount_t		*mp;	/* file system mount structure */
6436 	__be64			*pp;	/* pointer to block address */
6437 
6438 	bno = NULLFSBLOCK;
6439 	mp = ip->i_mount;
6440 	ifp = XFS_IFORK_PTR(ip, whichfork);
6441 	if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
6442 		xfs_bmap_count_leaves(ifp, 0,
6443 			ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
6444 			count);
6445 		return 0;
6446 	}
6447 
6448 	/*
6449 	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
6450 	 */
6451 	block = ifp->if_broot;
6452 	level = be16_to_cpu(block->bb_level);
6453 	ASSERT(level > 0);
6454 	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
6455 	bno = be64_to_cpu(*pp);
6456 	ASSERT(bno != NULLDFSBNO);
6457 	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
6458 	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
6459 
6460 	if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
6461 		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
6462 				 mp);
6463 		return XFS_ERROR(EFSCORRUPTED);
6464 	}
6465 
6466 	return 0;
6467 }
6468 
6469 /*
6470  * Recursively walks each level of a btree
6471  * to count total fsblocks is use.
6472  */
6473 STATIC int                                     /* error */
xfs_bmap_count_tree(xfs_mount_t * mp,xfs_trans_t * tp,xfs_ifork_t * ifp,xfs_fsblock_t blockno,int levelin,int * count)6474 xfs_bmap_count_tree(
6475 	xfs_mount_t     *mp,            /* file system mount point */
6476 	xfs_trans_t     *tp,            /* transaction pointer */
6477 	xfs_ifork_t	*ifp,		/* inode fork pointer */
6478 	xfs_fsblock_t   blockno,	/* file system block number */
6479 	int             levelin,	/* level in btree */
6480 	int		*count)		/* Count of blocks */
6481 {
6482 	int			error;
6483 	xfs_buf_t		*bp, *nbp;
6484 	int			level = levelin;
6485 	__be64			*pp;
6486 	xfs_fsblock_t           bno = blockno;
6487 	xfs_fsblock_t		nextbno;
6488 	struct xfs_btree_block	*block, *nextblock;
6489 	int			numrecs;
6490 
6491 	if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF)))
6492 		return error;
6493 	*count += 1;
6494 	block = XFS_BUF_TO_BLOCK(bp);
6495 
6496 	if (--level) {
6497 		/* Not at node above leafs, count this level of nodes */
6498 		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
6499 		while (nextbno != NULLFSBLOCK) {
6500 			if ((error = xfs_btree_read_bufl(mp, tp, nextbno,
6501 				0, &nbp, XFS_BMAP_BTREE_REF)))
6502 				return error;
6503 			*count += 1;
6504 			nextblock = XFS_BUF_TO_BLOCK(nbp);
6505 			nextbno = be64_to_cpu(nextblock->bb_u.l.bb_rightsib);
6506 			xfs_trans_brelse(tp, nbp);
6507 		}
6508 
6509 		/* Dive to the next level */
6510 		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
6511 		bno = be64_to_cpu(*pp);
6512 		if (unlikely((error =
6513 		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
6514 			xfs_trans_brelse(tp, bp);
6515 			XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
6516 					 XFS_ERRLEVEL_LOW, mp);
6517 			return XFS_ERROR(EFSCORRUPTED);
6518 		}
6519 		xfs_trans_brelse(tp, bp);
6520 	} else {
6521 		/* count all level 1 nodes and their leaves */
6522 		for (;;) {
6523 			nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
6524 			numrecs = be16_to_cpu(block->bb_numrecs);
6525 			xfs_bmap_disk_count_leaves(mp, block, numrecs, count);
6526 			xfs_trans_brelse(tp, bp);
6527 			if (nextbno == NULLFSBLOCK)
6528 				break;
6529 			bno = nextbno;
6530 			if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
6531 				XFS_BMAP_BTREE_REF)))
6532 				return error;
6533 			*count += 1;
6534 			block = XFS_BUF_TO_BLOCK(bp);
6535 		}
6536 	}
6537 	return 0;
6538 }
6539 
6540 /*
6541  * Count leaf blocks given a range of extent records.
6542  */
6543 STATIC void
xfs_bmap_count_leaves(xfs_ifork_t * ifp,xfs_extnum_t idx,int numrecs,int * count)6544 xfs_bmap_count_leaves(
6545 	xfs_ifork_t		*ifp,
6546 	xfs_extnum_t		idx,
6547 	int			numrecs,
6548 	int			*count)
6549 {
6550 	int		b;
6551 
6552 	for (b = 0; b < numrecs; b++) {
6553 		xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
6554 		*count += xfs_bmbt_get_blockcount(frp);
6555 	}
6556 }
6557 
6558 /*
6559  * Count leaf blocks given a range of extent records originally
6560  * in btree format.
6561  */
6562 STATIC void
xfs_bmap_disk_count_leaves(struct xfs_mount * mp,struct xfs_btree_block * block,int numrecs,int * count)6563 xfs_bmap_disk_count_leaves(
6564 	struct xfs_mount	*mp,
6565 	struct xfs_btree_block	*block,
6566 	int			numrecs,
6567 	int			*count)
6568 {
6569 	int		b;
6570 	xfs_bmbt_rec_t	*frp;
6571 
6572 	for (b = 1; b <= numrecs; b++) {
6573 		frp = XFS_BMBT_REC_ADDR(mp, block, b);
6574 		*count += xfs_bmbt_disk_get_blockcount(frp);
6575 	}
6576 }
6577