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