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