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 "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" 42 43 /* 44 * Lookup the first record less than or equal to [bno, len, owner, offset] 45 * in the btree given by cur. 46 */ 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) 56 { 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); 63 } 64 65 /* 66 * Lookup the record exactly matching [bno, len, owner, offset] 67 * in the btree given by cur. 68 */ 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) 78 { 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); 85 } 86 87 /* 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. 91 */ 92 STATIC int 93 xfs_rmap_update( 94 struct xfs_btree_cur *cur, 95 struct xfs_rmap_irec *irec) 96 { 97 union xfs_btree_rec rec; 98 int error; 99 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); 103 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; 114 } 115 116 int 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) 124 { 125 int i; 126 int error; 127 128 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno, 129 len, owner, offset, flags); 130 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); 135 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; 150 } 151 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) 160 { 161 int i; 162 int error; 163 164 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, 165 len, owner, offset, flags); 166 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); 171 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; 181 } 182 183 /* Convert an internal btree record to an rmap record. */ 184 int 185 xfs_rmap_btrec_to_irec( 186 union xfs_btree_rec *rec, 187 struct xfs_rmap_irec *irec) 188 { 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); 195 } 196 197 /* 198 * Get the data from the pointed-to record. 199 */ 200 int 201 xfs_rmap_get_rec( 202 struct xfs_btree_cur *cur, 203 struct xfs_rmap_irec *irec, 204 int *stat) 205 { 206 union xfs_btree_rec *rec; 207 int error; 208 209 error = xfs_btree_get_rec(cur, &rec, stat); 210 if (error || !*stat) 211 return error; 212 213 return xfs_rmap_btrec_to_irec(rec, irec); 214 } 215 216 struct xfs_find_left_neighbor_info { 217 struct xfs_rmap_irec high; 218 struct xfs_rmap_irec *irec; 219 int *stat; 220 }; 221 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) 228 { 229 struct xfs_find_left_neighbor_info *info = priv; 230 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); 235 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; 242 243 *info->irec = *rec; 244 *info->stat = 1; 245 return XFS_BTREE_QUERY_RANGE_ABORT; 246 } 247 248 /* 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. 252 */ 253 int 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) 262 { 263 struct xfs_find_left_neighbor_info info; 264 int error; 265 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; 282 283 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, 284 cur->bc_private.a.agno, bno, 0, owner, offset, flags); 285 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; 296 } 297 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) 304 { 305 struct xfs_find_left_neighbor_info *info = priv; 306 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); 311 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; 319 320 *info->irec = *rec; 321 *info->stat = 1; 322 return XFS_BTREE_QUERY_RANGE_ABORT; 323 } 324 325 /* 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. 330 */ 331 int 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) 340 { 341 struct xfs_find_left_neighbor_info info; 342 int error; 343 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; 355 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; 368 } 369 370 /* 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. 373 */ 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) 384 { 385 int error = 0; 386 387 if (owner == XFS_RMAP_OWN_UNKNOWN) 388 return 0; 389 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); 393 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); 396 397 /* Check the offset, if necessary. */ 398 if (XFS_RMAP_NON_INODE_OWNER(owner)) 399 goto out; 400 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); 409 } 410 411 out: 412 return error; 413 } 414 415 /* 416 * Find the extent in the rmap btree and remove it. 417 * 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. 420 * 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. 427 * 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. 432 */ 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) 440 { 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; 450 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); 458 459 /* 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. 463 */ 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); 468 469 error = xfs_rmap_get_rec(cur, <rec, &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; 478 479 /* 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. 485 */ 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; 490 } 491 492 /* 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. 498 */ 499 if (owner == XFS_RMAP_OWN_UNKNOWN && 500 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 501 struct xfs_rmap_irec rtrec; 502 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; 514 } 515 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); 520 521 /* Check owner information. */ 522 error = xfs_rmap_free_check_owner(mp, ltoff, <rec, bno, len, owner, 523 offset, flags); 524 if (error) 525 goto out_error; 526 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) { 538 /* 539 * overlap left hand side of extent: move the start, trim the 540 * length and update the current record. 541 * 542 * ltbno ltlen 543 * Orig: |oooooooooooooooooooo| 544 * Freeing: |fffffffff| 545 * Result: |rrrrrrrrrr| 546 * bno len 547 */ 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, <rec); 553 if (error) 554 goto out_error; 555 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 556 /* 557 * overlap right hand side of extent: trim the length and update 558 * the current record. 559 * 560 * ltbno ltlen 561 * Orig: |oooooooooooooooooooo| 562 * Freeing: |fffffffff| 563 * Result: |rrrrrrrrrr| 564 * bno len 565 */ 566 ltrec.rm_blockcount -= len; 567 error = xfs_rmap_update(cur, <rec); 568 if (error) 569 goto out_error; 570 } else { 571 572 /* 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. 577 * 578 * ltbno ltlen 579 * Orig: |oooooooooooooooooooo| 580 * Freeing: |fffffffff| 581 * Result: |rrrrr| |rrrr| 582 * bno len 583 */ 584 xfs_extlen_t orig_len = ltrec.rm_blockcount; 585 586 ltrec.rm_blockcount = bno - ltrec.rm_startblock; 587 error = xfs_rmap_update(cur, <rec); 588 if (error) 589 goto out_error; 590 591 error = xfs_btree_increment(cur, 0, &i); 592 if (error) 593 goto out_error; 594 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; 613 } 614 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; 623 } 624 625 /* 626 * Remove a reference to an extent in the rmap btree. 627 */ 628 int 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) 636 { 637 struct xfs_mount *mp = tp->t_mountp; 638 struct xfs_btree_cur *cur; 639 int error; 640 641 if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 642 return 0; 643 644 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 645 646 error = xfs_rmap_unmap(cur, bno, len, false, oinfo); 647 if (error) 648 goto out_error; 649 650 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 651 return 0; 652 653 out_error: 654 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 655 return error; 656 } 657 658 /* 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. 662 */ 663 static bool 664 xfs_rmap_is_mergeable( 665 struct xfs_rmap_irec *irec, 666 uint64_t owner, 667 unsigned int flags) 668 { 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; 683 } 684 685 /* 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. 690 */ 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) 698 { 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; 710 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)); 720 721 /* 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. 725 */ 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); 731 732 error = xfs_rmap_get_rec(cur, <rec, &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); 740 741 if (!xfs_rmap_is_mergeable(<rec, owner, flags)) 742 have_lt = 0; 743 744 XFS_WANT_CORRUPTED_GOTO(mp, 745 have_lt == 0 || 746 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); 747 748 /* 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. 752 */ 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, >rec, &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(>rec, owner, flags)) 768 have_gt = 0; 769 } 770 771 /* 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. 774 */ 775 if (have_lt && 776 ltrec.rm_startblock + ltrec.rm_blockcount == bno && 777 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { 778 /* 779 * left edge contiguous, merge into left record. 780 * 781 * ltbno ltlen 782 * orig: |ooooooooo| 783 * adding: |aaaaaaaaa| 784 * result: |rrrrrrrrrrrrrrrrrrr| 785 * bno len 786 */ 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) { 793 /* 794 * right edge also contiguous, delete right record 795 * and merge into left record. 796 * 797 * ltbno ltlen gtbno gtlen 798 * orig: |ooooooooo| |ooooooooo| 799 * adding: |aaaaaaaaa| 800 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 801 */ 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); 813 } 814 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, <rec); 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)) { 825 /* 826 * right edge contiguous, merge into right record. 827 * 828 * gtbno gtlen 829 * Orig: |ooooooooo| 830 * adding: |aaaaaaaaa| 831 * Result: |rrrrrrrrrrrrrrrrrrr| 832 * bno len 833 */ 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, >rec); 839 if (error) 840 goto out_error; 841 } else { 842 /* 843 * no contiguous edge with identical owner, insert 844 * new record at current cursor position. 845 */ 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); 857 } 858 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; 866 } 867 868 /* 869 * Add a reference to an extent in the rmap btree. 870 */ 871 int 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) 879 { 880 struct xfs_mount *mp = tp->t_mountp; 881 struct xfs_btree_cur *cur; 882 int error; 883 884 if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 885 return 0; 886 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; 891 892 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 893 return 0; 894 895 out_error: 896 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 897 return error; 898 } 899 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) 906 907 #define LEFT r[0] 908 #define RIGHT r[1] 909 #define PREV r[2] 910 #define NEW r[3] 911 912 /* 913 * Convert an unwritten extent to a real extent or vice versa. 914 * Does not handle overlapping extents. 915 */ 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) 923 { 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; 937 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); 945 946 /* 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. 950 */ 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); 955 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); 964 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; 969 970 /* 971 * Set flags determining what part of the previous oldext allocation 972 * extent is being replaced by a newext allocation. 973 */ 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; 978 979 /* 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. 983 */ 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; 1004 } 1005 1006 /* 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. 1010 */ 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; 1034 } 1035 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; 1044 1045 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 1046 _RET_IP_); 1047 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); 1053 1054 /* 1055 * Switch out based on the FILLING and CONTIG state bits. 1056 */ 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: 1061 /* 1062 * Setting all of a previous oldext extent to newext. 1063 * The left and right neighbors are both contiguous with new. 1064 */ 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; 1099 1100 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1101 /* 1102 * Setting all of a previous oldext extent to newext. 1103 * The left neighbor is contiguous, the right is not. 1104 */ 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; 1123 1124 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1125 /* 1126 * Setting all of a previous oldext extent to newext. 1127 * The right neighbor is contiguous, the left is not. 1128 */ 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; 1152 1153 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1154 /* 1155 * Setting all of a previous oldext extent to newext. 1156 * Neither the left nor right neighbors are contiguous with 1157 * the new one. 1158 */ 1159 NEW = PREV; 1160 NEW.rm_flags = newext; 1161 error = xfs_rmap_update(cur, &NEW); 1162 if (error) 1163 goto done; 1164 break; 1165 1166 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1167 /* 1168 * Setting the first part of a previous oldext extent to newext. 1169 * The left neighbor is contiguous. 1170 */ 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; 1187 1188 case RMAP_LEFT_FILLING: 1189 /* 1190 * Setting the first part of a previous oldext extent to newext. 1191 * The left neighbor is not contiguous. 1192 */ 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; 1213 1214 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1215 /* 1216 * Setting the last part of a previous oldext extent to newext. 1217 * The right neighbor is contiguous with the new allocation. 1218 */ 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; 1235 1236 case RMAP_RIGHT_FILLING: 1237 /* 1238 * Setting the last part of a previous oldext extent to newext. 1239 * The right neighbor is not contiguous. 1240 */ 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; 1264 1265 case 0: 1266 /* 1267 * Setting the middle part of a previous oldext extent to 1268 * newext. Contiguity is impossible here. 1269 * One extent becomes three extents. 1270 */ 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); 1293 /* 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. 1297 */ 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; 1313 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: 1321 /* 1322 * These cases are all impossible. 1323 */ 1324 ASSERT(0); 1325 } 1326 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; 1334 } 1335 1336 /* 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. 1340 */ 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) 1348 { 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; 1362 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); 1370 1371 /* 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. 1375 */ 1376 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 1377 &PREV, &i); 1378 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1379 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; 1384 1385 /* 1386 * Set flags determining what part of the previous oldext allocation 1387 * extent is being replaced by a newext allocation. 1388 */ 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; 1393 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; 1406 } 1407 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; 1427 } 1428 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; 1437 1438 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 1439 _RET_IP_); 1440 /* 1441 * Switch out based on the FILLING and CONTIG state bits. 1442 */ 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: 1447 /* 1448 * Setting all of a previous oldext extent to newext. 1449 * The left and right neighbors are both contiguous with new. 1450 */ 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; 1473 1474 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1475 /* 1476 * Setting all of a previous oldext extent to newext. 1477 * The left neighbor is contiguous, the right is not. 1478 */ 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; 1496 1497 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1498 /* 1499 * Setting all of a previous oldext extent to newext. 1500 * The right neighbor is contiguous, the left is not. 1501 */ 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; 1520 1521 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1522 /* 1523 * Setting all of a previous oldext extent to newext. 1524 * Neither the left nor right neighbors are contiguous with 1525 * the new one. 1526 */ 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; 1539 1540 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1541 /* 1542 * Setting the first part of a previous oldext extent to newext. 1543 * The left neighbor is contiguous. 1544 */ 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; 1571 1572 case RMAP_LEFT_FILLING: 1573 /* 1574 * Setting the first part of a previous oldext extent to newext. 1575 * The left neighbor is not contiguous. 1576 */ 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; 1595 1596 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1597 /* 1598 * Setting the last part of a previous oldext extent to newext. 1599 * The right neighbor is contiguous with the new allocation. 1600 */ 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; 1627 1628 case RMAP_RIGHT_FILLING: 1629 /* 1630 * Setting the last part of a previous oldext extent to newext. 1631 * The right neighbor is not contiguous. 1632 */ 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; 1648 1649 case 0: 1650 /* 1651 * Setting the middle part of a previous oldext extent to 1652 * newext. Contiguity is impossible here. 1653 * One extent becomes three extents. 1654 */ 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; 1691 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: 1699 /* 1700 * These cases are all impossible. 1701 */ 1702 ASSERT(0); 1703 } 1704 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; 1712 } 1713 1714 #undef NEW 1715 #undef LEFT 1716 #undef RIGHT 1717 #undef PREV 1718 1719 /* 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. 1724 * 1725 * For every other situation there can only be one owner for a given extent, 1726 * so we can call the regular _free function. 1727 */ 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) 1735 { 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; 1744 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); 1750 1751 /* 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. 1755 */ 1756 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 1757 <rec, &i); 1758 if (error) 1759 goto out_error; 1760 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1761 ltoff = ltrec.rm_offset; 1762 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); 1767 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); 1770 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); 1774 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); 1779 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) { 1788 /* 1789 * Overlap left hand side of extent: move the start, trim the 1790 * length and update the current record. 1791 * 1792 * ltbno ltlen 1793 * Orig: |oooooooooooooooooooo| 1794 * Freeing: |fffffffff| 1795 * Result: |rrrrrrrrrr| 1796 * bno len 1797 */ 1798 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; 1805 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) { 1816 /* 1817 * Overlap right hand side of extent: trim the length and 1818 * update the current record. 1819 * 1820 * ltbno ltlen 1821 * Orig: |oooooooooooooooooooo| 1822 * Freeing: |fffffffff| 1823 * Result: |rrrrrrrrrr| 1824 * bno len 1825 */ 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, <rec); 1834 if (error) 1835 goto out_error; 1836 } else { 1837 /* 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. 1842 * 1843 * ltbno ltlen 1844 * Orig: |oooooooooooooooooooo| 1845 * Freeing: |fffffffff| 1846 * Result: |rrrrr| |rrrr| 1847 * bno len 1848 */ 1849 xfs_extlen_t orig_len = ltrec.rm_blockcount; 1850 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, <rec); 1860 if (error) 1861 goto out_error; 1862 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; 1870 } 1871 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; 1879 } 1880 1881 /* 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. 1886 * 1887 * For every other situation there can only be one owner for a given extent, 1888 * so we can call the regular _alloc function. 1889 */ 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) 1897 { 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; 1908 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); 1914 1915 /* Is there a left record that abuts our range? */ 1916 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, 1917 <rec, &have_lt); 1918 if (error) 1919 goto out_error; 1920 if (have_lt && 1921 !xfs_rmap_is_mergeable(<rec, owner, flags)) 1922 have_lt = 0; 1923 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, >rec, &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); 1938 1939 if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 1940 have_gt = 0; 1941 } 1942 1943 if (have_lt && 1944 ltrec.rm_startblock + ltrec.rm_blockcount == bno && 1945 ltrec.rm_offset + ltrec.rm_blockcount == offset) { 1946 /* 1947 * Left edge contiguous, merge into left record. 1948 * 1949 * ltbno ltlen 1950 * orig: |ooooooooo| 1951 * adding: |aaaaaaaaa| 1952 * result: |rrrrrrrrrrrrrrrrrrr| 1953 * bno len 1954 */ 1955 ltrec.rm_blockcount += len; 1956 if (have_gt && 1957 bno + len == gtrec.rm_startblock && 1958 offset + len == gtrec.rm_offset) { 1959 /* 1960 * Right edge also contiguous, delete right record 1961 * and merge into left record. 1962 * 1963 * ltbno ltlen gtbno gtlen 1964 * orig: |ooooooooo| |ooooooooo| 1965 * adding: |aaaaaaaaa| 1966 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 1967 */ 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; 1974 } 1975 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); 1983 1984 error = xfs_rmap_update(cur, <rec); 1985 if (error) 1986 goto out_error; 1987 } else if (have_gt && 1988 bno + len == gtrec.rm_startblock && 1989 offset + len == gtrec.rm_offset) { 1990 /* 1991 * Right edge contiguous, merge into right record. 1992 * 1993 * gtbno gtlen 1994 * Orig: |ooooooooo| 1995 * adding: |aaaaaaaaa| 1996 * Result: |rrrrrrrrrrrrrrrrrrr| 1997 * bno len 1998 */ 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; 2005 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 { 2016 /* 2017 * No contiguous edge with identical owner, insert 2018 * new record at current cursor position. 2019 */ 2020 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); 2021 if (error) 2022 goto out_error; 2023 } 2024 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; 2032 } 2033 2034 struct xfs_rmap_query_range_info { 2035 xfs_rmap_query_range_fn fn; 2036 void *priv; 2037 }; 2038 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) 2045 { 2046 struct xfs_rmap_query_range_info *query = priv; 2047 struct xfs_rmap_irec irec; 2048 int error; 2049 2050 error = xfs_rmap_btrec_to_irec(rec, &irec); 2051 if (error) 2052 return error; 2053 return query->fn(cur, &irec, query->priv); 2054 } 2055 2056 /* Find all rmaps between two keys. */ 2057 int 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) 2064 { 2065 union xfs_btree_irec low_brec; 2066 union xfs_btree_irec high_brec; 2067 struct xfs_rmap_query_range_info query; 2068 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); 2075 } 2076 2077 /* Find all rmaps. */ 2078 int 2079 xfs_rmap_query_all( 2080 struct xfs_btree_cur *cur, 2081 xfs_rmap_query_range_fn fn, 2082 void *priv) 2083 { 2084 struct xfs_rmap_query_range_info query; 2085 2086 query.priv = priv; 2087 query.fn = fn; 2088 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query); 2089 } 2090 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) 2097 { 2098 struct xfs_buf *agbp; 2099 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); 2106 } 2107 2108 /* 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. 2114 */ 2115 int 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) 2126 { 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; 2135 2136 agno = XFS_FSB_TO_AGNO(mp, startblock); 2137 ASSERT(agno != NULLAGNUMBER); 2138 bno = XFS_FSB_TO_AGBNO(mp, startblock); 2139 2140 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, 2141 startoff, blockcount, state); 2142 2143 if (XFS_TEST_ERROR(false, mp, 2144 XFS_ERRTAG_RMAP_FINISH_ONE)) 2145 return -EIO; 2146 2147 /* 2148 * If we haven't gotten a cursor or the cursor AG doesn't match 2149 * the startblock, get one now. 2150 */ 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; 2156 } 2157 if (rcur == NULL) { 2158 /* 2159 * Refresh the freelist before we start changing the 2160 * rmapbt, because a shape change could cause us to 2161 * allocate blocks. 2162 */ 2163 error = xfs_free_extent_fix_freelist(tp, agno, &agbp); 2164 if (error) 2165 return error; 2166 if (!agbp) 2167 return -EFSCORRUPTED; 2168 2169 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 2170 if (!rcur) { 2171 error = -ENOMEM; 2172 goto out_cur; 2173 } 2174 } 2175 *pcur = rcur; 2176 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); 2180 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; 2210 } 2211 return error; 2212 2213 out_cur: 2214 xfs_trans_brelse(tp, agbp); 2215 2216 return error; 2217 } 2218 2219 /* 2220 * Don't defer an rmap if we aren't an rmap filesystem. 2221 */ 2222 static bool 2223 xfs_rmap_update_is_needed( 2224 struct xfs_mount *mp, 2225 int whichfork) 2226 { 2227 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK; 2228 } 2229 2230 /* 2231 * Record a rmap intent; the list is kept sorted first by AG and then by 2232 * increasing age. 2233 */ 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) 2242 { 2243 struct xfs_rmap_intent *ri; 2244 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); 2252 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; 2259 2260 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); 2261 return 0; 2262 } 2263 2264 /* Map an extent into a file. */ 2265 int 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) 2272 { 2273 if (!xfs_rmap_update_is_needed(mp, whichfork)) 2274 return 0; 2275 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); 2279 } 2280 2281 /* Unmap an extent out of a file. */ 2282 int 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) 2289 { 2290 if (!xfs_rmap_update_is_needed(mp, whichfork)) 2291 return 0; 2292 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); 2296 } 2297 2298 /* Convert a data fork extent from unwritten to real or vice versa. */ 2299 int 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) 2306 { 2307 if (!xfs_rmap_update_is_needed(mp, whichfork)) 2308 return 0; 2309 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); 2313 } 2314 2315 /* Schedule the creation of an rmap for non-file data. */ 2316 int 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) 2324 { 2325 struct xfs_bmbt_irec bmap; 2326 2327 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) 2328 return 0; 2329 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; 2334 2335 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner, 2336 XFS_DATA_FORK, &bmap); 2337 } 2338 2339 /* Schedule the deletion of an rmap for non-file data. */ 2340 int 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) 2348 { 2349 struct xfs_bmbt_irec bmap; 2350 2351 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) 2352 return 0; 2353 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; 2358 2359 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner, 2360 XFS_DATA_FORK, &bmap); 2361 } 2362 2363 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ 2364 int 2365 xfs_rmap_compare( 2366 const struct xfs_rmap_irec *a, 2367 const struct xfs_rmap_irec *b) 2368 { 2369 __u64 oa; 2370 __u64 ob; 2371 2372 oa = xfs_rmap_irec_offset_pack(a); 2373 ob = xfs_rmap_irec_offset_pack(b); 2374 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; 2389 } 2390 2391 /* Is there a record covering a given extent? */ 2392 int 2393 xfs_rmap_has_record( 2394 struct xfs_btree_cur *cur, 2395 xfs_agblock_t bno, 2396 xfs_extlen_t len, 2397 bool *exists) 2398 { 2399 union xfs_btree_irec low; 2400 union xfs_btree_irec high; 2401 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; 2406 2407 return xfs_btree_has_record(cur, &low, &high, exists); 2408 } 2409 2410 /* 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. 2416 */ 2417 int 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) 2424 { 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; 2431 2432 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2433 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || 2434 (flags & XFS_RMAP_BMBT_BLOCK)); 2435 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; 2443 } 2444 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; 2451 } 2452 2453 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno && 2454 irec.rm_startblock + irec.rm_blockcount >= bno + len); 2455 return 0; 2456 } 2457