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