]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_bmap.c
Update copyright/license notices to match SGI legal prefered boilerplate.
[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;
2425 ASSERT(INT_GET(rblock->bb_level, ARCH_CONVERT) == 1);
2426 ASSERT(INT_GET(rblock->bb_numrecs, ARCH_CONVERT) == 1);
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;
2869 INT_SET(block->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
2870 INT_SET(block->bb_level, ARCH_CONVERT, 1);
2871 INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
2872 INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLDFSBNO);
5000d01d 2873 INT_SET(block->bb_rightsib, ARCH_CONVERT, 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);
2926 INT_SET(ablock->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
46eca962 2927 ablock->bb_level = 0;
2bd0ea18 2928 INT_SET(ablock->bb_leftsib, ARCH_CONVERT, NULLDFSBNO);
5000d01d 2929 INT_SET(ablock->bb_rightsib, ARCH_CONVERT, 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 }
f9e56f43 2939 INT_SET(ablock->bb_numrecs, ARCH_CONVERT, cnt);
2bd0ea18
NS
2940 ASSERT(INT_GET(ablock->bb_numrecs, ARCH_CONVERT) == XFS_IFORK_NEXTENTS(ip, whichfork));
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);
2954 xfs_bmbt_log_recs(cur, abp, 1, INT_GET(ablock->bb_numrecs, ARCH_CONVERT));
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);
062998e3
NS
3242 rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME;
3243 if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) {
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",
3247 (ip->i_mount)->m_fsname,(long long)ip->i_ino,
3248 gotp->br_startblock, gotp->br_startoff,
3249 gotp->br_blockcount,gotp->br_state);
3250 }
3251 return ep;
2bd0ea18
NS
3252}
3253
3254/*
3255 * Compute the worst-case number of indirect blocks that will be used
3256 * for ip's delayed extent of length "len".
3257 */
3258STATIC xfs_filblks_t
3259xfs_bmap_worst_indlen(
3260 xfs_inode_t *ip, /* incore inode pointer */
3261 xfs_filblks_t len) /* delayed extent length */
3262{
3263 int level; /* btree level number */
3264 int maxrecs; /* maximum record count at this level */
3265 xfs_mount_t *mp; /* mount structure */
3266 xfs_filblks_t rval; /* return value */
3267
3268 mp = ip->i_mount;
3269 maxrecs = mp->m_bmap_dmxr[0];
3270 for (level = 0, rval = 0;
3271 level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
3272 level++) {
3273 len += maxrecs - 1;
3274 do_div(len, maxrecs);
3275 rval += len;
3276 if (len == 1)
3277 return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
3278 level - 1;
3279 if (level == 0)
3280 maxrecs = mp->m_bmap_dmxr[1];
3281 }
3282 return rval;
3283}
3284
57c9fccb
NS
3285/*
3286 * Convert inode from non-attributed to attributed.
3287 * Must not be in a transaction, ip must not be locked.
3288 */
3289int /* error code */
3290xfs_bmap_add_attrfork(
3291 xfs_inode_t *ip, /* incore inode pointer */
ca86e759
NS
3292 int size, /* space new attribute needs */
3293 int rsvd) /* xact may use reserved blks */
57c9fccb 3294{
57c9fccb
NS
3295 xfs_fsblock_t firstblock; /* 1st block/ag allocated */
3296 xfs_bmap_free_t flist; /* freed extent list */
57c9fccb 3297 xfs_mount_t *mp; /* mount structure */
57c9fccb 3298 xfs_trans_t *tp; /* transaction pointer */
ca86e759
NS
3299 unsigned long s; /* spinlock spl value */
3300 int blks; /* space reservation */
3301 int version = 1; /* superblock attr version */
3302 int committed; /* xaction was committed */
3303 int logflags; /* logging flags */
3304 int error; /* error return value */
57c9fccb 3305
ca86e759 3306 ASSERT(XFS_IFORK_Q(ip) == 0);
57c9fccb
NS
3307 ASSERT(ip->i_df.if_ext_max ==
3308 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
ca86e759 3309
57c9fccb
NS
3310 mp = ip->i_mount;
3311 ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
3312 tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
3313 blks = XFS_ADDAFORK_SPACE_RES(mp);
3314 if (rsvd)
3315 tp->t_flags |= XFS_TRANS_RESERVE;
3316 if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
3317 XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
3318 goto error0;
3319 xfs_ilock(ip, XFS_ILOCK_EXCL);
3320 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, blks, 0, rsvd ?
3321 XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
3322 XFS_QMOPT_RES_REGBLKS);
3323 if (error) {
3324 xfs_iunlock(ip, XFS_ILOCK_EXCL);
3325 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
3326 return error;
3327 }
3328 if (XFS_IFORK_Q(ip))
3329 goto error1;
3330 if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
3331 /*
3332 * For inodes coming from pre-6.2 filesystems.
3333 */
3334 ASSERT(ip->i_d.di_aformat == 0);
3335 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
3336 }
3337 ASSERT(ip->i_d.di_anextents == 0);
3338 VN_HOLD(XFS_ITOV(ip));
3339 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
3340 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
3341 switch (ip->i_d.di_format) {
3342 case XFS_DINODE_FMT_DEV:
3343 ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
3344 break;
3345 case XFS_DINODE_FMT_UUID:
3346 ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
3347 break;
3348 case XFS_DINODE_FMT_LOCAL:
3349 case XFS_DINODE_FMT_EXTENTS:
3350 case XFS_DINODE_FMT_BTREE:
ca86e759 3351 ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
6239071d 3352 if (!ip->i_d.di_forkoff)
ca86e759 3353 ip->i_d.di_forkoff = mp->m_attroffset >> 3;
6239071d
NS
3354 else if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR))
3355 version = 2;
57c9fccb
NS
3356 break;
3357 default:
3358 ASSERT(0);
3359 error = XFS_ERROR(EINVAL);
3360 goto error1;
3361 }
3362 ip->i_df.if_ext_max =
3363 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
3364 ASSERT(ip->i_afp == NULL);
3365 ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
3366 ip->i_afp->if_ext_max =
3367 XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
3368 ip->i_afp->if_flags = XFS_IFEXTENTS;
3369 logflags = 0;
3370 XFS_BMAP_INIT(&flist, &firstblock);
3371 switch (ip->i_d.di_format) {
3372 case XFS_DINODE_FMT_LOCAL:
3373 error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
3374 &logflags);
3375 break;
3376 case XFS_DINODE_FMT_EXTENTS:
3377 error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
3378 &flist, &logflags);
3379 break;
3380 case XFS_DINODE_FMT_BTREE:
3381 error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
3382 &logflags);
3383 break;
3384 default:
3385 error = 0;
3386 break;
3387 }
3388 if (logflags)
3389 xfs_trans_log_inode(tp, ip, logflags);
3390 if (error)
3391 goto error2;
ca86e759
NS
3392 if (!XFS_SB_VERSION_HASATTR(&mp->m_sb) ||
3393 (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2)) {
3f853c7a
NS
3394 __int64_t sbfields = 0;
3395
57c9fccb
NS
3396 s = XFS_SB_LOCK(mp);
3397 if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) {
3398 XFS_SB_VERSION_ADDATTR(&mp->m_sb);
3f853c7a 3399 sbfields |= XFS_SB_VERSIONNUM;
ca86e759
NS
3400 }
3401 if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2) {
3402 XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
3f853c7a 3403 sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
ca86e759 3404 }
3f853c7a 3405 if (sbfields) {
57c9fccb 3406 XFS_SB_UNLOCK(mp, s);
3f853c7a 3407 xfs_mod_sb(tp, sbfields);
57c9fccb
NS
3408 } else
3409 XFS_SB_UNLOCK(mp, s);
3410 }
3411 if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed)))
3412 goto error2;
3413 error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL);
3414 ASSERT(ip->i_df.if_ext_max ==
3415 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
3416 return error;
3417error2:
3418 xfs_bmap_cancel(&flist);
3419error1:
3420 ASSERT(ismrlocked(&ip->i_lock,MR_UPDATE));
3421 xfs_iunlock(ip, XFS_ILOCK_EXCL);
3422error0:
3423 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
3424 ASSERT(ip->i_df.if_ext_max ==
3425 XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
3426 return error;
3427}
3428
2bd0ea18
NS
3429/*
3430 * Add the extent to the list of extents to be free at transaction end.
3431 * The list is maintained sorted (by block number).
3432 */
3433/* ARGSUSED */
3434void
3435xfs_bmap_add_free(
3436 xfs_fsblock_t bno, /* fs block number of extent */
3437 xfs_filblks_t len, /* length of extent */
3438 xfs_bmap_free_t *flist, /* list of extents */
3439 xfs_mount_t *mp) /* mount point structure */
3440{
3441 xfs_bmap_free_item_t *cur; /* current (next) element */
3442 xfs_bmap_free_item_t *new; /* new element */
3443 xfs_bmap_free_item_t *prev; /* previous element */
3444#ifdef DEBUG
3445 xfs_agnumber_t agno;
3446 xfs_agblock_t agbno;
3447
3448 ASSERT(bno != NULLFSBLOCK);
3449 ASSERT(len > 0);
3450 ASSERT(len <= MAXEXTLEN);
3451 ASSERT(!ISNULLSTARTBLOCK(bno));
3452 agno = XFS_FSB_TO_AGNO(mp, bno);
3453 agbno = XFS_FSB_TO_AGBNO(mp, bno);
3454 ASSERT(agno < mp->m_sb.sb_agcount);
3455 ASSERT(agbno < mp->m_sb.sb_agblocks);
3456 ASSERT(len < mp->m_sb.sb_agblocks);
3457 ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
3458#endif
3459 ASSERT(xfs_bmap_free_item_zone != NULL);
3460 new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
3461 new->xbfi_startblock = bno;
3462 new->xbfi_blockcount = (xfs_extlen_t)len;
3463 for (prev = NULL, cur = flist->xbf_first;
3464 cur != NULL;
3465 prev = cur, cur = cur->xbfi_next) {
3466 if (cur->xbfi_startblock >= bno)
3467 break;
3468 }
3469 if (prev)
3470 prev->xbfi_next = new;
3471 else
3472 flist->xbf_first = new;
3473 new->xbfi_next = cur;
3474 flist->xbf_count++;
3475}
3476
5000d01d 3477/*
2bd0ea18 3478 * Compute and fill in the value of the maximum depth of a bmap btree
dfc130f3 3479 * in this filesystem. Done once, during mount.
2bd0ea18
NS
3480 */
3481void
3482xfs_bmap_compute_maxlevels(
3483 xfs_mount_t *mp, /* file system mount structure */
3484 int whichfork) /* data or attr fork */
3485{
3486 int level; /* btree level */
3487 uint maxblocks; /* max blocks at this level */
3488 uint maxleafents; /* max leaf entries possible */
3489 int maxrootrecs; /* max records in root block */
3490 int minleafrecs; /* min records in leaf block */
3491 int minnoderecs; /* min records in node block */
3492 int sz; /* root block size */
3493
3494 /*
3495 * The maximum number of extents in a file, hence the maximum
3496 * number of leaf entries, is controlled by the type of di_nextents
3497 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
3498 * (a signed 16-bit number, xfs_aextnum_t).
3499 */
ca86e759
NS
3500 if (whichfork == XFS_DATA_FORK) {
3501 maxleafents = MAXEXTNUM;
6239071d
NS
3502 sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
3503 mp->m_attroffset : XFS_BMDR_SPACE_CALC(MINDBTPTRS);
ca86e759
NS
3504 } else {
3505 maxleafents = MAXAEXTNUM;
6239071d
NS
3506 sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
3507 mp->m_sb.sb_inodesize - mp->m_attroffset :
3508 XFS_BMDR_SPACE_CALC(MINABTPTRS);
ca86e759
NS
3509 }
3510 maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
2bd0ea18
NS
3511 minleafrecs = mp->m_bmap_dmnr[0];
3512 minnoderecs = mp->m_bmap_dmnr[1];
2bd0ea18
NS
3513 maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
3514 for (level = 1; maxblocks > 1; level++) {
3515 if (maxblocks <= maxrootrecs)
3516 maxblocks = 1;
3517 else
3518 maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
3519 }
3520 mp->m_bm_maxlevels[whichfork] = level;
3521}
3522
57c9fccb
NS
3523/*
3524 * Free up any items left in the list.
3525 */
3526void
3527xfs_bmap_cancel(
3528 xfs_bmap_free_t *flist) /* list of bmap_free_items */
3529{
3530 xfs_bmap_free_item_t *free; /* free list item */
3531 xfs_bmap_free_item_t *next;
3532
3533 if (flist->xbf_count == 0)
3534 return;
3535 ASSERT(flist->xbf_first != NULL);
3536 for (free = flist->xbf_first; free; free = next) {
3537 next = free->xbfi_next;
3538 xfs_bmap_del_free(flist, NULL, free);
3539 }
3540 ASSERT(flist->xbf_count == 0);
3541}
3542
2bd0ea18
NS
3543/*
3544 * Returns the file-relative block number of the first unused block(s)
3545 * in the file with at least "len" logically contiguous blocks free.
3546 * This is the lowest-address hole if the file has holes, else the first block
3547 * past the end of file.
3548 * Return 0 if the file is currently local (in-inode).
3549 */
3550int /* error */
3551xfs_bmap_first_unused(
3552 xfs_trans_t *tp, /* transaction pointer */
3553 xfs_inode_t *ip, /* incore inode */
3554 xfs_extlen_t len, /* size of hole to find */
3555 xfs_fileoff_t *first_unused, /* unused block */
3556 int whichfork) /* data or attr fork */
3557{
3558 xfs_bmbt_rec_t *base; /* base of extent array */
3559 xfs_bmbt_rec_t *ep; /* pointer to an extent entry */
3560 int error; /* error return value */
3561 xfs_ifork_t *ifp; /* inode fork pointer */
3562 xfs_fileoff_t lastaddr; /* last block number seen */
3563 xfs_fileoff_t lowest; /* lowest useful block */
3564 xfs_fileoff_t max; /* starting useful block */
3565 xfs_fileoff_t off; /* offset for this block */
3566 xfs_extnum_t nextents; /* number of extent entries */
3567
3568 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
3569 XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
3570 XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
3571 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
3572 *first_unused = 0;
3573 return 0;
3574 }
3575 ifp = XFS_IFORK_PTR(ip, whichfork);
3576 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
3577 (error = xfs_iread_extents(tp, ip, whichfork)))
3578 return error;
3579 lowest = *first_unused;
3580 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3581 base = &ifp->if_u1.if_extents[0];
3582 for (lastaddr = 0, max = lowest, ep = base;
3583 ep < &base[nextents];
3584 ep++) {
3585 off = xfs_bmbt_get_startoff(ep);
3586 /*
3587 * See if the hole before this extent will work.
3588 */
3589 if (off >= lowest + len && off - max >= len) {
3590 *first_unused = max;
3591 return 0;
3592 }
3593 lastaddr = off + xfs_bmbt_get_blockcount(ep);
3594 max = XFS_FILEOFF_MAX(lastaddr, lowest);
3595 }
3596 *first_unused = max;
3597 return 0;
3598}
3599
3600/*
3601 * Returns the file-relative block number of the last block + 1 before
3602 * last_block (input value) in the file.
3603 * This is not based on i_size, it is based on the extent list.
3604 * Returns 0 for local files, as they do not have an extent list.
3605 */
3606int /* error */
3607xfs_bmap_last_before(
3608 xfs_trans_t *tp, /* transaction pointer */
3609 xfs_inode_t *ip, /* incore inode */
3610 xfs_fileoff_t *last_block, /* last block */
3611 int whichfork) /* data or attr fork */
3612{
3613 xfs_fileoff_t bno; /* input file offset */
3614 int eof; /* hit end of file */
3615 xfs_bmbt_rec_t *ep; /* pointer to last extent */
3616 int error; /* error return value */
dfc130f3 3617 xfs_bmbt_irec_t got; /* current extent value */
2bd0ea18
NS
3618 xfs_ifork_t *ifp; /* inode fork pointer */
3619 xfs_extnum_t lastx; /* last extent used */
dfc130f3 3620 xfs_bmbt_irec_t prev; /* previous extent value */
2bd0ea18
NS
3621
3622 if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
3623 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
3624 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
3625 return XFS_ERROR(EIO);
3626 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
3627 *last_block = 0;
3628 return 0;
3629 }
3630 ifp = XFS_IFORK_PTR(ip, whichfork);
3631 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
3632 (error = xfs_iread_extents(tp, ip, whichfork)))
3633 return error;
3634 bno = *last_block - 1;
3635 ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
3636 &prev);
3637 if (eof || xfs_bmbt_get_startoff(ep) > bno) {
3638 if (prev.br_startoff == NULLFILEOFF)
3639 *last_block = 0;
3640 else
3641 *last_block = prev.br_startoff + prev.br_blockcount;
3642 }
3643 /*
3644 * Otherwise *last_block is already the right answer.
3645 */
3646 return 0;
3647}
3648
3649/*
3650 * Returns the file-relative block number of the first block past eof in
3651 * the file. This is not based on i_size, it is based on the extent list.
3652 * Returns 0 for local files, as they do not have an extent list.
3653 */
3654int /* error */
3655xfs_bmap_last_offset(
3656 xfs_trans_t *tp, /* transaction pointer */
3657 xfs_inode_t *ip, /* incore inode */
3658 xfs_fileoff_t *last_block, /* last block */
3659 int whichfork) /* data or attr fork */
3660{
3661 xfs_bmbt_rec_t *base; /* base of extent array */
3662 xfs_bmbt_rec_t *ep; /* pointer to last extent */
3663 int error; /* error return value */
3664 xfs_ifork_t *ifp; /* inode fork pointer */
3665 xfs_extnum_t nextents; /* number of extent entries */
3666
3667 if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
3668 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
3669 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
3670 return XFS_ERROR(EIO);
3671 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
3672 *last_block = 0;
3673 return 0;
3674 }
3675 ifp = XFS_IFORK_PTR(ip, whichfork);
3676 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
3677 (error = xfs_iread_extents(tp, ip, whichfork)))
3678 return error;
3679 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3680 if (!nextents) {
3681 *last_block = 0;
3682 return 0;
3683 }
3684 base = &ifp->if_u1.if_extents[0];
3685 ASSERT(base != NULL);
3686 ep = &base[nextents - 1];
3687 *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep);
3688 return 0;
3689}
3690
3691/*
3692 * Returns whether the selected fork of the inode has exactly one
3693 * block or not. For the data fork we check this matches di_size,
3694 * implying the file's range is 0..bsize-1.
3695 */
3696int /* 1=>1 block, 0=>otherwise */
3697xfs_bmap_one_block(
3698 xfs_inode_t *ip, /* incore inode */
3699 int whichfork) /* data or attr fork */
3700{
3701 xfs_bmbt_rec_t *ep; /* ptr to fork's extent */
3702 xfs_ifork_t *ifp; /* inode fork pointer */
3703 int rval; /* return value */
dfc130f3 3704 xfs_bmbt_irec_t s; /* internal version of extent */
2bd0ea18
NS
3705
3706#ifndef DEBUG
3707 if (whichfork == XFS_DATA_FORK)
3708 return ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize;
3709#endif /* !DEBUG */
3710 if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
3711 return 0;
3712 if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
3713 return 0;
3714 ifp = XFS_IFORK_PTR(ip, whichfork);
3715 ASSERT(ifp->if_flags & XFS_IFEXTENTS);
3716 ep = ifp->if_u1.if_extents;
3717 xfs_bmbt_get_all(ep, &s);
3718 rval = s.br_startoff == 0 && s.br_blockcount == 1;
3719 if (rval && whichfork == XFS_DATA_FORK)
3720 ASSERT(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
3721 return rval;
3722}
3723
3724/*
3725 * Read in the extents to if_extents.
3726 * All inode fields are set up by caller, we just traverse the btree
3727 * and copy the records in. If the file system cannot contain unwritten
3728 * extents, the records are checked for no "state" flags.
3729 */
3730int /* error */
3731xfs_bmap_read_extents(
3732 xfs_trans_t *tp, /* transaction pointer */
3733 xfs_inode_t *ip, /* incore inode */
3734 int whichfork) /* data or attr fork */
3735{
dfc130f3 3736 xfs_bmbt_block_t *block; /* current btree block */
2bd0ea18 3737 xfs_fsblock_t bno; /* block # of "block" */
7a3bffe4 3738 xfs_buf_t *bp; /* buffer for "block" */
2bd0ea18
NS
3739 int error; /* error return value */
3740 xfs_exntfmt_t exntf; /* XFS_EXTFMT_NOSTATE, if checking */
3741#ifdef XFS_BMAP_TRACE
3742 static char fname[] = "xfs_bmap_read_extents";
3743#endif
f9e56f43 3744 xfs_extnum_t i, j; /* index into the extents list */
2bd0ea18
NS
3745 xfs_ifork_t *ifp; /* fork structure */
3746 int level; /* btree level, for checking */
3747 xfs_mount_t *mp; /* file system mount structure */
3748 xfs_bmbt_ptr_t *pp; /* pointer to block address */
3749 /* REFERENCED */
3750 xfs_extnum_t room; /* number of entries there's room for */
3751 xfs_bmbt_rec_t *trp; /* target record pointer */
3752
3753 bno = NULLFSBLOCK;
3754 mp = ip->i_mount;
3755 ifp = XFS_IFORK_PTR(ip, whichfork);
3756 exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
3757 XFS_EXTFMT_INODE(ip);
3758 block = ifp->if_broot;
3759 /*
3760 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
3761 */
3762 ASSERT(INT_GET(block->bb_level, ARCH_CONVERT) > 0);
3763 level = INT_GET(block->bb_level, ARCH_CONVERT);
3764 pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
3765 ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
3766 ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
3767 ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
3768 bno = INT_GET(*pp, ARCH_CONVERT);
3769 /*
3770 * Go down the tree until leaf level is reached, following the first
3771 * pointer (leftmost) at each level.
3772 */
3773 while (level-- > 0) {
0e266570
NS
3774 if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
3775 XFS_BMAP_BTREE_REF)))
2bd0ea18
NS
3776 return error;
3777 block = XFS_BUF_TO_BMBT_BLOCK(bp);
3778 XFS_WANT_CORRUPTED_GOTO(
3779 XFS_BMAP_SANITY_CHECK(mp, block, level),
3780 error0);
3781 if (level == 0)
3782 break;
3783 pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
3784 1, mp->m_bmap_dmxr[1]);
63be04eb
NS
3785 XFS_WANT_CORRUPTED_GOTO(
3786 XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)),
3787 error0);
2bd0ea18
NS
3788 bno = INT_GET(*pp, ARCH_CONVERT);
3789 xfs_trans_brelse(tp, bp);
3790 }
3791 /*
3792 * Here with bp and block set to the leftmost leaf node in the tree.
3793 */
3794 room = ifp->if_bytes / (uint)sizeof(*trp);
3795 trp = ifp->if_u1.if_extents;
3796 i = 0;
3797 /*
3798 * Loop over all leaf nodes. Copy information to the extent list.
3799 */
3800 for (;;) {
f9e56f43 3801 xfs_bmbt_rec_t *frp, *temp;
2bd0ea18
NS
3802 xfs_fsblock_t nextbno;
3803 xfs_extnum_t num_recs;
3804
3805
3806 num_recs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
4ca431fc 3807 if (unlikely(i + num_recs > room)) {
2bd0ea18
NS
3808 ASSERT(i + num_recs <= room);
3809 xfs_fs_cmn_err(CE_WARN, ip->i_mount,
4ca431fc 3810 "corrupt dinode %Lu, (btree extents). Unmount and run xfs_repair.",
31c5308f 3811 (unsigned long long) ip->i_ino);
4ca431fc
NS
3812 XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
3813 XFS_ERRLEVEL_LOW,
3814 ip->i_mount);
2bd0ea18
NS
3815 goto error0;
3816 }
3817 XFS_WANT_CORRUPTED_GOTO(
3818 XFS_BMAP_SANITY_CHECK(mp, block, 0),
3819 error0);
3820 /*
3821 * Read-ahead the next leaf block, if any.
3822 */
3823 nextbno = INT_GET(block->bb_rightsib, ARCH_CONVERT);
3824 if (nextbno != NULLFSBLOCK)
3825 xfs_btree_reada_bufl(mp, nextbno, 1);
3826 /*
3827 * Copy records into the extent list.
3828 */
3829 frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
3830 block, 1, mp->m_bmap_dmxr[0]);
f9e56f43
NS
3831 temp = trp;
3832 for (j = 0; j < num_recs; j++, frp++, trp++) {
3833 trp->l0 = INT_GET(frp->l0, ARCH_CONVERT);
3834 trp->l1 = INT_GET(frp->l1, ARCH_CONVERT);
3835 }
2bd0ea18
NS
3836 if (exntf == XFS_EXTFMT_NOSTATE) {
3837 /*
3838 * Check all attribute bmap btree records and
5000d01d 3839 * any "older" data bmap btree records for a
2bd0ea18
NS
3840 * set bit in the "extent flag" position.
3841 */
4ca431fc
NS
3842 if (unlikely(xfs_check_nostate_extents(temp, num_recs))) {
3843 XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
3844 XFS_ERRLEVEL_LOW,
3845 ip->i_mount);
2bd0ea18
NS
3846 goto error0;
3847 }
3848 }
2bd0ea18
NS
3849 i += num_recs;
3850 xfs_trans_brelse(tp, bp);
3851 bno = nextbno;
3852 /*
3853 * If we've reached the end, stop.
3854 */
3855 if (bno == NULLFSBLOCK)
3856 break;
0e266570
NS
3857 if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
3858 XFS_BMAP_BTREE_REF)))
2bd0ea18
NS
3859 return error;
3860 block = XFS_BUF_TO_BMBT_BLOCK(bp);
3861 }
3862 ASSERT(i == ifp->if_bytes / (uint)sizeof(*trp));
3863 ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
3864 xfs_bmap_trace_exlist(fname, ip, i, whichfork);
3865 return 0;
3866error0:
3867 xfs_trans_brelse(tp, bp);
3868 return XFS_ERROR(EFSCORRUPTED);
3869}
3870
3871/*
3872 * Map file blocks to filesystem blocks.
3873 * File range is given by the bno/len pair.
3874 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
3875 * into a hole or past eof.
3876 * Only allocates blocks from a single allocation group,
3877 * to avoid locking problems.
3878 * The returned value in "firstblock" from the first call in a transaction
3879 * must be remembered and presented to subsequent calls in "firstblock".
3880 * An upper bound for the number of blocks to be allocated is supplied to
3881 * the first call in "total"; if no allocation group has that many free
3882 * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
3883 */
3884int /* error */
3885xfs_bmapi(
3886 xfs_trans_t *tp, /* transaction pointer */
3887 xfs_inode_t *ip, /* incore inode */
3888 xfs_fileoff_t bno, /* starting file offs. mapped */
3889 xfs_filblks_t len, /* length to map in file */
3890 int flags, /* XFS_BMAPI_... */
3891 xfs_fsblock_t *firstblock, /* first allocated block
3892 controls a.g. for allocs */
3893 xfs_extlen_t total, /* total blocks needed */
dfc130f3 3894 xfs_bmbt_irec_t *mval, /* output: map values */
2bd0ea18 3895 int *nmap, /* i/o: mval size/count */
dfc130f3 3896 xfs_bmap_free_t *flist) /* i/o: list extents to free */
2bd0ea18
NS
3897{
3898 xfs_fsblock_t abno; /* allocated block number */
3899 xfs_extlen_t alen; /* allocated extent length */
3900 xfs_fileoff_t aoff; /* allocated file offset */
3901 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */
dfc130f3 3902 xfs_btree_cur_t *cur; /* bmap btree cursor */
2bd0ea18
NS
3903 xfs_fileoff_t end; /* end of mapped file region */
3904 int eof; /* we've hit the end of extent list */
399ab595
NS
3905 char contig; /* allocation must be one extent */
3906 char delay; /* this request is for delayed alloc */
3907 char exact; /* don't do all of wasdelayed extent */
3908 char convert; /* unwritten extent I/O completion */
2bd0ea18
NS
3909 xfs_bmbt_rec_t *ep; /* extent list entry pointer */
3910 int error; /* error return */
dfc130f3 3911 xfs_bmbt_irec_t got; /* current extent list record */
2bd0ea18
NS
3912 xfs_ifork_t *ifp; /* inode fork pointer */
3913 xfs_extlen_t indlen; /* indirect blocks length */
2bd0ea18
NS
3914 xfs_extnum_t lastx; /* last useful extent number */
3915 int logflags; /* flags for transaction logging */
3916 xfs_extlen_t minleft; /* min blocks left after allocation */
3917 xfs_extlen_t minlen; /* min allocation size */
3918 xfs_mount_t *mp; /* xfs mount structure */
3919 int n; /* current extent index */
3920 int nallocs; /* number of extents alloc\'d */
3921 xfs_extnum_t nextents; /* number of extents in file */
3922 xfs_fileoff_t obno; /* old block number (offset) */
dfc130f3 3923 xfs_bmbt_irec_t prev; /* previous extent list record */
2bd0ea18 3924 int tmp_logflags; /* temp flags holder */
399ab595
NS
3925 int whichfork; /* data or attr fork */
3926 char inhole; /* current location is hole in file */
3927 char stateless; /* ignore state flag set */
2bd0ea18
NS
3928 char trim; /* output trimmed to match range */
3929 char userdata; /* allocating non-metadata */
3930 char wasdelay; /* old extent was delayed */
2bd0ea18 3931 char wr; /* this is a write request */
399ab595 3932 char rt; /* this is a realtime file */
85a875e9 3933 char rsvd; /* OK to allocate reserved blocks */
2bd0ea18
NS
3934#ifdef DEBUG
3935 xfs_fileoff_t orig_bno; /* original block number value */
3936 int orig_flags; /* original flags arg value */
3937 xfs_filblks_t orig_len; /* original value of len arg */
dfc130f3 3938 xfs_bmbt_irec_t *orig_mval; /* original value of mval */
2bd0ea18
NS
3939 int orig_nmap; /* original value of *nmap */
3940
3941 orig_bno = bno;
3942 orig_len = len;
3943 orig_flags = flags;
3944 orig_mval = mval;
3945 orig_nmap = *nmap;
3946#endif
3947 ASSERT(*nmap >= 1);
3948 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
3949 whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
3950 XFS_ATTR_FORK : XFS_DATA_FORK;
4ca431fc
NS
3951 mp = ip->i_mount;
3952 if (unlikely(XFS_TEST_ERROR(
3953 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
3954 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
3955 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
3956 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
3957 XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp);
2bd0ea18 3958 return XFS_ERROR(EFSCORRUPTED);
63be04eb 3959 }
2bd0ea18
NS
3960 if (XFS_FORCED_SHUTDOWN(mp))
3961 return XFS_ERROR(EIO);
399ab595 3962 rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
2bd0ea18
NS
3963 ifp = XFS_IFORK_PTR(ip, whichfork);
3964 ASSERT(ifp->if_ext_max ==
3965 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
0e266570 3966 if ((wr = (flags & XFS_BMAPI_WRITE)) != 0)
32a82561 3967 XFS_STATS_INC(xs_blk_mapw);
2bd0ea18 3968 else
32a82561 3969 XFS_STATS_INC(xs_blk_mapr);
2bd0ea18
NS
3970 delay = (flags & XFS_BMAPI_DELAY) != 0;
3971 trim = (flags & XFS_BMAPI_ENTIRE) == 0;
3972 userdata = (flags & XFS_BMAPI_METADATA) == 0;
399ab595 3973 convert = (flags & XFS_BMAPI_CONVERT) != 0;
2bd0ea18
NS
3974 exact = (flags & XFS_BMAPI_EXACT) != 0;
3975 rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
3976 contig = (flags & XFS_BMAPI_CONTIG) != 0;
3977 /*
3978 * stateless is used to combine extents which
3979 * differ only due to the state of the extents.
3980 * This technique is used from xfs_getbmap()
3981 * when the caller does not wish to see the
3982 * separation (which is the default).
3983 *
5000d01d 3984 * This technique is also used when writing a
2bd0ea18
NS
3985 * buffer which has been partially written,
3986 * (usually by being flushed during a chunkread),
3987 * to ensure one write takes place. This also
3988 * prevents a change in the xfs inode extents at
3989 * this time, intentionally. This change occurs
3990 * on completion of the write operation, in
3991 * xfs_strat_comp(), where the xfs_bmapi() call
3992 * is transactioned, and the extents combined.
3993 */
3994 stateless = (flags & XFS_BMAPI_IGSTATE) != 0;
3995 if (stateless && wr) /* if writing unwritten space, no */
3996 wr = 0; /* allocations are allowed */
3997 ASSERT(wr || !delay);
3998 logflags = 0;
3999 nallocs = 0;
4000 cur = NULL;
4001 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4002 ASSERT(wr && tp);
eae766ca
NS
4003 if ((error = xfs_bmap_local_to_extents(tp, ip,
4004 firstblock, total, &logflags, whichfork)))
2bd0ea18
NS
4005 goto error0;
4006 }
4007 if (wr && *firstblock == NULLFSBLOCK) {
4008 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
4009 minleft = INT_GET(ifp->if_broot->bb_level, ARCH_CONVERT) + 1;
4010 else
4011 minleft = 1;
4012 } else
4013 minleft = 0;
4014 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4015 (error = xfs_iread_extents(tp, ip, whichfork)))
4016 goto error0;
4017 ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4018 &prev);
4019 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4020 n = 0;
4021 end = bno + len;
4022 obno = bno;
4023 bma.ip = NULL;
4024 while (bno < end && n < *nmap) {
5000d01d 4025 /*
2bd0ea18
NS
4026 * Reading past eof, act as though there's a hole
4027 * up to end.
4028 */
4029 if (eof && !wr)
4030 got.br_startoff = end;
4031 inhole = eof || got.br_startoff > bno;
4032 wasdelay = wr && !inhole && !delay &&
4033 ISNULLSTARTBLOCK(got.br_startblock);
4034 /*
5000d01d 4035 * First, deal with the hole before the allocated space
2bd0ea18
NS
4036 * that we found, if any.
4037 */
4038 if (wr && (inhole || wasdelay)) {
4039 /*
4040 * For the wasdelay case, we could also just
4041 * allocate the stuff asked for in this bmap call
4042 * but that wouldn't be as good.
4043 */
4044 if (wasdelay && !exact) {
4045 alen = (xfs_extlen_t)got.br_blockcount;
4046 aoff = got.br_startoff;
4047 if (lastx != NULLEXTNUM && lastx) {
4048 ep = &ifp->if_u1.if_extents[lastx - 1];
4049 xfs_bmbt_get_all(ep, &prev);
4050 }
4051 } else if (wasdelay) {
4052 alen = (xfs_extlen_t)
4053 XFS_FILBLKS_MIN(len,
4054 (got.br_startoff +
4055 got.br_blockcount) - bno);
4056 aoff = bno;
4057 } else {
4058 alen = (xfs_extlen_t)
4059 XFS_FILBLKS_MIN(len, MAXEXTLEN);
4060 if (!eof)
4061 alen = (xfs_extlen_t)
4062 XFS_FILBLKS_MIN(alen,
4063 got.br_startoff - bno);
4064 aoff = bno;
4065 }
4066 minlen = contig ? alen : 1;
4067 if (delay) {
399ab595
NS
4068 xfs_extlen_t extsz;
4069
4070 /* Figure out the extent size, adjust alen */
4071 if (rt) {
4072 if (!(extsz = ip->i_d.di_extsize))
4073 extsz = mp->m_sb.sb_rextsize;
4074 } else {
4075 extsz = ip->i_d.di_extsize;
4076 }
4077 if (extsz) {
4078 error = xfs_bmap_extsize_align(mp,
4079 &got, &prev, extsz,
4080 rt, eof, delay, convert,
4081 &aoff, &alen);
4082 ASSERT(!error);
4083 }
4084
4085 if (rt)
4086 extsz = alen / mp->m_sb.sb_rextsize;
4087
2bd0ea18
NS
4088 /*
4089 * Make a transaction-less quota reservation for
4090 * delayed allocation blocks. This number gets
4091 * adjusted later.
4092 * We return EDQUOT if we haven't allocated
4093 * blks already inside this loop;
4094 */
399ab595
NS
4095 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
4096 mp, NULL, ip, (long)alen, 0,
4097 rt ? XFS_QMOPT_RES_RTBLKS :
4098 XFS_QMOPT_RES_REGBLKS)) {
2bd0ea18
NS
4099 if (n == 0) {
4100 *nmap = 0;
4101 ASSERT(cur == NULL);
4102 return XFS_ERROR(EDQUOT);
4103 }
4104 break;
4105 }
062998e3
NS
4106
4107 /*
4108 * Split changing sb for alen and indlen since
4109 * they could be coming from different places.
4110 */
399ab595
NS
4111 indlen = (xfs_extlen_t)
4112 xfs_bmap_worst_indlen(ip, alen);
4113 ASSERT(indlen > 0);
4114
4115 if (rt) {
4116 error = xfs_mod_incore_sb(mp,
4117 XFS_SBS_FREXTENTS,
4118 -(extsz), rsvd);
062998e3 4119 } else {
399ab595
NS
4120 error = xfs_mod_incore_sb(mp,
4121 XFS_SBS_FDBLOCKS,
4122 -(alen), rsvd);
4123 }
4124 if (!error) {
4125 error = xfs_mod_incore_sb(mp,
4126 XFS_SBS_FDBLOCKS,
4127 -(indlen), rsvd);
4128 if (error && rt) {
4129 xfs_mod_incore_sb(ip->i_mount,
4130 XFS_SBS_FREXTENTS,
4131 extsz, rsvd);
4132 } else if (error) {
4133 xfs_mod_incore_sb(ip->i_mount,
4134 XFS_SBS_FDBLOCKS,
4135 alen, rsvd);
062998e3
NS
4136 }
4137 }
4138
399ab595
NS
4139 if (error) {
4140 if (XFS_IS_QUOTA_ON(ip->i_mount))
4141 /* unreserve the blocks now */
4142 (void)
4143 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
4144 mp, NULL, ip,
4145 (long)alen, 0, rt ?
4146 XFS_QMOPT_RES_RTBLKS :
4147 XFS_QMOPT_RES_REGBLKS);
2bd0ea18
NS
4148 break;
4149 }
399ab595 4150
2bd0ea18
NS
4151 ip->i_delayed_blks += alen;
4152 abno = NULLSTARTBLOCK(indlen);
4153 } else {
4154 /*
4155 * If first time, allocate and fill in
4156 * once-only bma fields.
4157 */
4158 if (bma.ip == NULL) {
4159 bma.tp = tp;
4160 bma.ip = ip;
4161 bma.prevp = &prev;
4162 bma.gotp = &got;
4163 bma.total = total;
34317449
NS
4164 bma.userdata = 0;
4165 }
4166 /* Indicate if this is the first user data
4167 * in the file, or just any user data.
4168 */
4169 if (userdata) {
5000d01d
SL
4170 bma.userdata = (aoff == 0) ?
4171 XFS_ALLOC_INITIAL_USER_DATA :
34317449 4172 XFS_ALLOC_USERDATA;
2bd0ea18
NS
4173 }
4174 /*
4175 * Fill in changeable bma fields.
4176 */
4177 bma.eof = eof;
4178 bma.firstblock = *firstblock;
4179 bma.alen = alen;
4180 bma.off = aoff;
399ab595 4181 bma.conv = convert;
2bd0ea18
NS
4182 bma.wasdel = wasdelay;
4183 bma.minlen = minlen;
4184 bma.low = flist->xbf_low;
4185 bma.minleft = minleft;
4186 /*
4187 * Only want to do the alignment at the
5000d01d 4188 * eof if it is userdata and allocation length
2bd0ea18
NS
4189 * is larger than a stripe unit.
4190 */
4191 if (mp->m_dalign && alen >= mp->m_dalign &&
4192 userdata && whichfork == XFS_DATA_FORK) {
0e266570
NS
4193 if ((error = xfs_bmap_isaeof(ip, aoff,
4194 whichfork, &bma.aeof)))
2bd0ea18
NS
4195 goto error0;
4196 } else
4197 bma.aeof = 0;
4198 /*
4199 * Call allocator.
4200 */
0e266570 4201 if ((error = xfs_bmap_alloc(&bma)))
2bd0ea18
NS
4202 goto error0;
4203 /*
4204 * Copy out result fields.
4205 */
4206 abno = bma.rval;
0e266570 4207 if ((flist->xbf_low = bma.low))
2bd0ea18
NS
4208 minleft = 0;
4209 alen = bma.alen;
4210 aoff = bma.off;
4211 ASSERT(*firstblock == NULLFSBLOCK ||
eae766ca
NS
4212 XFS_FSB_TO_AGNO(mp, *firstblock) ==
4213 XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
2bd0ea18 4214 (flist->xbf_low &&
eae766ca
NS
4215 XFS_FSB_TO_AGNO(mp, *firstblock) <
4216 XFS_FSB_TO_AGNO(mp, bma.firstblock)));
2bd0ea18
NS
4217 *firstblock = bma.firstblock;
4218 if (cur)
4219 cur->bc_private.b.firstblock =
4220 *firstblock;
4221 if (abno == NULLFSBLOCK)
4222 break;
4223 if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
eae766ca 4224 cur = xfs_btree_init_cursor(mp,
2bd0ea18
NS
4225 tp, NULL, 0, XFS_BTNUM_BMAP,
4226 ip, whichfork);
4227 cur->bc_private.b.firstblock =
4228 *firstblock;
4229 cur->bc_private.b.flist = flist;
4230 }
4231 /*
4232 * Bump the number of extents we've allocated
4233 * in this call.
4234 */
4235 nallocs++;
4236 }
4237 if (cur)
4238 cur->bc_private.b.flags =
4239 wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
4240 got.br_startoff = aoff;
4241 got.br_startblock = abno;
4242 got.br_blockcount = alen;
4243 got.br_state = XFS_EXT_NORM; /* assume normal */
4244 /*
4245 * Determine state of extent, and the filesystem.
5000d01d 4246 * A wasdelay extent has been initialized, so
2bd0ea18
NS
4247 * shouldn't be flagged as unwritten.
4248 */
4249 if (wr && XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
4250 if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
4251 got.br_state = XFS_EXT_UNWRITTEN;
4252 }
4253 error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
4254 firstblock, flist, &tmp_logflags, whichfork,
4255 rsvd);
4256 logflags |= tmp_logflags;
4257 if (error)
4258 goto error0;
4259 lastx = ifp->if_lastex;
4260 ep = &ifp->if_u1.if_extents[lastx];
4261 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4262 xfs_bmbt_get_all(ep, &got);
4263 ASSERT(got.br_startoff <= aoff);
4264 ASSERT(got.br_startoff + got.br_blockcount >=
4265 aoff + alen);
4266#ifdef DEBUG
4267 if (delay) {
4268 ASSERT(ISNULLSTARTBLOCK(got.br_startblock));
4269 ASSERT(STARTBLOCKVAL(got.br_startblock) > 0);
4270 }
4271 ASSERT(got.br_state == XFS_EXT_NORM ||
4272 got.br_state == XFS_EXT_UNWRITTEN);
4273#endif
4274 /*
4275 * Fall down into the found allocated space case.
4276 */
4277 } else if (inhole) {
4278 /*
4279 * Reading in a hole.
4280 */
4281 mval->br_startoff = bno;
4282 mval->br_startblock = HOLESTARTBLOCK;
4283 mval->br_blockcount =
4284 XFS_FILBLKS_MIN(len, got.br_startoff - bno);
4285 mval->br_state = XFS_EXT_NORM;
4286 bno += mval->br_blockcount;
4287 len -= mval->br_blockcount;
4288 mval++;
4289 n++;
4290 continue;
4291 }
4292 /*
4293 * Then deal with the allocated space we found.
4294 */
4295 ASSERT(ep != NULL);
4296 if (trim && (got.br_startoff + got.br_blockcount > obno)) {
4297 if (obno > bno)
4298 bno = obno;
4299 ASSERT((bno >= obno) || (n == 0));
4300 ASSERT(bno < end);
4301 mval->br_startoff = bno;
4302 if (ISNULLSTARTBLOCK(got.br_startblock)) {
4303 ASSERT(!wr || delay);
4304 mval->br_startblock = DELAYSTARTBLOCK;
4305 } else
4306 mval->br_startblock =
4307 got.br_startblock +
4308 (bno - got.br_startoff);
4309 /*
4310 * Return the minimum of what we got and what we
4311 * asked for for the length. We can use the len
4312 * variable here because it is modified below
4313 * and we could have been there before coming
4314 * here if the first part of the allocation
4315 * didn't overlap what was asked for.
4316 */
4317 mval->br_blockcount =
4318 XFS_FILBLKS_MIN(end - bno, got.br_blockcount -
4319 (bno - got.br_startoff));
4320 mval->br_state = got.br_state;
4321 ASSERT(mval->br_blockcount <= len);
4322 } else {
4323 *mval = got;
4324 if (ISNULLSTARTBLOCK(mval->br_startblock)) {
4325 ASSERT(!wr || delay);
4326 mval->br_startblock = DELAYSTARTBLOCK;
4327 }
4328 }
4329
4330 /*
4331 * Check if writing previously allocated but
4332 * unwritten extents.
4333 */
4334 if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
4335 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
4336 /*
4337 * Modify (by adding) the state flag, if writing.
4338 */
4339 ASSERT(mval->br_blockcount <= len);
4340 if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
eae766ca 4341 cur = xfs_btree_init_cursor(mp,
2bd0ea18
NS
4342 tp, NULL, 0, XFS_BTNUM_BMAP,
4343 ip, whichfork);
4344 cur->bc_private.b.firstblock =
4345 *firstblock;
4346 cur->bc_private.b.flist = flist;
4347 }
4348 mval->br_state = XFS_EXT_NORM;
4349 error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
4350 firstblock, flist, &tmp_logflags, whichfork,
4351 rsvd);
4352 logflags |= tmp_logflags;
4353 if (error)
4354 goto error0;
4355 lastx = ifp->if_lastex;
4356 ep = &ifp->if_u1.if_extents[lastx];
4357 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4358 xfs_bmbt_get_all(ep, &got);
4359 /*
5000d01d
SL
4360 * We may have combined previously unwritten
4361 * space with written space, so generate
2bd0ea18
NS
4362 * another request.
4363 */
4364 if (mval->br_blockcount < len)
4365 continue;
4366 }
4367
4368 ASSERT(!trim ||
4369 ((mval->br_startoff + mval->br_blockcount) <= end));
4370 ASSERT(!trim || (mval->br_blockcount <= len) ||
4371 (mval->br_startoff < obno));
4372 bno = mval->br_startoff + mval->br_blockcount;
4373 len = end - bno;
4374 if (n > 0 && mval->br_startoff == mval[-1].br_startoff) {
4375 ASSERT(mval->br_startblock == mval[-1].br_startblock);
4376 ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
4377 ASSERT(mval->br_state == mval[-1].br_state);
4378 mval[-1].br_blockcount = mval->br_blockcount;
4379 mval[-1].br_state = mval->br_state;
4380 } else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
4381 mval[-1].br_startblock != DELAYSTARTBLOCK &&
4382 mval[-1].br_startblock != HOLESTARTBLOCK &&
4383 mval->br_startblock ==
4384 mval[-1].br_startblock + mval[-1].br_blockcount &&
4385 (stateless || mval[-1].br_state == mval->br_state)) {
4386 ASSERT(mval->br_startoff ==
4387 mval[-1].br_startoff + mval[-1].br_blockcount);
4388 mval[-1].br_blockcount += mval->br_blockcount;
4389 } else if (n > 0 &&
4390 mval->br_startblock == DELAYSTARTBLOCK &&
4391 mval[-1].br_startblock == DELAYSTARTBLOCK &&
4392 mval->br_startoff ==
4393 mval[-1].br_startoff + mval[-1].br_blockcount) {
4394 mval[-1].br_blockcount += mval->br_blockcount;
4395 mval[-1].br_state = mval->br_state;
4396 } else if (!((n == 0) &&
4397 ((mval->br_startoff + mval->br_blockcount) <=
4398 obno))) {
4399 mval++;
4400 n++;
4401 }
4402 /*
4403 * If we're done, stop now. Stop when we've allocated
4404 * XFS_BMAP_MAX_NMAP extents no matter what. Otherwise
4405 * the transaction may get too big.
4406 */
4407 if (bno >= end || n >= *nmap || nallocs >= *nmap)
4408 break;
4409 /*
4410 * Else go on to the next record.
4411 */
4412 ep++;
4413 lastx++;
4414 if (lastx >= nextents) {
4415 eof = 1;
4416 prev = got;
4417 } else
4418 xfs_bmbt_get_all(ep, &got);
4419 }
4420 ifp->if_lastex = lastx;
4421 *nmap = n;
4422 /*
4423 * Transform from btree to extents, give it cur.
4424 */
4425 if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
4426 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
4427 ASSERT(wr && cur);
4428 error = xfs_bmap_btree_to_extents(tp, ip, cur,
4ca431fc 4429 &tmp_logflags, whichfork);
2bd0ea18
NS
4430 logflags |= tmp_logflags;
4431 if (error)
4432 goto error0;
4433 }
4434 ASSERT(ifp->if_ext_max ==
4435 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4436 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
4437 XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
4438 error = 0;
4439
4440error0:
4441 /*
4442 * Log everything. Do this after conversion, there's no point in
4443 * logging the extent list if we've converted to btree format.
4444 */
4445 if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
4446 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
4447 logflags &= ~XFS_ILOG_FEXT(whichfork);
4448 else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
4449 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
4450 logflags &= ~XFS_ILOG_FBROOT(whichfork);
4451 /*
4452 * Log whatever the flags say, even if error. Otherwise we might miss
4453 * detecting a case where the data is changed, there's an error,
4454 * and it's not logged so we don't shutdown when we should.
4455 */
4456 if (logflags) {
4457 ASSERT(tp && wr);
4458 xfs_trans_log_inode(tp, ip, logflags);
4459 }
4460 if (cur) {
4461 if (!error) {
4462 ASSERT(*firstblock == NULLFSBLOCK ||
eae766ca
NS
4463 XFS_FSB_TO_AGNO(mp, *firstblock) ==
4464 XFS_FSB_TO_AGNO(mp,
2bd0ea18
NS
4465 cur->bc_private.b.firstblock) ||
4466 (flist->xbf_low &&
eae766ca
NS
4467 XFS_FSB_TO_AGNO(mp, *firstblock) <
4468 XFS_FSB_TO_AGNO(mp,
2bd0ea18
NS
4469 cur->bc_private.b.firstblock)));
4470 *firstblock = cur->bc_private.b.firstblock;
4471 }
4472 xfs_btree_del_cursor(cur,
4473 error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
4474 }
4475 if (!error)
4476 xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
4477 orig_nmap, *nmap);
4478 return error;
4479}
4480
4481/*
4482 * Map file blocks to filesystem blocks, simple version.
4483 * One block (extent) only, read-only.
4484 * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
4485 * For the other flag values, the effect is as if XFS_BMAPI_METADATA
4486 * was set and all the others were clear.
4487 */
4488int /* error */
4489xfs_bmapi_single(
4490 xfs_trans_t *tp, /* transaction pointer */
4491 xfs_inode_t *ip, /* incore inode */
4492 int whichfork, /* data or attr fork */
4493 xfs_fsblock_t *fsb, /* output: mapped block */
4494 xfs_fileoff_t bno) /* starting file offs. mapped */
4495{
4496 int eof; /* we've hit the end of extent list */
4497 int error; /* error return */
dfc130f3 4498 xfs_bmbt_irec_t got; /* current extent list record */
2bd0ea18
NS
4499 xfs_ifork_t *ifp; /* inode fork pointer */
4500 xfs_extnum_t lastx; /* last useful extent number */
dfc130f3 4501 xfs_bmbt_irec_t prev; /* previous extent list record */
2bd0ea18
NS
4502
4503 ifp = XFS_IFORK_PTR(ip, whichfork);
4ca431fc
NS
4504 if (unlikely(
4505 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4506 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) {
4507 XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW,
4508 ip->i_mount);
2bd0ea18 4509 return XFS_ERROR(EFSCORRUPTED);
63be04eb 4510 }
2bd0ea18
NS
4511 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
4512 return XFS_ERROR(EIO);
32a82561 4513 XFS_STATS_INC(xs_blk_mapr);
2bd0ea18
NS
4514 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4515 (error = xfs_iread_extents(tp, ip, whichfork)))
4516 return error;
4517 (void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4518 &prev);
5000d01d 4519 /*
2bd0ea18
NS
4520 * Reading past eof, act as though there's a hole
4521 * up to end.
4522 */
4523 if (eof || got.br_startoff > bno) {
4524 *fsb = NULLFSBLOCK;
4525 return 0;
4526 }
4527 ASSERT(!ISNULLSTARTBLOCK(got.br_startblock));
4528 ASSERT(bno < got.br_startoff + got.br_blockcount);
4529 *fsb = got.br_startblock + (bno - got.br_startoff);
4530 ifp->if_lastex = lastx;
4531 return 0;
4532}
4533
4534/*
4535 * Unmap (remove) blocks from a file.
4536 * If nexts is nonzero then the number of extents to remove is limited to
dfc130f3 4537 * that value. If not all extents in the block range can be removed then
2bd0ea18
NS
4538 * *done is set.
4539 */
4540int /* error */
4541xfs_bunmapi(
4542 xfs_trans_t *tp, /* transaction pointer */
4543 struct xfs_inode *ip, /* incore inode */
4544 xfs_fileoff_t bno, /* starting offset to unmap */
4545 xfs_filblks_t len, /* length to unmap in file */
5000d01d 4546 int flags, /* misc flags */
2bd0ea18
NS
4547 xfs_extnum_t nexts, /* number of extents max */
4548 xfs_fsblock_t *firstblock, /* first allocated block
4549 controls a.g. for allocs */
4550 xfs_bmap_free_t *flist, /* i/o: list extents to free */
4551 int *done) /* set if not done yet */
4552{
2bd0ea18
NS
4553 xfs_btree_cur_t *cur; /* bmap btree cursor */
4554 xfs_bmbt_irec_t del; /* extent being deleted */
4555 int eof; /* is deleting at eof */
4556 xfs_bmbt_rec_t *ep; /* extent list entry pointer */
4557 int error; /* error return value */
4558 xfs_extnum_t extno; /* extent number in list */
4559 xfs_bmbt_irec_t got; /* current extent list entry */
4560 xfs_ifork_t *ifp; /* inode fork pointer */
4561 int isrt; /* freeing in rt area */
4562 xfs_extnum_t lastx; /* last extent index used */
4563 int logflags; /* transaction logging flags */
4564 xfs_extlen_t mod; /* rt extent offset */
4565 xfs_mount_t *mp; /* mount structure */
4566 xfs_extnum_t nextents; /* size of extent list */
4567 xfs_bmbt_irec_t prev; /* previous extent list entry */
4568 xfs_fileoff_t start; /* first file offset deleted */
4569 int tmp_logflags; /* partial logging flags */
4570 int wasdel; /* was a delayed alloc extent */
4571 int whichfork; /* data or attribute fork */
4572 int rsvd; /* OK to allocate reserved blocks */
4573 xfs_fsblock_t sum;
4574
4575 xfs_bunmap_trace(ip, bno, len, flags, (inst_t *)__return_address);
4576 whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4577 XFS_ATTR_FORK : XFS_DATA_FORK;
4578 ifp = XFS_IFORK_PTR(ip, whichfork);
4ca431fc
NS
4579 if (unlikely(
4580 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4581 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
4582 XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
4583 ip->i_mount);
2bd0ea18 4584 return XFS_ERROR(EFSCORRUPTED);
63be04eb 4585 }
2bd0ea18
NS
4586 mp = ip->i_mount;
4587 if (XFS_FORCED_SHUTDOWN(mp))
4588 return XFS_ERROR(EIO);
2bd0ea18
NS
4589 rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
4590 ASSERT(len > 0);
4591 ASSERT(nexts >= 0);
4592 ASSERT(ifp->if_ext_max ==
4593 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4594 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4595 (error = xfs_iread_extents(tp, ip, whichfork)))
4596 return error;
4597 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4598 if (nextents == 0) {
4599 *done = 1;
4600 return 0;
4601 }
32a82561 4602 XFS_STATS_INC(xs_blk_unmap);
399ab595 4603 isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
2bd0ea18
NS
4604 start = bno;
4605 bno = start + len - 1;
4606 ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4607 &prev);
4608 /*
4609 * Check to see if the given block number is past the end of the
4610 * file, back up to the last block if so...
4611 */
4612 if (eof) {
4613 ep = &ifp->if_u1.if_extents[--lastx];
4614 xfs_bmbt_get_all(ep, &got);
4615 bno = got.br_startoff + got.br_blockcount - 1;
4616 }
4617 logflags = 0;
4618 if (ifp->if_flags & XFS_IFBROOT) {
4619 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
4620 cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
4621 whichfork);
4622 cur->bc_private.b.firstblock = *firstblock;
4623 cur->bc_private.b.flist = flist;
4624 cur->bc_private.b.flags = 0;
4625 } else
4626 cur = NULL;
4627 extno = 0;
4628 while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
4629 (nexts == 0 || extno < nexts)) {
4630 /*
4631 * Is the found extent after a hole in which bno lives?
4632 * Just back up to the previous extent, if so.
4633 */
4634 if (got.br_startoff > bno) {
4635 if (--lastx < 0)
4636 break;
4637 ep--;
4638 xfs_bmbt_get_all(ep, &got);
4639 }
4640 /*
4641 * Is the last block of this extent before the range
4642 * we're supposed to delete? If so, we're done.
4643 */
4644 bno = XFS_FILEOFF_MIN(bno,
4645 got.br_startoff + got.br_blockcount - 1);
4646 if (bno < start)
4647 break;
4648 /*
4649 * Then deal with the (possibly delayed) allocated space
4650 * we found.
4651 */
4652 ASSERT(ep != NULL);
4653 del = got;
4654 wasdel = ISNULLSTARTBLOCK(del.br_startblock);
4655 if (got.br_startoff < start) {
4656 del.br_startoff = start;
4657 del.br_blockcount -= start - got.br_startoff;
4658 if (!wasdel)
4659 del.br_startblock += start - got.br_startoff;
4660 }
4661 if (del.br_startoff + del.br_blockcount > bno + 1)
4662 del.br_blockcount = bno + 1 - del.br_startoff;
4663 sum = del.br_startblock + del.br_blockcount;
4664 if (isrt &&
4665 (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
4666 /*
4667 * Realtime extent not lined up at the end.
4668 * The extent could have been split into written
4669 * and unwritten pieces, or we could just be
4670 * unmapping part of it. But we can't really
4671 * get rid of part of a realtime extent.
4672 */
4673 if (del.br_state == XFS_EXT_UNWRITTEN ||
4674 !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
4675 /*
4676 * This piece is unwritten, or we're not
4677 * using unwritten extents. Skip over it.
4678 */
4679 ASSERT(bno >= mod);
4680 bno -= mod > del.br_blockcount ?
4681 del.br_blockcount : mod;
4682 if (bno < got.br_startoff) {
4683 if (--lastx >= 0)
4684 xfs_bmbt_get_all(--ep, &got);
4685 }
4686 continue;
4687 }
4688 /*
4689 * It's written, turn it unwritten.
4690 * This is better than zeroing it.
4691 */
4692 ASSERT(del.br_state == XFS_EXT_NORM);
4693 ASSERT(xfs_trans_get_block_res(tp) > 0);
4694 /*
4695 * If this spans a realtime extent boundary,
4696 * chop it back to the start of the one we end at.
4697 */
4698 if (del.br_blockcount > mod) {
4699 del.br_startoff += del.br_blockcount - mod;
4700 del.br_startblock += del.br_blockcount - mod;
4701 del.br_blockcount = mod;
4702 }
4703 del.br_state = XFS_EXT_UNWRITTEN;
4704 error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
4705 firstblock, flist, &logflags, XFS_DATA_FORK, 0);
4706 if (error)
4707 goto error0;
4708 goto nodelete;
4709 }
4710 if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
4711 /*
4712 * Realtime extent is lined up at the end but not
4713 * at the front. We'll get rid of full extents if
4714 * we can.
4715 */
4716 mod = mp->m_sb.sb_rextsize - mod;
4717 if (del.br_blockcount > mod) {
4718 del.br_blockcount -= mod;
4719 del.br_startoff += mod;
4720 del.br_startblock += mod;
4721 } else if ((del.br_startoff == start &&
4722 (del.br_state == XFS_EXT_UNWRITTEN ||
4723 xfs_trans_get_block_res(tp) == 0)) ||
4724 !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
4725 /*
4726 * Can't make it unwritten. There isn't
4727 * a full extent here so just skip it.
4728 */
4729 ASSERT(bno >= del.br_blockcount);
4730 bno -= del.br_blockcount;
4731 if (bno < got.br_startoff) {
4732 if (--lastx >= 0)
4733 xfs_bmbt_get_all(--ep, &got);
4734 }
4735 continue;
4736 } else if (del.br_state == XFS_EXT_UNWRITTEN) {
4737 /*
4738 * This one is already unwritten.
4739 * It must have a written left neighbor.
4740 * Unwrite the killed part of that one and
4741 * try again.
4742 */
4743 ASSERT(lastx > 0);
4744 xfs_bmbt_get_all(ep - 1, &prev);
4745 ASSERT(prev.br_state == XFS_EXT_NORM);
4746 ASSERT(!ISNULLSTARTBLOCK(prev.br_startblock));
4747 ASSERT(del.br_startblock ==
4748 prev.br_startblock + prev.br_blockcount);
4749 if (prev.br_startoff < start) {
4750 mod = start - prev.br_startoff;
4751 prev.br_blockcount -= mod;
4752 prev.br_startblock += mod;
4753 prev.br_startoff = start;
4754 }
4755 prev.br_state = XFS_EXT_UNWRITTEN;
4756 error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
4757 &prev, firstblock, flist, &logflags,
4758 XFS_DATA_FORK, 0);
4759 if (error)
4760 goto error0;
4761 goto nodelete;
4762 } else {
4763 ASSERT(del.br_state == XFS_EXT_NORM);
4764 del.br_state = XFS_EXT_UNWRITTEN;
4765 error = xfs_bmap_add_extent(ip, lastx, &cur,
4766 &del, firstblock, flist, &logflags,
4767 XFS_DATA_FORK, 0);
4768 if (error)
4769 goto error0;
4770 goto nodelete;
4771 }
4772 }
4773 if (wasdel) {
4774 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
399ab595
NS
4775 /* Update realtime/data freespace, unreserve quota */
4776 if (isrt) {
4777 xfs_filblks_t rtexts;
4778
4779 rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
4780 do_div(rtexts, mp->m_sb.sb_rextsize);
4781 xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
4782 (int)rtexts, rsvd);
4783 (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
4784 NULL, ip, -((long)del.br_blockcount), 0,
4785 XFS_QMOPT_RES_RTBLKS);
4786 } else {
4787 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
4788 (int)del.br_blockcount, rsvd);
4789 (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
4790 NULL, ip, -((long)del.br_blockcount), 0,
eae766ca 4791 XFS_QMOPT_RES_REGBLKS);
399ab595 4792 }
2bd0ea18
NS
4793 ip->i_delayed_blks -= del.br_blockcount;
4794 if (cur)
4795 cur->bc_private.b.flags |=
4796 XFS_BTCUR_BPRV_WASDEL;
4797 } else if (cur)
4798 cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
4799 /*
4800 * If it's the case where the directory code is running
5000d01d 4801 * with no block reservation, and the deleted block is in
2bd0ea18
NS
4802 * the middle of its extent, and the resulting insert
4803 * of an extent would cause transformation to btree format,
4804 * then reject it. The calling code will then swap
4805 * blocks around instead.
4806 * We have to do this now, rather than waiting for the
4807 * conversion to btree format, since the transaction
4808 * will be dirty.
4809 */
4810 if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
4811 XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
4812 XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
4813 del.br_startoff > got.br_startoff &&
5000d01d 4814 del.br_startoff + del.br_blockcount <
2bd0ea18
NS
4815 got.br_startoff + got.br_blockcount) {
4816 error = XFS_ERROR(ENOSPC);
4817 goto error0;
4818 }
4819 error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
4ca431fc 4820 &tmp_logflags, whichfork, rsvd);
2bd0ea18
NS
4821 logflags |= tmp_logflags;
4822 if (error)
4823 goto error0;
4824 bno = del.br_startoff - 1;
4825nodelete:
4826 lastx = ifp->if_lastex;
4827 /*
4828 * If not done go on to the next (previous) record.
4829 * Reset ep in case the extents array was re-alloced.
4830 */
4831 ep = &ifp->if_u1.if_extents[lastx];
4832 if (bno != (xfs_fileoff_t)-1 && bno >= start) {
4833 if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) ||
4834 xfs_bmbt_get_startoff(ep) > bno) {
4835 lastx--;
4836 ep--;
4837 }
4838 if (lastx >= 0)
4839 xfs_bmbt_get_all(ep, &got);
4840 extno++;
4841 }
4842 }
4843 ifp->if_lastex = lastx;
4844 *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
4845 ASSERT(ifp->if_ext_max ==
4846 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4847 /*
4848 * Convert to a btree if necessary.
4849 */
4850 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
4851 XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
4852 ASSERT(cur == NULL);
4853 error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
4854 &cur, 0, &tmp_logflags, whichfork);
4855 logflags |= tmp_logflags;
4856 if (error)
4857 goto error0;
4858 }
4859 /*
4860 * transform from btree to extents, give it cur
4861 */
4862 else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
4863 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
4864 ASSERT(cur != NULL);
4865 error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
4ca431fc 4866 whichfork);
2bd0ea18
NS
4867 logflags |= tmp_logflags;
4868 if (error)
4869 goto error0;
4870 }
4871 /*
4872 * transform from extents to local?
4873 */
4874 ASSERT(ifp->if_ext_max ==
4875 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4876 error = 0;
4877error0:
4878 /*
4879 * Log everything. Do this after conversion, there's no point in
4880 * logging the extent list if we've converted to btree format.
4881 */
4882 if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
4883 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
4884 logflags &= ~XFS_ILOG_FEXT(whichfork);
4885 else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
4886 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
4887 logflags &= ~XFS_ILOG_FBROOT(whichfork);
4888 /*
5000d01d 4889 * Log inode even in the error case, if the transaction
2bd0ea18
NS
4890 * is dirty we'll need to shut down the filesystem.
4891 */
4892 if (logflags)
4893 xfs_trans_log_inode(tp, ip, logflags);
4894 if (cur) {
4895 if (!error) {
4896 *firstblock = cur->bc_private.b.firstblock;
4897 cur->bc_private.b.allocated = 0;
4898 }
4899 xfs_btree_del_cursor(cur,
4900 error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
4901 }
4902 return error;
4903}
4904
4905/*
5000d01d
SL
4906 * Check the last inode extent to determine whether this allocation will result
4907 * in blocks being allocated at the end of the file. When we allocate new data
2bd0ea18
NS
4908 * blocks at the end of the file which do not start at the previous data block,
4909 * we will try to align the new blocks at stripe unit boundaries.
4910 */
4911int /* error */
4912xfs_bmap_isaeof(
4913 xfs_inode_t *ip, /* incore inode pointer */
dfc130f3
RC
4914 xfs_fileoff_t off, /* file offset in fsblocks */
4915 int whichfork, /* data or attribute fork */
85a875e9 4916 char *aeof) /* return value */
2bd0ea18
NS
4917{
4918 int error; /* error return value */
4919 xfs_ifork_t *ifp; /* inode fork pointer */
4920 xfs_bmbt_rec_t *lastrec; /* extent list entry pointer */
4921 xfs_extnum_t nextents; /* size of extent list */
dfc130f3 4922 xfs_bmbt_irec_t s; /* expanded extent list entry */
2bd0ea18
NS
4923
4924 ASSERT(whichfork == XFS_DATA_FORK);
4925 ifp = XFS_IFORK_PTR(ip, whichfork);
4926 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4927 (error = xfs_iread_extents(NULL, ip, whichfork)))
4928 return error;
4929 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4930 if (nextents == 0) {
4931 *aeof = 1;
4932 return 0;
4933 }
4934 /*
4935 * Go to the last extent
4936 */
4937 lastrec = &ifp->if_u1.if_extents[nextents - 1];
4938 xfs_bmbt_get_all(lastrec, &s);
4939 /*
4940 * Check we are allocating in the last extent (for delayed allocations)
4941 * or past the last extent for non-delayed allocations.
5000d01d 4942 */
2bd0ea18
NS
4943 *aeof = (off >= s.br_startoff &&
4944 off < s.br_startoff + s.br_blockcount &&
4945 ISNULLSTARTBLOCK(s.br_startblock)) ||
4946 off >= s.br_startoff + s.br_blockcount;
4947 return 0;
4948}