Merge tag 'xtensa-20180225' of git://github.com/jcmvbkbc/linux-xtensa
[cris-mirror.git] / fs / xfs / libxfs / xfs_rmap.c
blob79822cf6ebe36d62b8d912b1b44f5204e0ec1438
1 /*
2 * Copyright (c) 2014 Red Hat, Inc.
3 * All Rights Reserved.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
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.
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
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_shared.h"
21 #include "xfs_format.h"
22 #include "xfs_log_format.h"
23 #include "xfs_trans_resv.h"
24 #include "xfs_bit.h"
25 #include "xfs_sb.h"
26 #include "xfs_mount.h"
27 #include "xfs_defer.h"
28 #include "xfs_da_format.h"
29 #include "xfs_da_btree.h"
30 #include "xfs_btree.h"
31 #include "xfs_trans.h"
32 #include "xfs_alloc.h"
33 #include "xfs_rmap.h"
34 #include "xfs_rmap_btree.h"
35 #include "xfs_trans_space.h"
36 #include "xfs_trace.h"
37 #include "xfs_errortag.h"
38 #include "xfs_error.h"
39 #include "xfs_extent_busy.h"
40 #include "xfs_bmap.h"
41 #include "xfs_inode.h"
44 * Lookup the first record less than or equal to [bno, len, owner, offset]
45 * in the btree given by cur.
47 int
48 xfs_rmap_lookup_le(
49 struct xfs_btree_cur *cur,
50 xfs_agblock_t bno,
51 xfs_extlen_t len,
52 uint64_t owner,
53 uint64_t offset,
54 unsigned int flags,
55 int *stat)
57 cur->bc_rec.r.rm_startblock = bno;
58 cur->bc_rec.r.rm_blockcount = len;
59 cur->bc_rec.r.rm_owner = owner;
60 cur->bc_rec.r.rm_offset = offset;
61 cur->bc_rec.r.rm_flags = flags;
62 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
66 * Lookup the record exactly matching [bno, len, owner, offset]
67 * in the btree given by cur.
69 int
70 xfs_rmap_lookup_eq(
71 struct xfs_btree_cur *cur,
72 xfs_agblock_t bno,
73 xfs_extlen_t len,
74 uint64_t owner,
75 uint64_t offset,
76 unsigned int flags,
77 int *stat)
79 cur->bc_rec.r.rm_startblock = bno;
80 cur->bc_rec.r.rm_blockcount = len;
81 cur->bc_rec.r.rm_owner = owner;
82 cur->bc_rec.r.rm_offset = offset;
83 cur->bc_rec.r.rm_flags = flags;
84 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
88 * Update the record referred to by cur to the value given
89 * by [bno, len, owner, offset].
90 * This either works (return 0) or gets an EFSCORRUPTED error.
92 STATIC int
93 xfs_rmap_update(
94 struct xfs_btree_cur *cur,
95 struct xfs_rmap_irec *irec)
97 union xfs_btree_rec rec;
98 int error;
100 trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
101 irec->rm_startblock, irec->rm_blockcount,
102 irec->rm_owner, irec->rm_offset, irec->rm_flags);
104 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
105 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
106 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
107 rec.rmap.rm_offset = cpu_to_be64(
108 xfs_rmap_irec_offset_pack(irec));
109 error = xfs_btree_update(cur, &rec);
110 if (error)
111 trace_xfs_rmap_update_error(cur->bc_mp,
112 cur->bc_private.a.agno, error, _RET_IP_);
113 return error;
117 xfs_rmap_insert(
118 struct xfs_btree_cur *rcur,
119 xfs_agblock_t agbno,
120 xfs_extlen_t len,
121 uint64_t owner,
122 uint64_t offset,
123 unsigned int flags)
125 int i;
126 int error;
128 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
129 len, owner, offset, flags);
131 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
132 if (error)
133 goto done;
134 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
136 rcur->bc_rec.r.rm_startblock = agbno;
137 rcur->bc_rec.r.rm_blockcount = len;
138 rcur->bc_rec.r.rm_owner = owner;
139 rcur->bc_rec.r.rm_offset = offset;
140 rcur->bc_rec.r.rm_flags = flags;
141 error = xfs_btree_insert(rcur, &i);
142 if (error)
143 goto done;
144 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
145 done:
146 if (error)
147 trace_xfs_rmap_insert_error(rcur->bc_mp,
148 rcur->bc_private.a.agno, error, _RET_IP_);
149 return error;
152 STATIC int
153 xfs_rmap_delete(
154 struct xfs_btree_cur *rcur,
155 xfs_agblock_t agbno,
156 xfs_extlen_t len,
157 uint64_t owner,
158 uint64_t offset,
159 unsigned int flags)
161 int i;
162 int error;
164 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
165 len, owner, offset, flags);
167 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
168 if (error)
169 goto done;
170 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
172 error = xfs_btree_delete(rcur, &i);
173 if (error)
174 goto done;
175 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
176 done:
177 if (error)
178 trace_xfs_rmap_delete_error(rcur->bc_mp,
179 rcur->bc_private.a.agno, error, _RET_IP_);
180 return error;
183 /* Convert an internal btree record to an rmap record. */
185 xfs_rmap_btrec_to_irec(
186 union xfs_btree_rec *rec,
187 struct xfs_rmap_irec *irec)
189 irec->rm_flags = 0;
190 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
191 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
192 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
193 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
194 irec);
198 * Get the data from the pointed-to record.
201 xfs_rmap_get_rec(
202 struct xfs_btree_cur *cur,
203 struct xfs_rmap_irec *irec,
204 int *stat)
206 union xfs_btree_rec *rec;
207 int error;
209 error = xfs_btree_get_rec(cur, &rec, stat);
210 if (error || !*stat)
211 return error;
213 return xfs_rmap_btrec_to_irec(rec, irec);
216 struct xfs_find_left_neighbor_info {
217 struct xfs_rmap_irec high;
218 struct xfs_rmap_irec *irec;
219 int *stat;
222 /* For each rmap given, figure out if it matches the key we want. */
223 STATIC int
224 xfs_rmap_find_left_neighbor_helper(
225 struct xfs_btree_cur *cur,
226 struct xfs_rmap_irec *rec,
227 void *priv)
229 struct xfs_find_left_neighbor_info *info = priv;
231 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
232 cur->bc_private.a.agno, rec->rm_startblock,
233 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
234 rec->rm_flags);
236 if (rec->rm_owner != info->high.rm_owner)
237 return XFS_BTREE_QUERY_RANGE_CONTINUE;
238 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
239 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
240 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
241 return XFS_BTREE_QUERY_RANGE_CONTINUE;
243 *info->irec = *rec;
244 *info->stat = 1;
245 return XFS_BTREE_QUERY_RANGE_ABORT;
249 * Find the record to the left of the given extent, being careful only to
250 * return a match with the same owner and adjacent physical and logical
251 * block ranges.
254 xfs_rmap_find_left_neighbor(
255 struct xfs_btree_cur *cur,
256 xfs_agblock_t bno,
257 uint64_t owner,
258 uint64_t offset,
259 unsigned int flags,
260 struct xfs_rmap_irec *irec,
261 int *stat)
263 struct xfs_find_left_neighbor_info info;
264 int error;
266 *stat = 0;
267 if (bno == 0)
268 return 0;
269 info.high.rm_startblock = bno - 1;
270 info.high.rm_owner = owner;
271 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
272 !(flags & XFS_RMAP_BMBT_BLOCK)) {
273 if (offset == 0)
274 return 0;
275 info.high.rm_offset = offset - 1;
276 } else
277 info.high.rm_offset = 0;
278 info.high.rm_flags = flags;
279 info.high.rm_blockcount = 0;
280 info.irec = irec;
281 info.stat = stat;
283 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
284 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
286 error = xfs_rmap_query_range(cur, &info.high, &info.high,
287 xfs_rmap_find_left_neighbor_helper, &info);
288 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
289 error = 0;
290 if (*stat)
291 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
292 cur->bc_private.a.agno, irec->rm_startblock,
293 irec->rm_blockcount, irec->rm_owner,
294 irec->rm_offset, irec->rm_flags);
295 return error;
298 /* For each rmap given, figure out if it matches the key we want. */
299 STATIC int
300 xfs_rmap_lookup_le_range_helper(
301 struct xfs_btree_cur *cur,
302 struct xfs_rmap_irec *rec,
303 void *priv)
305 struct xfs_find_left_neighbor_info *info = priv;
307 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
308 cur->bc_private.a.agno, rec->rm_startblock,
309 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
310 rec->rm_flags);
312 if (rec->rm_owner != info->high.rm_owner)
313 return XFS_BTREE_QUERY_RANGE_CONTINUE;
314 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
315 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
316 (rec->rm_offset > info->high.rm_offset ||
317 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
318 return XFS_BTREE_QUERY_RANGE_CONTINUE;
320 *info->irec = *rec;
321 *info->stat = 1;
322 return XFS_BTREE_QUERY_RANGE_ABORT;
326 * Find the record to the left of the given extent, being careful only to
327 * return a match with the same owner and overlapping physical and logical
328 * block ranges. This is the overlapping-interval version of
329 * xfs_rmap_lookup_le.
332 xfs_rmap_lookup_le_range(
333 struct xfs_btree_cur *cur,
334 xfs_agblock_t bno,
335 uint64_t owner,
336 uint64_t offset,
337 unsigned int flags,
338 struct xfs_rmap_irec *irec,
339 int *stat)
341 struct xfs_find_left_neighbor_info info;
342 int error;
344 info.high.rm_startblock = bno;
345 info.high.rm_owner = owner;
346 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
347 info.high.rm_offset = offset;
348 else
349 info.high.rm_offset = 0;
350 info.high.rm_flags = flags;
351 info.high.rm_blockcount = 0;
352 *stat = 0;
353 info.irec = irec;
354 info.stat = stat;
356 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
357 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
358 error = xfs_rmap_query_range(cur, &info.high, &info.high,
359 xfs_rmap_lookup_le_range_helper, &info);
360 if (error == XFS_BTREE_QUERY_RANGE_ABORT)
361 error = 0;
362 if (*stat)
363 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
364 cur->bc_private.a.agno, irec->rm_startblock,
365 irec->rm_blockcount, irec->rm_owner,
366 irec->rm_offset, irec->rm_flags);
367 return error;
371 * Perform all the relevant owner checks for a removal op. If we're doing an
372 * unknown-owner removal then we have no owner information to check.
374 static int
375 xfs_rmap_free_check_owner(
376 struct xfs_mount *mp,
377 uint64_t ltoff,
378 struct xfs_rmap_irec *rec,
379 xfs_fsblock_t bno,
380 xfs_filblks_t len,
381 uint64_t owner,
382 uint64_t offset,
383 unsigned int flags)
385 int error = 0;
387 if (owner == XFS_RMAP_OWN_UNKNOWN)
388 return 0;
390 /* Make sure the unwritten flag matches. */
391 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
392 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
394 /* Make sure the owner matches what we expect to find in the tree. */
395 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
397 /* Check the offset, if necessary. */
398 if (XFS_RMAP_NON_INODE_OWNER(owner))
399 goto out;
401 if (flags & XFS_RMAP_BMBT_BLOCK) {
402 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
403 out);
404 } else {
405 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
406 XFS_WANT_CORRUPTED_GOTO(mp,
407 ltoff + rec->rm_blockcount >= offset + len,
408 out);
411 out:
412 return error;
416 * Find the extent in the rmap btree and remove it.
418 * The record we find should always be an exact match for the extent that we're
419 * looking for, since we insert them into the btree without modification.
421 * Special Case #1: when growing the filesystem, we "free" an extent when
422 * growing the last AG. This extent is new space and so it is not tracked as
423 * used space in the btree. The growfs code will pass in an owner of
424 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
425 * extent. We verify that - the extent lookup result in a record that does not
426 * overlap.
428 * Special Case #2: EFIs do not record the owner of the extent, so when
429 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
430 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
431 * corruption checks during log recovery.
433 STATIC int
434 xfs_rmap_unmap(
435 struct xfs_btree_cur *cur,
436 xfs_agblock_t bno,
437 xfs_extlen_t len,
438 bool unwritten,
439 struct xfs_owner_info *oinfo)
441 struct xfs_mount *mp = cur->bc_mp;
442 struct xfs_rmap_irec ltrec;
443 uint64_t ltoff;
444 int error = 0;
445 int i;
446 uint64_t owner;
447 uint64_t offset;
448 unsigned int flags;
449 bool ignore_off;
451 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
452 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
453 (flags & XFS_RMAP_BMBT_BLOCK);
454 if (unwritten)
455 flags |= XFS_RMAP_UNWRITTEN;
456 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
457 unwritten, oinfo);
460 * We should always have a left record because there's a static record
461 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
462 * will not ever be removed from the tree.
464 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
465 if (error)
466 goto out_error;
467 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
469 error = xfs_rmap_get_rec(cur, &ltrec, &i);
470 if (error)
471 goto out_error;
472 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
473 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
474 cur->bc_private.a.agno, ltrec.rm_startblock,
475 ltrec.rm_blockcount, ltrec.rm_owner,
476 ltrec.rm_offset, ltrec.rm_flags);
477 ltoff = ltrec.rm_offset;
480 * For growfs, the incoming extent must be beyond the left record we
481 * just found as it is new space and won't be used by anyone. This is
482 * just a corruption check as we don't actually do anything with this
483 * extent. Note that we need to use >= instead of > because it might
484 * be the case that the "left" extent goes all the way to EOFS.
486 if (owner == XFS_RMAP_OWN_NULL) {
487 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
488 ltrec.rm_blockcount, out_error);
489 goto out_done;
493 * If we're doing an unknown-owner removal for EFI recovery, we expect
494 * to find the full range in the rmapbt or nothing at all. If we
495 * don't find any rmaps overlapping either end of the range, we're
496 * done. Hopefully this means that the EFI creator already queued
497 * (and finished) a RUI to remove the rmap.
499 if (owner == XFS_RMAP_OWN_UNKNOWN &&
500 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
501 struct xfs_rmap_irec rtrec;
503 error = xfs_btree_increment(cur, 0, &i);
504 if (error)
505 goto out_error;
506 if (i == 0)
507 goto out_done;
508 error = xfs_rmap_get_rec(cur, &rtrec, &i);
509 if (error)
510 goto out_error;
511 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
512 if (rtrec.rm_startblock >= bno + len)
513 goto out_done;
516 /* Make sure the extent we found covers the entire freeing range. */
517 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
518 ltrec.rm_startblock + ltrec.rm_blockcount >=
519 bno + len, out_error);
521 /* Check owner information. */
522 error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, bno, len, owner,
523 offset, flags);
524 if (error)
525 goto out_error;
527 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
528 /* exact match, simply remove the record from rmap tree */
529 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
530 ltrec.rm_startblock, ltrec.rm_blockcount,
531 ltrec.rm_owner, ltrec.rm_offset,
532 ltrec.rm_flags);
533 error = xfs_btree_delete(cur, &i);
534 if (error)
535 goto out_error;
536 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
537 } else if (ltrec.rm_startblock == bno) {
539 * overlap left hand side of extent: move the start, trim the
540 * length and update the current record.
542 * ltbno ltlen
543 * Orig: |oooooooooooooooooooo|
544 * Freeing: |fffffffff|
545 * Result: |rrrrrrrrrr|
546 * bno len
548 ltrec.rm_startblock += len;
549 ltrec.rm_blockcount -= len;
550 if (!ignore_off)
551 ltrec.rm_offset += len;
552 error = xfs_rmap_update(cur, &ltrec);
553 if (error)
554 goto out_error;
555 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
557 * overlap right hand side of extent: trim the length and update
558 * the current record.
560 * ltbno ltlen
561 * Orig: |oooooooooooooooooooo|
562 * Freeing: |fffffffff|
563 * Result: |rrrrrrrrrr|
564 * bno len
566 ltrec.rm_blockcount -= len;
567 error = xfs_rmap_update(cur, &ltrec);
568 if (error)
569 goto out_error;
570 } else {
573 * overlap middle of extent: trim the length of the existing
574 * record to the length of the new left-extent size, increment
575 * the insertion position so we can insert a new record
576 * containing the remaining right-extent space.
578 * ltbno ltlen
579 * Orig: |oooooooooooooooooooo|
580 * Freeing: |fffffffff|
581 * Result: |rrrrr| |rrrr|
582 * bno len
584 xfs_extlen_t orig_len = ltrec.rm_blockcount;
586 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
587 error = xfs_rmap_update(cur, &ltrec);
588 if (error)
589 goto out_error;
591 error = xfs_btree_increment(cur, 0, &i);
592 if (error)
593 goto out_error;
595 cur->bc_rec.r.rm_startblock = bno + len;
596 cur->bc_rec.r.rm_blockcount = orig_len - len -
597 ltrec.rm_blockcount;
598 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
599 if (ignore_off)
600 cur->bc_rec.r.rm_offset = 0;
601 else
602 cur->bc_rec.r.rm_offset = offset + len;
603 cur->bc_rec.r.rm_flags = flags;
604 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
605 cur->bc_rec.r.rm_startblock,
606 cur->bc_rec.r.rm_blockcount,
607 cur->bc_rec.r.rm_owner,
608 cur->bc_rec.r.rm_offset,
609 cur->bc_rec.r.rm_flags);
610 error = xfs_btree_insert(cur, &i);
611 if (error)
612 goto out_error;
615 out_done:
616 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
617 unwritten, oinfo);
618 out_error:
619 if (error)
620 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
621 error, _RET_IP_);
622 return error;
626 * Remove a reference to an extent in the rmap btree.
629 xfs_rmap_free(
630 struct xfs_trans *tp,
631 struct xfs_buf *agbp,
632 xfs_agnumber_t agno,
633 xfs_agblock_t bno,
634 xfs_extlen_t len,
635 struct xfs_owner_info *oinfo)
637 struct xfs_mount *mp = tp->t_mountp;
638 struct xfs_btree_cur *cur;
639 int error;
641 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
642 return 0;
644 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
646 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
647 if (error)
648 goto out_error;
650 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
651 return 0;
653 out_error:
654 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
655 return error;
659 * A mergeable rmap must have the same owner and the same values for
660 * the unwritten, attr_fork, and bmbt flags. The startblock and
661 * offset are checked separately.
663 static bool
664 xfs_rmap_is_mergeable(
665 struct xfs_rmap_irec *irec,
666 uint64_t owner,
667 unsigned int flags)
669 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
670 return false;
671 if (irec->rm_owner != owner)
672 return false;
673 if ((flags & XFS_RMAP_UNWRITTEN) ^
674 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
675 return false;
676 if ((flags & XFS_RMAP_ATTR_FORK) ^
677 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
678 return false;
679 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
680 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
681 return false;
682 return true;
686 * When we allocate a new block, the first thing we do is add a reference to
687 * the extent in the rmap btree. This takes the form of a [agbno, length,
688 * owner, offset] record. Flags are encoded in the high bits of the offset
689 * field.
691 STATIC int
692 xfs_rmap_map(
693 struct xfs_btree_cur *cur,
694 xfs_agblock_t bno,
695 xfs_extlen_t len,
696 bool unwritten,
697 struct xfs_owner_info *oinfo)
699 struct xfs_mount *mp = cur->bc_mp;
700 struct xfs_rmap_irec ltrec;
701 struct xfs_rmap_irec gtrec;
702 int have_gt;
703 int have_lt;
704 int error = 0;
705 int i;
706 uint64_t owner;
707 uint64_t offset;
708 unsigned int flags = 0;
709 bool ignore_off;
711 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
712 ASSERT(owner != 0);
713 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
714 (flags & XFS_RMAP_BMBT_BLOCK);
715 if (unwritten)
716 flags |= XFS_RMAP_UNWRITTEN;
717 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
718 unwritten, oinfo);
719 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
722 * For the initial lookup, look for an exact match or the left-adjacent
723 * record for our insertion point. This will also give us the record for
724 * start block contiguity tests.
726 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
727 &have_lt);
728 if (error)
729 goto out_error;
730 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
732 error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
733 if (error)
734 goto out_error;
735 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
736 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
737 cur->bc_private.a.agno, ltrec.rm_startblock,
738 ltrec.rm_blockcount, ltrec.rm_owner,
739 ltrec.rm_offset, ltrec.rm_flags);
741 if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
742 have_lt = 0;
744 XFS_WANT_CORRUPTED_GOTO(mp,
745 have_lt == 0 ||
746 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
749 * Increment the cursor to see if we have a right-adjacent record to our
750 * insertion point. This will give us the record for end block
751 * contiguity tests.
753 error = xfs_btree_increment(cur, 0, &have_gt);
754 if (error)
755 goto out_error;
756 if (have_gt) {
757 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
758 if (error)
759 goto out_error;
760 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
761 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
762 out_error);
763 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
764 cur->bc_private.a.agno, gtrec.rm_startblock,
765 gtrec.rm_blockcount, gtrec.rm_owner,
766 gtrec.rm_offset, gtrec.rm_flags);
767 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
768 have_gt = 0;
772 * Note: cursor currently points one record to the right of ltrec, even
773 * if there is no record in the tree to the right.
775 if (have_lt &&
776 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
777 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
779 * left edge contiguous, merge into left record.
781 * ltbno ltlen
782 * orig: |ooooooooo|
783 * adding: |aaaaaaaaa|
784 * result: |rrrrrrrrrrrrrrrrrrr|
785 * bno len
787 ltrec.rm_blockcount += len;
788 if (have_gt &&
789 bno + len == gtrec.rm_startblock &&
790 (ignore_off || offset + len == gtrec.rm_offset) &&
791 (unsigned long)ltrec.rm_blockcount + len +
792 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
794 * right edge also contiguous, delete right record
795 * and merge into left record.
797 * ltbno ltlen gtbno gtlen
798 * orig: |ooooooooo| |ooooooooo|
799 * adding: |aaaaaaaaa|
800 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
802 ltrec.rm_blockcount += gtrec.rm_blockcount;
803 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
804 gtrec.rm_startblock,
805 gtrec.rm_blockcount,
806 gtrec.rm_owner,
807 gtrec.rm_offset,
808 gtrec.rm_flags);
809 error = xfs_btree_delete(cur, &i);
810 if (error)
811 goto out_error;
812 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
815 /* point the cursor back to the left record and update */
816 error = xfs_btree_decrement(cur, 0, &have_gt);
817 if (error)
818 goto out_error;
819 error = xfs_rmap_update(cur, &ltrec);
820 if (error)
821 goto out_error;
822 } else if (have_gt &&
823 bno + len == gtrec.rm_startblock &&
824 (ignore_off || offset + len == gtrec.rm_offset)) {
826 * right edge contiguous, merge into right record.
828 * gtbno gtlen
829 * Orig: |ooooooooo|
830 * adding: |aaaaaaaaa|
831 * Result: |rrrrrrrrrrrrrrrrrrr|
832 * bno len
834 gtrec.rm_startblock = bno;
835 gtrec.rm_blockcount += len;
836 if (!ignore_off)
837 gtrec.rm_offset = offset;
838 error = xfs_rmap_update(cur, &gtrec);
839 if (error)
840 goto out_error;
841 } else {
843 * no contiguous edge with identical owner, insert
844 * new record at current cursor position.
846 cur->bc_rec.r.rm_startblock = bno;
847 cur->bc_rec.r.rm_blockcount = len;
848 cur->bc_rec.r.rm_owner = owner;
849 cur->bc_rec.r.rm_offset = offset;
850 cur->bc_rec.r.rm_flags = flags;
851 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
852 owner, offset, flags);
853 error = xfs_btree_insert(cur, &i);
854 if (error)
855 goto out_error;
856 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
859 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
860 unwritten, oinfo);
861 out_error:
862 if (error)
863 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
864 error, _RET_IP_);
865 return error;
869 * Add a reference to an extent in the rmap btree.
872 xfs_rmap_alloc(
873 struct xfs_trans *tp,
874 struct xfs_buf *agbp,
875 xfs_agnumber_t agno,
876 xfs_agblock_t bno,
877 xfs_extlen_t len,
878 struct xfs_owner_info *oinfo)
880 struct xfs_mount *mp = tp->t_mountp;
881 struct xfs_btree_cur *cur;
882 int error;
884 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
885 return 0;
887 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
888 error = xfs_rmap_map(cur, bno, len, false, oinfo);
889 if (error)
890 goto out_error;
892 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
893 return 0;
895 out_error:
896 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
897 return error;
900 #define RMAP_LEFT_CONTIG (1 << 0)
901 #define RMAP_RIGHT_CONTIG (1 << 1)
902 #define RMAP_LEFT_FILLING (1 << 2)
903 #define RMAP_RIGHT_FILLING (1 << 3)
904 #define RMAP_LEFT_VALID (1 << 6)
905 #define RMAP_RIGHT_VALID (1 << 7)
907 #define LEFT r[0]
908 #define RIGHT r[1]
909 #define PREV r[2]
910 #define NEW r[3]
913 * Convert an unwritten extent to a real extent or vice versa.
914 * Does not handle overlapping extents.
916 STATIC int
917 xfs_rmap_convert(
918 struct xfs_btree_cur *cur,
919 xfs_agblock_t bno,
920 xfs_extlen_t len,
921 bool unwritten,
922 struct xfs_owner_info *oinfo)
924 struct xfs_mount *mp = cur->bc_mp;
925 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
926 /* left is 0, right is 1, prev is 2 */
927 /* new is 3 */
928 uint64_t owner;
929 uint64_t offset;
930 uint64_t new_endoff;
931 unsigned int oldext;
932 unsigned int newext;
933 unsigned int flags = 0;
934 int i;
935 int state = 0;
936 int error;
938 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
939 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
940 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
941 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
942 new_endoff = offset + len;
943 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
944 unwritten, oinfo);
947 * For the initial lookup, look for an exact match or the left-adjacent
948 * record for our insertion point. This will also give us the record for
949 * start block contiguity tests.
951 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
952 if (error)
953 goto done;
954 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
956 error = xfs_rmap_get_rec(cur, &PREV, &i);
957 if (error)
958 goto done;
959 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
960 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
961 cur->bc_private.a.agno, PREV.rm_startblock,
962 PREV.rm_blockcount, PREV.rm_owner,
963 PREV.rm_offset, PREV.rm_flags);
965 ASSERT(PREV.rm_offset <= offset);
966 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
967 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
968 newext = ~oldext & XFS_RMAP_UNWRITTEN;
971 * Set flags determining what part of the previous oldext allocation
972 * extent is being replaced by a newext allocation.
974 if (PREV.rm_offset == offset)
975 state |= RMAP_LEFT_FILLING;
976 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
977 state |= RMAP_RIGHT_FILLING;
980 * Decrement the cursor to see if we have a left-adjacent record to our
981 * insertion point. This will give us the record for end block
982 * contiguity tests.
984 error = xfs_btree_decrement(cur, 0, &i);
985 if (error)
986 goto done;
987 if (i) {
988 state |= RMAP_LEFT_VALID;
989 error = xfs_rmap_get_rec(cur, &LEFT, &i);
990 if (error)
991 goto done;
992 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
993 XFS_WANT_CORRUPTED_GOTO(mp,
994 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
995 done);
996 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
997 cur->bc_private.a.agno, LEFT.rm_startblock,
998 LEFT.rm_blockcount, LEFT.rm_owner,
999 LEFT.rm_offset, LEFT.rm_flags);
1000 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1001 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1002 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1003 state |= RMAP_LEFT_CONTIG;
1007 * Increment the cursor to see if we have a right-adjacent record to our
1008 * insertion point. This will give us the record for end block
1009 * contiguity tests.
1011 error = xfs_btree_increment(cur, 0, &i);
1012 if (error)
1013 goto done;
1014 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1015 error = xfs_btree_increment(cur, 0, &i);
1016 if (error)
1017 goto done;
1018 if (i) {
1019 state |= RMAP_RIGHT_VALID;
1020 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1021 if (error)
1022 goto done;
1023 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1024 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1025 done);
1026 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1027 cur->bc_private.a.agno, RIGHT.rm_startblock,
1028 RIGHT.rm_blockcount, RIGHT.rm_owner,
1029 RIGHT.rm_offset, RIGHT.rm_flags);
1030 if (bno + len == RIGHT.rm_startblock &&
1031 offset + len == RIGHT.rm_offset &&
1032 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1033 state |= RMAP_RIGHT_CONTIG;
1036 /* check that left + prev + right is not too long */
1037 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1038 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1039 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1040 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1041 (unsigned long)LEFT.rm_blockcount + len +
1042 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1043 state &= ~RMAP_RIGHT_CONTIG;
1045 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1046 _RET_IP_);
1048 /* reset the cursor back to PREV */
1049 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1050 if (error)
1051 goto done;
1052 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1055 * Switch out based on the FILLING and CONTIG state bits.
1057 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1058 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1059 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1060 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1062 * Setting all of a previous oldext extent to newext.
1063 * The left and right neighbors are both contiguous with new.
1065 error = xfs_btree_increment(cur, 0, &i);
1066 if (error)
1067 goto done;
1068 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1069 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1070 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1071 RIGHT.rm_owner, RIGHT.rm_offset,
1072 RIGHT.rm_flags);
1073 error = xfs_btree_delete(cur, &i);
1074 if (error)
1075 goto done;
1076 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1077 error = xfs_btree_decrement(cur, 0, &i);
1078 if (error)
1079 goto done;
1080 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1081 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1082 PREV.rm_startblock, PREV.rm_blockcount,
1083 PREV.rm_owner, PREV.rm_offset,
1084 PREV.rm_flags);
1085 error = xfs_btree_delete(cur, &i);
1086 if (error)
1087 goto done;
1088 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1089 error = xfs_btree_decrement(cur, 0, &i);
1090 if (error)
1091 goto done;
1092 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1093 NEW = LEFT;
1094 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1095 error = xfs_rmap_update(cur, &NEW);
1096 if (error)
1097 goto done;
1098 break;
1100 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1102 * Setting all of a previous oldext extent to newext.
1103 * The left neighbor is contiguous, the right is not.
1105 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1106 PREV.rm_startblock, PREV.rm_blockcount,
1107 PREV.rm_owner, PREV.rm_offset,
1108 PREV.rm_flags);
1109 error = xfs_btree_delete(cur, &i);
1110 if (error)
1111 goto done;
1112 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1113 error = xfs_btree_decrement(cur, 0, &i);
1114 if (error)
1115 goto done;
1116 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1117 NEW = LEFT;
1118 NEW.rm_blockcount += PREV.rm_blockcount;
1119 error = xfs_rmap_update(cur, &NEW);
1120 if (error)
1121 goto done;
1122 break;
1124 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1126 * Setting all of a previous oldext extent to newext.
1127 * The right neighbor is contiguous, the left is not.
1129 error = xfs_btree_increment(cur, 0, &i);
1130 if (error)
1131 goto done;
1132 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1133 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1134 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1135 RIGHT.rm_owner, RIGHT.rm_offset,
1136 RIGHT.rm_flags);
1137 error = xfs_btree_delete(cur, &i);
1138 if (error)
1139 goto done;
1140 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1141 error = xfs_btree_decrement(cur, 0, &i);
1142 if (error)
1143 goto done;
1144 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1145 NEW = PREV;
1146 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1147 NEW.rm_flags = newext;
1148 error = xfs_rmap_update(cur, &NEW);
1149 if (error)
1150 goto done;
1151 break;
1153 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1155 * Setting all of a previous oldext extent to newext.
1156 * Neither the left nor right neighbors are contiguous with
1157 * the new one.
1159 NEW = PREV;
1160 NEW.rm_flags = newext;
1161 error = xfs_rmap_update(cur, &NEW);
1162 if (error)
1163 goto done;
1164 break;
1166 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1168 * Setting the first part of a previous oldext extent to newext.
1169 * The left neighbor is contiguous.
1171 NEW = PREV;
1172 NEW.rm_offset += len;
1173 NEW.rm_startblock += len;
1174 NEW.rm_blockcount -= len;
1175 error = xfs_rmap_update(cur, &NEW);
1176 if (error)
1177 goto done;
1178 error = xfs_btree_decrement(cur, 0, &i);
1179 if (error)
1180 goto done;
1181 NEW = LEFT;
1182 NEW.rm_blockcount += len;
1183 error = xfs_rmap_update(cur, &NEW);
1184 if (error)
1185 goto done;
1186 break;
1188 case RMAP_LEFT_FILLING:
1190 * Setting the first part of a previous oldext extent to newext.
1191 * The left neighbor is not contiguous.
1193 NEW = PREV;
1194 NEW.rm_startblock += len;
1195 NEW.rm_offset += len;
1196 NEW.rm_blockcount -= len;
1197 error = xfs_rmap_update(cur, &NEW);
1198 if (error)
1199 goto done;
1200 NEW.rm_startblock = bno;
1201 NEW.rm_owner = owner;
1202 NEW.rm_offset = offset;
1203 NEW.rm_blockcount = len;
1204 NEW.rm_flags = newext;
1205 cur->bc_rec.r = NEW;
1206 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1207 len, owner, offset, newext);
1208 error = xfs_btree_insert(cur, &i);
1209 if (error)
1210 goto done;
1211 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1212 break;
1214 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1216 * Setting the last part of a previous oldext extent to newext.
1217 * The right neighbor is contiguous with the new allocation.
1219 NEW = PREV;
1220 NEW.rm_blockcount -= len;
1221 error = xfs_rmap_update(cur, &NEW);
1222 if (error)
1223 goto done;
1224 error = xfs_btree_increment(cur, 0, &i);
1225 if (error)
1226 goto done;
1227 NEW = RIGHT;
1228 NEW.rm_offset = offset;
1229 NEW.rm_startblock = bno;
1230 NEW.rm_blockcount += len;
1231 error = xfs_rmap_update(cur, &NEW);
1232 if (error)
1233 goto done;
1234 break;
1236 case RMAP_RIGHT_FILLING:
1238 * Setting the last part of a previous oldext extent to newext.
1239 * The right neighbor is not contiguous.
1241 NEW = PREV;
1242 NEW.rm_blockcount -= len;
1243 error = xfs_rmap_update(cur, &NEW);
1244 if (error)
1245 goto done;
1246 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1247 oldext, &i);
1248 if (error)
1249 goto done;
1250 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1251 NEW.rm_startblock = bno;
1252 NEW.rm_owner = owner;
1253 NEW.rm_offset = offset;
1254 NEW.rm_blockcount = len;
1255 NEW.rm_flags = newext;
1256 cur->bc_rec.r = NEW;
1257 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1258 len, owner, offset, newext);
1259 error = xfs_btree_insert(cur, &i);
1260 if (error)
1261 goto done;
1262 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1263 break;
1265 case 0:
1267 * Setting the middle part of a previous oldext extent to
1268 * newext. Contiguity is impossible here.
1269 * One extent becomes three extents.
1271 /* new right extent - oldext */
1272 NEW.rm_startblock = bno + len;
1273 NEW.rm_owner = owner;
1274 NEW.rm_offset = new_endoff;
1275 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1276 new_endoff;
1277 NEW.rm_flags = PREV.rm_flags;
1278 error = xfs_rmap_update(cur, &NEW);
1279 if (error)
1280 goto done;
1281 /* new left extent - oldext */
1282 NEW = PREV;
1283 NEW.rm_blockcount = offset - PREV.rm_offset;
1284 cur->bc_rec.r = NEW;
1285 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1286 NEW.rm_startblock, NEW.rm_blockcount,
1287 NEW.rm_owner, NEW.rm_offset,
1288 NEW.rm_flags);
1289 error = xfs_btree_insert(cur, &i);
1290 if (error)
1291 goto done;
1292 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1294 * Reset the cursor to the position of the new extent
1295 * we are about to insert as we can't trust it after
1296 * the previous insert.
1298 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1299 oldext, &i);
1300 if (error)
1301 goto done;
1302 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1303 /* new middle extent - newext */
1304 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1305 cur->bc_rec.r.rm_flags |= newext;
1306 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1307 owner, offset, newext);
1308 error = xfs_btree_insert(cur, &i);
1309 if (error)
1310 goto done;
1311 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1312 break;
1314 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1315 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1316 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1317 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1318 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1319 case RMAP_LEFT_CONTIG:
1320 case RMAP_RIGHT_CONTIG:
1322 * These cases are all impossible.
1324 ASSERT(0);
1327 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1328 unwritten, oinfo);
1329 done:
1330 if (error)
1331 trace_xfs_rmap_convert_error(cur->bc_mp,
1332 cur->bc_private.a.agno, error, _RET_IP_);
1333 return error;
1337 * Convert an unwritten extent to a real extent or vice versa. If there is no
1338 * possibility of overlapping extents, delegate to the simpler convert
1339 * function.
1341 STATIC int
1342 xfs_rmap_convert_shared(
1343 struct xfs_btree_cur *cur,
1344 xfs_agblock_t bno,
1345 xfs_extlen_t len,
1346 bool unwritten,
1347 struct xfs_owner_info *oinfo)
1349 struct xfs_mount *mp = cur->bc_mp;
1350 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1351 /* left is 0, right is 1, prev is 2 */
1352 /* new is 3 */
1353 uint64_t owner;
1354 uint64_t offset;
1355 uint64_t new_endoff;
1356 unsigned int oldext;
1357 unsigned int newext;
1358 unsigned int flags = 0;
1359 int i;
1360 int state = 0;
1361 int error;
1363 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1364 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1365 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1366 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1367 new_endoff = offset + len;
1368 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1369 unwritten, oinfo);
1372 * For the initial lookup, look for and exact match or the left-adjacent
1373 * record for our insertion point. This will also give us the record for
1374 * start block contiguity tests.
1376 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1377 &PREV, &i);
1378 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1380 ASSERT(PREV.rm_offset <= offset);
1381 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1382 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1383 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1386 * Set flags determining what part of the previous oldext allocation
1387 * extent is being replaced by a newext allocation.
1389 if (PREV.rm_offset == offset)
1390 state |= RMAP_LEFT_FILLING;
1391 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1392 state |= RMAP_RIGHT_FILLING;
1394 /* Is there a left record that abuts our range? */
1395 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1396 &LEFT, &i);
1397 if (error)
1398 goto done;
1399 if (i) {
1400 state |= RMAP_LEFT_VALID;
1401 XFS_WANT_CORRUPTED_GOTO(mp,
1402 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1403 done);
1404 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1405 state |= RMAP_LEFT_CONTIG;
1408 /* Is there a right record that abuts our range? */
1409 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1410 newext, &i);
1411 if (error)
1412 goto done;
1413 if (i) {
1414 state |= RMAP_RIGHT_VALID;
1415 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1416 if (error)
1417 goto done;
1418 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1419 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1420 done);
1421 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1422 cur->bc_private.a.agno, RIGHT.rm_startblock,
1423 RIGHT.rm_blockcount, RIGHT.rm_owner,
1424 RIGHT.rm_offset, RIGHT.rm_flags);
1425 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1426 state |= RMAP_RIGHT_CONTIG;
1429 /* check that left + prev + right is not too long */
1430 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1431 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1432 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1433 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1434 (unsigned long)LEFT.rm_blockcount + len +
1435 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1436 state &= ~RMAP_RIGHT_CONTIG;
1438 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1439 _RET_IP_);
1441 * Switch out based on the FILLING and CONTIG state bits.
1443 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1444 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1445 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1446 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1448 * Setting all of a previous oldext extent to newext.
1449 * The left and right neighbors are both contiguous with new.
1451 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1452 RIGHT.rm_blockcount, RIGHT.rm_owner,
1453 RIGHT.rm_offset, RIGHT.rm_flags);
1454 if (error)
1455 goto done;
1456 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1457 PREV.rm_blockcount, PREV.rm_owner,
1458 PREV.rm_offset, PREV.rm_flags);
1459 if (error)
1460 goto done;
1461 NEW = LEFT;
1462 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1463 NEW.rm_blockcount, NEW.rm_owner,
1464 NEW.rm_offset, NEW.rm_flags, &i);
1465 if (error)
1466 goto done;
1467 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1468 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1469 error = xfs_rmap_update(cur, &NEW);
1470 if (error)
1471 goto done;
1472 break;
1474 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1476 * Setting all of a previous oldext extent to newext.
1477 * The left neighbor is contiguous, the right is not.
1479 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1480 PREV.rm_blockcount, PREV.rm_owner,
1481 PREV.rm_offset, PREV.rm_flags);
1482 if (error)
1483 goto done;
1484 NEW = LEFT;
1485 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1486 NEW.rm_blockcount, NEW.rm_owner,
1487 NEW.rm_offset, NEW.rm_flags, &i);
1488 if (error)
1489 goto done;
1490 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1491 NEW.rm_blockcount += PREV.rm_blockcount;
1492 error = xfs_rmap_update(cur, &NEW);
1493 if (error)
1494 goto done;
1495 break;
1497 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1499 * Setting all of a previous oldext extent to newext.
1500 * The right neighbor is contiguous, the left is not.
1502 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1503 RIGHT.rm_blockcount, RIGHT.rm_owner,
1504 RIGHT.rm_offset, RIGHT.rm_flags);
1505 if (error)
1506 goto done;
1507 NEW = PREV;
1508 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1509 NEW.rm_blockcount, NEW.rm_owner,
1510 NEW.rm_offset, NEW.rm_flags, &i);
1511 if (error)
1512 goto done;
1513 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1514 NEW.rm_blockcount += RIGHT.rm_blockcount;
1515 NEW.rm_flags = RIGHT.rm_flags;
1516 error = xfs_rmap_update(cur, &NEW);
1517 if (error)
1518 goto done;
1519 break;
1521 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1523 * Setting all of a previous oldext extent to newext.
1524 * Neither the left nor right neighbors are contiguous with
1525 * the new one.
1527 NEW = PREV;
1528 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1529 NEW.rm_blockcount, NEW.rm_owner,
1530 NEW.rm_offset, NEW.rm_flags, &i);
1531 if (error)
1532 goto done;
1533 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1534 NEW.rm_flags = newext;
1535 error = xfs_rmap_update(cur, &NEW);
1536 if (error)
1537 goto done;
1538 break;
1540 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1542 * Setting the first part of a previous oldext extent to newext.
1543 * The left neighbor is contiguous.
1545 NEW = PREV;
1546 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1547 NEW.rm_blockcount, NEW.rm_owner,
1548 NEW.rm_offset, NEW.rm_flags);
1549 if (error)
1550 goto done;
1551 NEW.rm_offset += len;
1552 NEW.rm_startblock += len;
1553 NEW.rm_blockcount -= len;
1554 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1555 NEW.rm_blockcount, NEW.rm_owner,
1556 NEW.rm_offset, NEW.rm_flags);
1557 if (error)
1558 goto done;
1559 NEW = LEFT;
1560 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1561 NEW.rm_blockcount, NEW.rm_owner,
1562 NEW.rm_offset, NEW.rm_flags, &i);
1563 if (error)
1564 goto done;
1565 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1566 NEW.rm_blockcount += len;
1567 error = xfs_rmap_update(cur, &NEW);
1568 if (error)
1569 goto done;
1570 break;
1572 case RMAP_LEFT_FILLING:
1574 * Setting the first part of a previous oldext extent to newext.
1575 * The left neighbor is not contiguous.
1577 NEW = PREV;
1578 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1579 NEW.rm_blockcount, NEW.rm_owner,
1580 NEW.rm_offset, NEW.rm_flags);
1581 if (error)
1582 goto done;
1583 NEW.rm_offset += len;
1584 NEW.rm_startblock += len;
1585 NEW.rm_blockcount -= len;
1586 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1587 NEW.rm_blockcount, NEW.rm_owner,
1588 NEW.rm_offset, NEW.rm_flags);
1589 if (error)
1590 goto done;
1591 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1592 if (error)
1593 goto done;
1594 break;
1596 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1598 * Setting the last part of a previous oldext extent to newext.
1599 * The right neighbor is contiguous with the new allocation.
1601 NEW = PREV;
1602 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1603 NEW.rm_blockcount, NEW.rm_owner,
1604 NEW.rm_offset, NEW.rm_flags, &i);
1605 if (error)
1606 goto done;
1607 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1608 NEW.rm_blockcount = offset - NEW.rm_offset;
1609 error = xfs_rmap_update(cur, &NEW);
1610 if (error)
1611 goto done;
1612 NEW = RIGHT;
1613 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1614 NEW.rm_blockcount, NEW.rm_owner,
1615 NEW.rm_offset, NEW.rm_flags);
1616 if (error)
1617 goto done;
1618 NEW.rm_offset = offset;
1619 NEW.rm_startblock = bno;
1620 NEW.rm_blockcount += len;
1621 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1622 NEW.rm_blockcount, NEW.rm_owner,
1623 NEW.rm_offset, NEW.rm_flags);
1624 if (error)
1625 goto done;
1626 break;
1628 case RMAP_RIGHT_FILLING:
1630 * Setting the last part of a previous oldext extent to newext.
1631 * The right neighbor is not contiguous.
1633 NEW = PREV;
1634 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1635 NEW.rm_blockcount, NEW.rm_owner,
1636 NEW.rm_offset, NEW.rm_flags, &i);
1637 if (error)
1638 goto done;
1639 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1640 NEW.rm_blockcount -= len;
1641 error = xfs_rmap_update(cur, &NEW);
1642 if (error)
1643 goto done;
1644 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1645 if (error)
1646 goto done;
1647 break;
1649 case 0:
1651 * Setting the middle part of a previous oldext extent to
1652 * newext. Contiguity is impossible here.
1653 * One extent becomes three extents.
1655 /* new right extent - oldext */
1656 NEW.rm_startblock = bno + len;
1657 NEW.rm_owner = owner;
1658 NEW.rm_offset = new_endoff;
1659 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1660 new_endoff;
1661 NEW.rm_flags = PREV.rm_flags;
1662 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1663 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1664 NEW.rm_flags);
1665 if (error)
1666 goto done;
1667 /* new left extent - oldext */
1668 NEW = PREV;
1669 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1670 NEW.rm_blockcount, NEW.rm_owner,
1671 NEW.rm_offset, NEW.rm_flags, &i);
1672 if (error)
1673 goto done;
1674 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1675 NEW.rm_blockcount = offset - NEW.rm_offset;
1676 error = xfs_rmap_update(cur, &NEW);
1677 if (error)
1678 goto done;
1679 /* new middle extent - newext */
1680 NEW.rm_startblock = bno;
1681 NEW.rm_blockcount = len;
1682 NEW.rm_owner = owner;
1683 NEW.rm_offset = offset;
1684 NEW.rm_flags = newext;
1685 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1686 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1687 NEW.rm_flags);
1688 if (error)
1689 goto done;
1690 break;
1692 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1693 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1694 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1695 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1696 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1697 case RMAP_LEFT_CONTIG:
1698 case RMAP_RIGHT_CONTIG:
1700 * These cases are all impossible.
1702 ASSERT(0);
1705 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1706 unwritten, oinfo);
1707 done:
1708 if (error)
1709 trace_xfs_rmap_convert_error(cur->bc_mp,
1710 cur->bc_private.a.agno, error, _RET_IP_);
1711 return error;
1714 #undef NEW
1715 #undef LEFT
1716 #undef RIGHT
1717 #undef PREV
1720 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1721 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1722 * that the prev/next records in the btree might belong to another owner.
1723 * Therefore we must use delete+insert to alter any of the key fields.
1725 * For every other situation there can only be one owner for a given extent,
1726 * so we can call the regular _free function.
1728 STATIC int
1729 xfs_rmap_unmap_shared(
1730 struct xfs_btree_cur *cur,
1731 xfs_agblock_t bno,
1732 xfs_extlen_t len,
1733 bool unwritten,
1734 struct xfs_owner_info *oinfo)
1736 struct xfs_mount *mp = cur->bc_mp;
1737 struct xfs_rmap_irec ltrec;
1738 uint64_t ltoff;
1739 int error = 0;
1740 int i;
1741 uint64_t owner;
1742 uint64_t offset;
1743 unsigned int flags;
1745 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1746 if (unwritten)
1747 flags |= XFS_RMAP_UNWRITTEN;
1748 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1749 unwritten, oinfo);
1752 * We should always have a left record because there's a static record
1753 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1754 * will not ever be removed from the tree.
1756 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1757 &ltrec, &i);
1758 if (error)
1759 goto out_error;
1760 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1761 ltoff = ltrec.rm_offset;
1763 /* Make sure the extent we found covers the entire freeing range. */
1764 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1765 ltrec.rm_startblock + ltrec.rm_blockcount >=
1766 bno + len, out_error);
1768 /* Make sure the owner matches what we expect to find in the tree. */
1769 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1771 /* Make sure the unwritten flag matches. */
1772 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1773 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1775 /* Check the offset. */
1776 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1777 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1778 out_error);
1780 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1781 /* Exact match, simply remove the record from rmap tree. */
1782 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1783 ltrec.rm_blockcount, ltrec.rm_owner,
1784 ltrec.rm_offset, ltrec.rm_flags);
1785 if (error)
1786 goto out_error;
1787 } else if (ltrec.rm_startblock == bno) {
1789 * Overlap left hand side of extent: move the start, trim the
1790 * length and update the current record.
1792 * ltbno ltlen
1793 * Orig: |oooooooooooooooooooo|
1794 * Freeing: |fffffffff|
1795 * Result: |rrrrrrrrrr|
1796 * bno len
1799 /* Delete prev rmap. */
1800 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1801 ltrec.rm_blockcount, ltrec.rm_owner,
1802 ltrec.rm_offset, ltrec.rm_flags);
1803 if (error)
1804 goto out_error;
1806 /* Add an rmap at the new offset. */
1807 ltrec.rm_startblock += len;
1808 ltrec.rm_blockcount -= len;
1809 ltrec.rm_offset += len;
1810 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1811 ltrec.rm_blockcount, ltrec.rm_owner,
1812 ltrec.rm_offset, ltrec.rm_flags);
1813 if (error)
1814 goto out_error;
1815 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1817 * Overlap right hand side of extent: trim the length and
1818 * update the current record.
1820 * ltbno ltlen
1821 * Orig: |oooooooooooooooooooo|
1822 * Freeing: |fffffffff|
1823 * Result: |rrrrrrrrrr|
1824 * bno len
1826 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1827 ltrec.rm_blockcount, ltrec.rm_owner,
1828 ltrec.rm_offset, ltrec.rm_flags, &i);
1829 if (error)
1830 goto out_error;
1831 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1832 ltrec.rm_blockcount -= len;
1833 error = xfs_rmap_update(cur, &ltrec);
1834 if (error)
1835 goto out_error;
1836 } else {
1838 * Overlap middle of extent: trim the length of the existing
1839 * record to the length of the new left-extent size, increment
1840 * the insertion position so we can insert a new record
1841 * containing the remaining right-extent space.
1843 * ltbno ltlen
1844 * Orig: |oooooooooooooooooooo|
1845 * Freeing: |fffffffff|
1846 * Result: |rrrrr| |rrrr|
1847 * bno len
1849 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1851 /* Shrink the left side of the rmap */
1852 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1853 ltrec.rm_blockcount, ltrec.rm_owner,
1854 ltrec.rm_offset, ltrec.rm_flags, &i);
1855 if (error)
1856 goto out_error;
1857 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1858 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1859 error = xfs_rmap_update(cur, &ltrec);
1860 if (error)
1861 goto out_error;
1863 /* Add an rmap at the new offset */
1864 error = xfs_rmap_insert(cur, bno + len,
1865 orig_len - len - ltrec.rm_blockcount,
1866 ltrec.rm_owner, offset + len,
1867 ltrec.rm_flags);
1868 if (error)
1869 goto out_error;
1872 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1873 unwritten, oinfo);
1874 out_error:
1875 if (error)
1876 trace_xfs_rmap_unmap_error(cur->bc_mp,
1877 cur->bc_private.a.agno, error, _RET_IP_);
1878 return error;
1882 * Find an extent in the rmap btree and map it. For rmap extent types that
1883 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1884 * that the prev/next records in the btree might belong to another owner.
1885 * Therefore we must use delete+insert to alter any of the key fields.
1887 * For every other situation there can only be one owner for a given extent,
1888 * so we can call the regular _alloc function.
1890 STATIC int
1891 xfs_rmap_map_shared(
1892 struct xfs_btree_cur *cur,
1893 xfs_agblock_t bno,
1894 xfs_extlen_t len,
1895 bool unwritten,
1896 struct xfs_owner_info *oinfo)
1898 struct xfs_mount *mp = cur->bc_mp;
1899 struct xfs_rmap_irec ltrec;
1900 struct xfs_rmap_irec gtrec;
1901 int have_gt;
1902 int have_lt;
1903 int error = 0;
1904 int i;
1905 uint64_t owner;
1906 uint64_t offset;
1907 unsigned int flags = 0;
1909 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1910 if (unwritten)
1911 flags |= XFS_RMAP_UNWRITTEN;
1912 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1913 unwritten, oinfo);
1915 /* Is there a left record that abuts our range? */
1916 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1917 &ltrec, &have_lt);
1918 if (error)
1919 goto out_error;
1920 if (have_lt &&
1921 !xfs_rmap_is_mergeable(&ltrec, owner, flags))
1922 have_lt = 0;
1924 /* Is there a right record that abuts our range? */
1925 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1926 flags, &have_gt);
1927 if (error)
1928 goto out_error;
1929 if (have_gt) {
1930 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
1931 if (error)
1932 goto out_error;
1933 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1934 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1935 cur->bc_private.a.agno, gtrec.rm_startblock,
1936 gtrec.rm_blockcount, gtrec.rm_owner,
1937 gtrec.rm_offset, gtrec.rm_flags);
1939 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
1940 have_gt = 0;
1943 if (have_lt &&
1944 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1945 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1947 * Left edge contiguous, merge into left record.
1949 * ltbno ltlen
1950 * orig: |ooooooooo|
1951 * adding: |aaaaaaaaa|
1952 * result: |rrrrrrrrrrrrrrrrrrr|
1953 * bno len
1955 ltrec.rm_blockcount += len;
1956 if (have_gt &&
1957 bno + len == gtrec.rm_startblock &&
1958 offset + len == gtrec.rm_offset) {
1960 * Right edge also contiguous, delete right record
1961 * and merge into left record.
1963 * ltbno ltlen gtbno gtlen
1964 * orig: |ooooooooo| |ooooooooo|
1965 * adding: |aaaaaaaaa|
1966 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1968 ltrec.rm_blockcount += gtrec.rm_blockcount;
1969 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1970 gtrec.rm_blockcount, gtrec.rm_owner,
1971 gtrec.rm_offset, gtrec.rm_flags);
1972 if (error)
1973 goto out_error;
1976 /* Point the cursor back to the left record and update. */
1977 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1978 ltrec.rm_blockcount, ltrec.rm_owner,
1979 ltrec.rm_offset, ltrec.rm_flags, &i);
1980 if (error)
1981 goto out_error;
1982 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1984 error = xfs_rmap_update(cur, &ltrec);
1985 if (error)
1986 goto out_error;
1987 } else if (have_gt &&
1988 bno + len == gtrec.rm_startblock &&
1989 offset + len == gtrec.rm_offset) {
1991 * Right edge contiguous, merge into right record.
1993 * gtbno gtlen
1994 * Orig: |ooooooooo|
1995 * adding: |aaaaaaaaa|
1996 * Result: |rrrrrrrrrrrrrrrrrrr|
1997 * bno len
1999 /* Delete the old record. */
2000 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2001 gtrec.rm_blockcount, gtrec.rm_owner,
2002 gtrec.rm_offset, gtrec.rm_flags);
2003 if (error)
2004 goto out_error;
2006 /* Move the start and re-add it. */
2007 gtrec.rm_startblock = bno;
2008 gtrec.rm_blockcount += len;
2009 gtrec.rm_offset = offset;
2010 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2011 gtrec.rm_blockcount, gtrec.rm_owner,
2012 gtrec.rm_offset, gtrec.rm_flags);
2013 if (error)
2014 goto out_error;
2015 } else {
2017 * No contiguous edge with identical owner, insert
2018 * new record at current cursor position.
2020 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2021 if (error)
2022 goto out_error;
2025 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2026 unwritten, oinfo);
2027 out_error:
2028 if (error)
2029 trace_xfs_rmap_map_error(cur->bc_mp,
2030 cur->bc_private.a.agno, error, _RET_IP_);
2031 return error;
2034 struct xfs_rmap_query_range_info {
2035 xfs_rmap_query_range_fn fn;
2036 void *priv;
2039 /* Format btree record and pass to our callback. */
2040 STATIC int
2041 xfs_rmap_query_range_helper(
2042 struct xfs_btree_cur *cur,
2043 union xfs_btree_rec *rec,
2044 void *priv)
2046 struct xfs_rmap_query_range_info *query = priv;
2047 struct xfs_rmap_irec irec;
2048 int error;
2050 error = xfs_rmap_btrec_to_irec(rec, &irec);
2051 if (error)
2052 return error;
2053 return query->fn(cur, &irec, query->priv);
2056 /* Find all rmaps between two keys. */
2058 xfs_rmap_query_range(
2059 struct xfs_btree_cur *cur,
2060 struct xfs_rmap_irec *low_rec,
2061 struct xfs_rmap_irec *high_rec,
2062 xfs_rmap_query_range_fn fn,
2063 void *priv)
2065 union xfs_btree_irec low_brec;
2066 union xfs_btree_irec high_brec;
2067 struct xfs_rmap_query_range_info query;
2069 low_brec.r = *low_rec;
2070 high_brec.r = *high_rec;
2071 query.priv = priv;
2072 query.fn = fn;
2073 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2074 xfs_rmap_query_range_helper, &query);
2077 /* Find all rmaps. */
2079 xfs_rmap_query_all(
2080 struct xfs_btree_cur *cur,
2081 xfs_rmap_query_range_fn fn,
2082 void *priv)
2084 struct xfs_rmap_query_range_info query;
2086 query.priv = priv;
2087 query.fn = fn;
2088 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2091 /* Clean up after calling xfs_rmap_finish_one. */
2092 void
2093 xfs_rmap_finish_one_cleanup(
2094 struct xfs_trans *tp,
2095 struct xfs_btree_cur *rcur,
2096 int error)
2098 struct xfs_buf *agbp;
2100 if (rcur == NULL)
2101 return;
2102 agbp = rcur->bc_private.a.agbp;
2103 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2104 if (error)
2105 xfs_trans_brelse(tp, agbp);
2109 * Process one of the deferred rmap operations. We pass back the
2110 * btree cursor to maintain our lock on the rmapbt between calls.
2111 * This saves time and eliminates a buffer deadlock between the
2112 * superblock and the AGF because we'll always grab them in the same
2113 * order.
2116 xfs_rmap_finish_one(
2117 struct xfs_trans *tp,
2118 enum xfs_rmap_intent_type type,
2119 uint64_t owner,
2120 int whichfork,
2121 xfs_fileoff_t startoff,
2122 xfs_fsblock_t startblock,
2123 xfs_filblks_t blockcount,
2124 xfs_exntst_t state,
2125 struct xfs_btree_cur **pcur)
2127 struct xfs_mount *mp = tp->t_mountp;
2128 struct xfs_btree_cur *rcur;
2129 struct xfs_buf *agbp = NULL;
2130 int error = 0;
2131 xfs_agnumber_t agno;
2132 struct xfs_owner_info oinfo;
2133 xfs_agblock_t bno;
2134 bool unwritten;
2136 agno = XFS_FSB_TO_AGNO(mp, startblock);
2137 ASSERT(agno != NULLAGNUMBER);
2138 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2140 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2141 startoff, blockcount, state);
2143 if (XFS_TEST_ERROR(false, mp,
2144 XFS_ERRTAG_RMAP_FINISH_ONE))
2145 return -EIO;
2148 * If we haven't gotten a cursor or the cursor AG doesn't match
2149 * the startblock, get one now.
2151 rcur = *pcur;
2152 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2153 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2154 rcur = NULL;
2155 *pcur = NULL;
2157 if (rcur == NULL) {
2159 * Refresh the freelist before we start changing the
2160 * rmapbt, because a shape change could cause us to
2161 * allocate blocks.
2163 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2164 if (error)
2165 return error;
2166 if (!agbp)
2167 return -EFSCORRUPTED;
2169 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2170 if (!rcur) {
2171 error = -ENOMEM;
2172 goto out_cur;
2175 *pcur = rcur;
2177 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2178 unwritten = state == XFS_EXT_UNWRITTEN;
2179 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2181 switch (type) {
2182 case XFS_RMAP_ALLOC:
2183 case XFS_RMAP_MAP:
2184 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2185 break;
2186 case XFS_RMAP_MAP_SHARED:
2187 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2188 &oinfo);
2189 break;
2190 case XFS_RMAP_FREE:
2191 case XFS_RMAP_UNMAP:
2192 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2193 &oinfo);
2194 break;
2195 case XFS_RMAP_UNMAP_SHARED:
2196 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2197 &oinfo);
2198 break;
2199 case XFS_RMAP_CONVERT:
2200 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2201 &oinfo);
2202 break;
2203 case XFS_RMAP_CONVERT_SHARED:
2204 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2205 !unwritten, &oinfo);
2206 break;
2207 default:
2208 ASSERT(0);
2209 error = -EFSCORRUPTED;
2211 return error;
2213 out_cur:
2214 xfs_trans_brelse(tp, agbp);
2216 return error;
2220 * Don't defer an rmap if we aren't an rmap filesystem.
2222 static bool
2223 xfs_rmap_update_is_needed(
2224 struct xfs_mount *mp,
2225 int whichfork)
2227 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2231 * Record a rmap intent; the list is kept sorted first by AG and then by
2232 * increasing age.
2234 static int
2235 __xfs_rmap_add(
2236 struct xfs_mount *mp,
2237 struct xfs_defer_ops *dfops,
2238 enum xfs_rmap_intent_type type,
2239 uint64_t owner,
2240 int whichfork,
2241 struct xfs_bmbt_irec *bmap)
2243 struct xfs_rmap_intent *ri;
2245 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2246 type,
2247 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2248 owner, whichfork,
2249 bmap->br_startoff,
2250 bmap->br_blockcount,
2251 bmap->br_state);
2253 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2254 INIT_LIST_HEAD(&ri->ri_list);
2255 ri->ri_type = type;
2256 ri->ri_owner = owner;
2257 ri->ri_whichfork = whichfork;
2258 ri->ri_bmap = *bmap;
2260 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2261 return 0;
2264 /* Map an extent into a file. */
2266 xfs_rmap_map_extent(
2267 struct xfs_mount *mp,
2268 struct xfs_defer_ops *dfops,
2269 struct xfs_inode *ip,
2270 int whichfork,
2271 struct xfs_bmbt_irec *PREV)
2273 if (!xfs_rmap_update_is_needed(mp, whichfork))
2274 return 0;
2276 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2277 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2278 whichfork, PREV);
2281 /* Unmap an extent out of a file. */
2283 xfs_rmap_unmap_extent(
2284 struct xfs_mount *mp,
2285 struct xfs_defer_ops *dfops,
2286 struct xfs_inode *ip,
2287 int whichfork,
2288 struct xfs_bmbt_irec *PREV)
2290 if (!xfs_rmap_update_is_needed(mp, whichfork))
2291 return 0;
2293 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2294 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2295 whichfork, PREV);
2298 /* Convert a data fork extent from unwritten to real or vice versa. */
2300 xfs_rmap_convert_extent(
2301 struct xfs_mount *mp,
2302 struct xfs_defer_ops *dfops,
2303 struct xfs_inode *ip,
2304 int whichfork,
2305 struct xfs_bmbt_irec *PREV)
2307 if (!xfs_rmap_update_is_needed(mp, whichfork))
2308 return 0;
2310 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2311 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2312 whichfork, PREV);
2315 /* Schedule the creation of an rmap for non-file data. */
2317 xfs_rmap_alloc_extent(
2318 struct xfs_mount *mp,
2319 struct xfs_defer_ops *dfops,
2320 xfs_agnumber_t agno,
2321 xfs_agblock_t bno,
2322 xfs_extlen_t len,
2323 uint64_t owner)
2325 struct xfs_bmbt_irec bmap;
2327 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2328 return 0;
2330 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2331 bmap.br_blockcount = len;
2332 bmap.br_startoff = 0;
2333 bmap.br_state = XFS_EXT_NORM;
2335 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2336 XFS_DATA_FORK, &bmap);
2339 /* Schedule the deletion of an rmap for non-file data. */
2341 xfs_rmap_free_extent(
2342 struct xfs_mount *mp,
2343 struct xfs_defer_ops *dfops,
2344 xfs_agnumber_t agno,
2345 xfs_agblock_t bno,
2346 xfs_extlen_t len,
2347 uint64_t owner)
2349 struct xfs_bmbt_irec bmap;
2351 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2352 return 0;
2354 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2355 bmap.br_blockcount = len;
2356 bmap.br_startoff = 0;
2357 bmap.br_state = XFS_EXT_NORM;
2359 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2360 XFS_DATA_FORK, &bmap);
2363 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2365 xfs_rmap_compare(
2366 const struct xfs_rmap_irec *a,
2367 const struct xfs_rmap_irec *b)
2369 __u64 oa;
2370 __u64 ob;
2372 oa = xfs_rmap_irec_offset_pack(a);
2373 ob = xfs_rmap_irec_offset_pack(b);
2375 if (a->rm_startblock < b->rm_startblock)
2376 return -1;
2377 else if (a->rm_startblock > b->rm_startblock)
2378 return 1;
2379 else if (a->rm_owner < b->rm_owner)
2380 return -1;
2381 else if (a->rm_owner > b->rm_owner)
2382 return 1;
2383 else if (oa < ob)
2384 return -1;
2385 else if (oa > ob)
2386 return 1;
2387 else
2388 return 0;
2391 /* Is there a record covering a given extent? */
2393 xfs_rmap_has_record(
2394 struct xfs_btree_cur *cur,
2395 xfs_agblock_t bno,
2396 xfs_extlen_t len,
2397 bool *exists)
2399 union xfs_btree_irec low;
2400 union xfs_btree_irec high;
2402 memset(&low, 0, sizeof(low));
2403 low.r.rm_startblock = bno;
2404 memset(&high, 0xFF, sizeof(high));
2405 high.r.rm_startblock = bno + len - 1;
2407 return xfs_btree_has_record(cur, &low, &high, exists);
2411 * Is there a record for this owner completely covering a given physical
2412 * extent? If so, *has_rmap will be set to true. If there is no record
2413 * or the record only covers part of the range, we set *has_rmap to false.
2414 * This function doesn't perform range lookups or offset checks, so it is
2415 * not suitable for checking data fork blocks.
2418 xfs_rmap_record_exists(
2419 struct xfs_btree_cur *cur,
2420 xfs_agblock_t bno,
2421 xfs_extlen_t len,
2422 struct xfs_owner_info *oinfo,
2423 bool *has_rmap)
2425 uint64_t owner;
2426 uint64_t offset;
2427 unsigned int flags;
2428 int has_record;
2429 struct xfs_rmap_irec irec;
2430 int error;
2432 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2433 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2434 (flags & XFS_RMAP_BMBT_BLOCK));
2436 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2437 &has_record);
2438 if (error)
2439 return error;
2440 if (!has_record) {
2441 *has_rmap = false;
2442 return 0;
2445 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2446 if (error)
2447 return error;
2448 if (!has_record) {
2449 *has_rmap = false;
2450 return 0;
2453 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2454 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2455 return 0;