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