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