10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0 2673930c3SDarrick J. Wong /* 3673930c3SDarrick J. Wong * Copyright (c) 2014 Red Hat, Inc. 4673930c3SDarrick J. Wong * All Rights Reserved. 5673930c3SDarrick J. Wong */ 6673930c3SDarrick J. Wong #include "xfs.h" 7673930c3SDarrick J. Wong #include "xfs_fs.h" 8673930c3SDarrick J. Wong #include "xfs_shared.h" 9673930c3SDarrick J. Wong #include "xfs_format.h" 10673930c3SDarrick J. Wong #include "xfs_log_format.h" 11673930c3SDarrick J. Wong #include "xfs_trans_resv.h" 12673930c3SDarrick J. Wong #include "xfs_bit.h" 13673930c3SDarrick J. Wong #include "xfs_mount.h" 14673930c3SDarrick J. Wong #include "xfs_defer.h" 15673930c3SDarrick J. Wong #include "xfs_btree.h" 16673930c3SDarrick J. Wong #include "xfs_trans.h" 17673930c3SDarrick J. Wong #include "xfs_alloc.h" 18673930c3SDarrick J. Wong #include "xfs_rmap.h" 190a1b0b38SDarrick J. Wong #include "xfs_rmap_btree.h" 20673930c3SDarrick J. Wong #include "xfs_trace.h" 21e9e899a2SDarrick J. Wong #include "xfs_errortag.h" 22673930c3SDarrick J. Wong #include "xfs_error.h" 239c194644SDarrick J. Wong #include "xfs_inode.h" 24673930c3SDarrick J. Wong 254b8ed677SDarrick J. Wong /* 264b8ed677SDarrick J. Wong * Lookup the first record less than or equal to [bno, len, owner, offset] 274b8ed677SDarrick J. Wong * in the btree given by cur. 284b8ed677SDarrick J. Wong */ 294b8ed677SDarrick J. Wong int 304b8ed677SDarrick J. Wong xfs_rmap_lookup_le( 314b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 324b8ed677SDarrick J. Wong xfs_agblock_t bno, 334b8ed677SDarrick J. Wong xfs_extlen_t len, 344b8ed677SDarrick J. Wong uint64_t owner, 354b8ed677SDarrick J. Wong uint64_t offset, 364b8ed677SDarrick J. Wong unsigned int flags, 374b8ed677SDarrick J. Wong int *stat) 384b8ed677SDarrick J. Wong { 394b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 404b8ed677SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 414b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 424b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 434b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 444b8ed677SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); 454b8ed677SDarrick J. Wong } 464b8ed677SDarrick J. Wong 474b8ed677SDarrick J. Wong /* 484b8ed677SDarrick J. Wong * Lookup the record exactly matching [bno, len, owner, offset] 494b8ed677SDarrick J. Wong * in the btree given by cur. 504b8ed677SDarrick J. Wong */ 514b8ed677SDarrick J. Wong int 524b8ed677SDarrick J. Wong xfs_rmap_lookup_eq( 534b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 544b8ed677SDarrick J. Wong xfs_agblock_t bno, 554b8ed677SDarrick J. Wong xfs_extlen_t len, 564b8ed677SDarrick J. Wong uint64_t owner, 574b8ed677SDarrick J. Wong uint64_t offset, 584b8ed677SDarrick J. Wong unsigned int flags, 594b8ed677SDarrick J. Wong int *stat) 604b8ed677SDarrick J. Wong { 614b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 624b8ed677SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 634b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 644b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 654b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 664b8ed677SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); 674b8ed677SDarrick J. Wong } 684b8ed677SDarrick J. Wong 694b8ed677SDarrick J. Wong /* 704b8ed677SDarrick J. Wong * Update the record referred to by cur to the value given 714b8ed677SDarrick J. Wong * by [bno, len, owner, offset]. 724b8ed677SDarrick J. Wong * This either works (return 0) or gets an EFSCORRUPTED error. 734b8ed677SDarrick J. Wong */ 744b8ed677SDarrick J. Wong STATIC int 754b8ed677SDarrick J. Wong xfs_rmap_update( 764b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 774b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec) 784b8ed677SDarrick J. Wong { 794b8ed677SDarrick J. Wong union xfs_btree_rec rec; 80abf09233SDarrick J. Wong int error; 81abf09233SDarrick J. Wong 82abf09233SDarrick J. Wong trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno, 83abf09233SDarrick J. Wong irec->rm_startblock, irec->rm_blockcount, 84abf09233SDarrick J. Wong irec->rm_owner, irec->rm_offset, irec->rm_flags); 854b8ed677SDarrick J. Wong 864b8ed677SDarrick J. Wong rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); 874b8ed677SDarrick J. Wong rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); 884b8ed677SDarrick J. Wong rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); 894b8ed677SDarrick J. Wong rec.rmap.rm_offset = cpu_to_be64( 904b8ed677SDarrick J. Wong xfs_rmap_irec_offset_pack(irec)); 91abf09233SDarrick J. Wong error = xfs_btree_update(cur, &rec); 92abf09233SDarrick J. Wong if (error) 93abf09233SDarrick J. Wong trace_xfs_rmap_update_error(cur->bc_mp, 94abf09233SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 95abf09233SDarrick J. Wong return error; 96abf09233SDarrick J. Wong } 97abf09233SDarrick J. Wong 98abf09233SDarrick J. Wong int 99abf09233SDarrick J. Wong xfs_rmap_insert( 100abf09233SDarrick J. Wong struct xfs_btree_cur *rcur, 101abf09233SDarrick J. Wong xfs_agblock_t agbno, 102abf09233SDarrick J. Wong xfs_extlen_t len, 103abf09233SDarrick J. Wong uint64_t owner, 104abf09233SDarrick J. Wong uint64_t offset, 105abf09233SDarrick J. Wong unsigned int flags) 106abf09233SDarrick J. Wong { 107abf09233SDarrick J. Wong int i; 108abf09233SDarrick J. Wong int error; 109abf09233SDarrick J. Wong 110abf09233SDarrick J. Wong trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno, 111abf09233SDarrick J. Wong len, owner, offset, flags); 112abf09233SDarrick J. Wong 113abf09233SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); 114abf09233SDarrick J. Wong if (error) 115abf09233SDarrick J. Wong goto done; 116f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) { 117f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 118f9e03706SDarrick J. Wong goto done; 119f9e03706SDarrick J. Wong } 120abf09233SDarrick J. Wong 121abf09233SDarrick J. Wong rcur->bc_rec.r.rm_startblock = agbno; 122abf09233SDarrick J. Wong rcur->bc_rec.r.rm_blockcount = len; 123abf09233SDarrick J. Wong rcur->bc_rec.r.rm_owner = owner; 124abf09233SDarrick J. Wong rcur->bc_rec.r.rm_offset = offset; 125abf09233SDarrick J. Wong rcur->bc_rec.r.rm_flags = flags; 126abf09233SDarrick J. Wong error = xfs_btree_insert(rcur, &i); 127abf09233SDarrick J. Wong if (error) 128abf09233SDarrick J. Wong goto done; 129f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { 130f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 131f9e03706SDarrick J. Wong goto done; 132f9e03706SDarrick J. Wong } 133abf09233SDarrick J. Wong done: 134abf09233SDarrick J. Wong if (error) 135abf09233SDarrick J. Wong trace_xfs_rmap_insert_error(rcur->bc_mp, 136abf09233SDarrick J. Wong rcur->bc_private.a.agno, error, _RET_IP_); 137abf09233SDarrick J. Wong return error; 1384b8ed677SDarrick J. Wong } 1394b8ed677SDarrick J. Wong 140ceeb9c83SDarrick J. Wong STATIC int 141ceeb9c83SDarrick J. Wong xfs_rmap_delete( 142ceeb9c83SDarrick J. Wong struct xfs_btree_cur *rcur, 143ceeb9c83SDarrick J. Wong xfs_agblock_t agbno, 144ceeb9c83SDarrick J. Wong xfs_extlen_t len, 145ceeb9c83SDarrick J. Wong uint64_t owner, 146ceeb9c83SDarrick J. Wong uint64_t offset, 147ceeb9c83SDarrick J. Wong unsigned int flags) 148ceeb9c83SDarrick J. Wong { 149ceeb9c83SDarrick J. Wong int i; 150ceeb9c83SDarrick J. Wong int error; 151ceeb9c83SDarrick J. Wong 152ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, 153ceeb9c83SDarrick J. Wong len, owner, offset, flags); 154ceeb9c83SDarrick J. Wong 155ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); 156ceeb9c83SDarrick J. Wong if (error) 157ceeb9c83SDarrick J. Wong goto done; 158f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { 159f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 160f9e03706SDarrick J. Wong goto done; 161f9e03706SDarrick J. Wong } 162ceeb9c83SDarrick J. Wong 163ceeb9c83SDarrick J. Wong error = xfs_btree_delete(rcur, &i); 164ceeb9c83SDarrick J. Wong if (error) 165ceeb9c83SDarrick J. Wong goto done; 166f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { 167f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 168f9e03706SDarrick J. Wong goto done; 169f9e03706SDarrick J. Wong } 170ceeb9c83SDarrick J. Wong done: 171ceeb9c83SDarrick J. Wong if (error) 172ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete_error(rcur->bc_mp, 173ceeb9c83SDarrick J. Wong rcur->bc_private.a.agno, error, _RET_IP_); 174ceeb9c83SDarrick J. Wong return error; 175ceeb9c83SDarrick J. Wong } 176ceeb9c83SDarrick J. Wong 17726788097SDarrick J. Wong /* Convert an internal btree record to an rmap record. */ 17826788097SDarrick J. Wong int 1794b8ed677SDarrick J. Wong xfs_rmap_btrec_to_irec( 1804b8ed677SDarrick J. Wong union xfs_btree_rec *rec, 1814b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec) 1824b8ed677SDarrick J. Wong { 1834b8ed677SDarrick J. Wong irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); 1844b8ed677SDarrick J. Wong irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); 1854b8ed677SDarrick J. Wong irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); 1864b8ed677SDarrick J. Wong return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), 1874b8ed677SDarrick J. Wong irec); 1884b8ed677SDarrick J. Wong } 1894b8ed677SDarrick J. Wong 1904b8ed677SDarrick J. Wong /* 1914b8ed677SDarrick J. Wong * Get the data from the pointed-to record. 1924b8ed677SDarrick J. Wong */ 1934b8ed677SDarrick J. Wong int 1944b8ed677SDarrick J. Wong xfs_rmap_get_rec( 1954b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 1964b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec, 1974b8ed677SDarrick J. Wong int *stat) 1984b8ed677SDarrick J. Wong { 1999e6c08d4SDave Chinner struct xfs_mount *mp = cur->bc_mp; 2009e6c08d4SDave Chinner xfs_agnumber_t agno = cur->bc_private.a.agno; 2014b8ed677SDarrick J. Wong union xfs_btree_rec *rec; 2024b8ed677SDarrick J. Wong int error; 2034b8ed677SDarrick J. Wong 2044b8ed677SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat); 2054b8ed677SDarrick J. Wong if (error || !*stat) 2064b8ed677SDarrick J. Wong return error; 2074b8ed677SDarrick J. Wong 2089e6c08d4SDave Chinner if (xfs_rmap_btrec_to_irec(rec, irec)) 2099e6c08d4SDave Chinner goto out_bad_rec; 2109e6c08d4SDave Chinner 2119e6c08d4SDave Chinner if (irec->rm_blockcount == 0) 2129e6c08d4SDave Chinner goto out_bad_rec; 2139e6c08d4SDave Chinner if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) { 2149e6c08d4SDave Chinner if (irec->rm_owner != XFS_RMAP_OWN_FS) 2159e6c08d4SDave Chinner goto out_bad_rec; 2169e6c08d4SDave Chinner if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1) 2179e6c08d4SDave Chinner goto out_bad_rec; 2189e6c08d4SDave Chinner } else { 2199e6c08d4SDave Chinner /* check for valid extent range, including overflow */ 2209e6c08d4SDave Chinner if (!xfs_verify_agbno(mp, agno, irec->rm_startblock)) 2219e6c08d4SDave Chinner goto out_bad_rec; 2229e6c08d4SDave Chinner if (irec->rm_startblock > 2239e6c08d4SDave Chinner irec->rm_startblock + irec->rm_blockcount) 2249e6c08d4SDave Chinner goto out_bad_rec; 2259e6c08d4SDave Chinner if (!xfs_verify_agbno(mp, agno, 2269e6c08d4SDave Chinner irec->rm_startblock + irec->rm_blockcount - 1)) 2279e6c08d4SDave Chinner goto out_bad_rec; 2289e6c08d4SDave Chinner } 2299e6c08d4SDave Chinner 2309e6c08d4SDave Chinner if (!(xfs_verify_ino(mp, irec->rm_owner) || 2319e6c08d4SDave Chinner (irec->rm_owner <= XFS_RMAP_OWN_FS && 2329e6c08d4SDave Chinner irec->rm_owner >= XFS_RMAP_OWN_MIN))) 2339e6c08d4SDave Chinner goto out_bad_rec; 2349e6c08d4SDave Chinner 2359e6c08d4SDave Chinner return 0; 2369e6c08d4SDave Chinner out_bad_rec: 2379e6c08d4SDave Chinner xfs_warn(mp, 2389e6c08d4SDave Chinner "Reverse Mapping BTree record corruption in AG %d detected!", 2399e6c08d4SDave Chinner agno); 2409e6c08d4SDave Chinner xfs_warn(mp, 2419e6c08d4SDave Chinner "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", 2429e6c08d4SDave Chinner irec->rm_owner, irec->rm_flags, irec->rm_startblock, 2439e6c08d4SDave Chinner irec->rm_blockcount); 2449e6c08d4SDave Chinner return -EFSCORRUPTED; 2454b8ed677SDarrick J. Wong } 2464b8ed677SDarrick J. Wong 247ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info { 248ceeb9c83SDarrick J. Wong struct xfs_rmap_irec high; 249ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec; 250ceeb9c83SDarrick J. Wong int *stat; 251ceeb9c83SDarrick J. Wong }; 252ceeb9c83SDarrick J. Wong 253ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 254ceeb9c83SDarrick J. Wong STATIC int 255ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper( 256ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 257ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *rec, 258ceeb9c83SDarrick J. Wong void *priv) 259ceeb9c83SDarrick J. Wong { 260ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 261ceeb9c83SDarrick J. Wong 262ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, 263ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, rec->rm_startblock, 264ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 265ceeb9c83SDarrick J. Wong rec->rm_flags); 266ceeb9c83SDarrick J. Wong 267ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 26839ee2239SDarrick J. Wong return 0; 269ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 270ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 271ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) 27239ee2239SDarrick J. Wong return 0; 273ceeb9c83SDarrick J. Wong 274ceeb9c83SDarrick J. Wong *info->irec = *rec; 275ceeb9c83SDarrick J. Wong *info->stat = 1; 276e7ee96dfSDarrick J. Wong return -ECANCELED; 277ceeb9c83SDarrick J. Wong } 278ceeb9c83SDarrick J. Wong 279ceeb9c83SDarrick J. Wong /* 280ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 281ceeb9c83SDarrick J. Wong * return a match with the same owner and adjacent physical and logical 282ceeb9c83SDarrick J. Wong * block ranges. 283ceeb9c83SDarrick J. Wong */ 284ceeb9c83SDarrick J. Wong int 285ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor( 286ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 287ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 288ceeb9c83SDarrick J. Wong uint64_t owner, 289ceeb9c83SDarrick J. Wong uint64_t offset, 290ceeb9c83SDarrick J. Wong unsigned int flags, 291ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 292ceeb9c83SDarrick J. Wong int *stat) 293ceeb9c83SDarrick J. Wong { 294ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 295ceeb9c83SDarrick J. Wong int error; 296ceeb9c83SDarrick J. Wong 297ceeb9c83SDarrick J. Wong *stat = 0; 298ceeb9c83SDarrick J. Wong if (bno == 0) 299ceeb9c83SDarrick J. Wong return 0; 300ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno - 1; 301ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 302ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && 303ceeb9c83SDarrick J. Wong !(flags & XFS_RMAP_BMBT_BLOCK)) { 304ceeb9c83SDarrick J. Wong if (offset == 0) 305ceeb9c83SDarrick J. Wong return 0; 306ceeb9c83SDarrick J. Wong info.high.rm_offset = offset - 1; 307ceeb9c83SDarrick J. Wong } else 308ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 309ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 310ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 311ceeb9c83SDarrick J. Wong info.irec = irec; 312ceeb9c83SDarrick J. Wong info.stat = stat; 313ceeb9c83SDarrick J. Wong 314ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, 315ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, bno, 0, owner, offset, flags); 316ceeb9c83SDarrick J. Wong 317ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 318ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper, &info); 319e7ee96dfSDarrick J. Wong if (error == -ECANCELED) 320ceeb9c83SDarrick J. Wong error = 0; 321ceeb9c83SDarrick J. Wong if (*stat) 322ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 323ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, irec->rm_startblock, 324ceeb9c83SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, 325ceeb9c83SDarrick J. Wong irec->rm_offset, irec->rm_flags); 326ceeb9c83SDarrick J. Wong return error; 327ceeb9c83SDarrick J. Wong } 328ceeb9c83SDarrick J. Wong 329ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 330ceeb9c83SDarrick J. Wong STATIC int 331ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper( 332ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 333ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *rec, 334ceeb9c83SDarrick J. Wong void *priv) 335ceeb9c83SDarrick J. Wong { 336ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 337ceeb9c83SDarrick J. Wong 338ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, 339ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, rec->rm_startblock, 340ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 341ceeb9c83SDarrick J. Wong rec->rm_flags); 342ceeb9c83SDarrick J. Wong 343ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 34439ee2239SDarrick J. Wong return 0; 345ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 346ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 347ceeb9c83SDarrick J. Wong (rec->rm_offset > info->high.rm_offset || 348ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) 34939ee2239SDarrick J. Wong return 0; 350ceeb9c83SDarrick J. Wong 351ceeb9c83SDarrick J. Wong *info->irec = *rec; 352ceeb9c83SDarrick J. Wong *info->stat = 1; 353e7ee96dfSDarrick J. Wong return -ECANCELED; 354ceeb9c83SDarrick J. Wong } 355ceeb9c83SDarrick J. Wong 356ceeb9c83SDarrick J. Wong /* 357ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 358ceeb9c83SDarrick J. Wong * return a match with the same owner and overlapping physical and logical 359ceeb9c83SDarrick J. Wong * block ranges. This is the overlapping-interval version of 360ceeb9c83SDarrick J. Wong * xfs_rmap_lookup_le. 361ceeb9c83SDarrick J. Wong */ 362ceeb9c83SDarrick J. Wong int 363ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range( 364ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 365ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 366ceeb9c83SDarrick J. Wong uint64_t owner, 367ceeb9c83SDarrick J. Wong uint64_t offset, 368ceeb9c83SDarrick J. Wong unsigned int flags, 369ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 370ceeb9c83SDarrick J. Wong int *stat) 371ceeb9c83SDarrick J. Wong { 372ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 373ceeb9c83SDarrick J. Wong int error; 374ceeb9c83SDarrick J. Wong 375ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno; 376ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 377ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) 378ceeb9c83SDarrick J. Wong info.high.rm_offset = offset; 379ceeb9c83SDarrick J. Wong else 380ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 381ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 382ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 383ceeb9c83SDarrick J. Wong *stat = 0; 384ceeb9c83SDarrick J. Wong info.irec = irec; 385ceeb9c83SDarrick J. Wong info.stat = stat; 386ceeb9c83SDarrick J. Wong 387ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range(cur->bc_mp, 388ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, bno, 0, owner, offset, flags); 389ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 390ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper, &info); 391e7ee96dfSDarrick J. Wong if (error == -ECANCELED) 392ceeb9c83SDarrick J. Wong error = 0; 393ceeb9c83SDarrick J. Wong if (*stat) 394ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 395ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, irec->rm_startblock, 396ceeb9c83SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, 397ceeb9c83SDarrick J. Wong irec->rm_offset, irec->rm_flags); 398ceeb9c83SDarrick J. Wong return error; 399ceeb9c83SDarrick J. Wong } 400ceeb9c83SDarrick J. Wong 401f922cd90SDarrick J. Wong /* 40268c58e9bSDarrick J. Wong * Perform all the relevant owner checks for a removal op. If we're doing an 40368c58e9bSDarrick J. Wong * unknown-owner removal then we have no owner information to check. 40468c58e9bSDarrick J. Wong */ 40568c58e9bSDarrick J. Wong static int 40668c58e9bSDarrick J. Wong xfs_rmap_free_check_owner( 40768c58e9bSDarrick J. Wong struct xfs_mount *mp, 40868c58e9bSDarrick J. Wong uint64_t ltoff, 40968c58e9bSDarrick J. Wong struct xfs_rmap_irec *rec, 41068c58e9bSDarrick J. Wong xfs_filblks_t len, 41168c58e9bSDarrick J. Wong uint64_t owner, 41268c58e9bSDarrick J. Wong uint64_t offset, 41368c58e9bSDarrick J. Wong unsigned int flags) 41468c58e9bSDarrick J. Wong { 41568c58e9bSDarrick J. Wong int error = 0; 41668c58e9bSDarrick J. Wong 41768c58e9bSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN) 41868c58e9bSDarrick J. Wong return 0; 41968c58e9bSDarrick J. Wong 42068c58e9bSDarrick J. Wong /* Make sure the unwritten flag matches. */ 421f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 422f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) != 423f9e03706SDarrick J. Wong (rec->rm_flags & XFS_RMAP_UNWRITTEN))) { 424f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 425f9e03706SDarrick J. Wong goto out; 426f9e03706SDarrick J. Wong } 42768c58e9bSDarrick J. Wong 42868c58e9bSDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 429f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) { 430f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 431f9e03706SDarrick J. Wong goto out; 432f9e03706SDarrick J. Wong } 43368c58e9bSDarrick J. Wong 43468c58e9bSDarrick J. Wong /* Check the offset, if necessary. */ 43568c58e9bSDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(owner)) 43668c58e9bSDarrick J. Wong goto out; 43768c58e9bSDarrick J. Wong 43868c58e9bSDarrick J. Wong if (flags & XFS_RMAP_BMBT_BLOCK) { 439f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 440f9e03706SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) { 441f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 442f9e03706SDarrick J. Wong goto out; 443f9e03706SDarrick J. Wong } 44468c58e9bSDarrick J. Wong } else { 445f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) { 446f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 447f9e03706SDarrick J. Wong goto out; 448f9e03706SDarrick J. Wong } 449f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 450f9e03706SDarrick J. Wong offset + len > ltoff + rec->rm_blockcount)) { 451f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 452f9e03706SDarrick J. Wong goto out; 453f9e03706SDarrick J. Wong } 45468c58e9bSDarrick J. Wong } 45568c58e9bSDarrick J. Wong 45668c58e9bSDarrick J. Wong out: 45768c58e9bSDarrick J. Wong return error; 45868c58e9bSDarrick J. Wong } 45968c58e9bSDarrick J. Wong 46068c58e9bSDarrick J. Wong /* 461f922cd90SDarrick J. Wong * Find the extent in the rmap btree and remove it. 462f922cd90SDarrick J. Wong * 463f922cd90SDarrick J. Wong * The record we find should always be an exact match for the extent that we're 464f922cd90SDarrick J. Wong * looking for, since we insert them into the btree without modification. 465f922cd90SDarrick J. Wong * 466f922cd90SDarrick J. Wong * Special Case #1: when growing the filesystem, we "free" an extent when 467f922cd90SDarrick J. Wong * growing the last AG. This extent is new space and so it is not tracked as 468f922cd90SDarrick J. Wong * used space in the btree. The growfs code will pass in an owner of 469f922cd90SDarrick J. Wong * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this 470f922cd90SDarrick J. Wong * extent. We verify that - the extent lookup result in a record that does not 471f922cd90SDarrick J. Wong * overlap. 472f922cd90SDarrick J. Wong * 473f922cd90SDarrick J. Wong * Special Case #2: EFIs do not record the owner of the extent, so when 474f922cd90SDarrick J. Wong * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap 475f922cd90SDarrick J. Wong * btree to ignore the owner (i.e. wildcard match) so we don't trigger 476f922cd90SDarrick J. Wong * corruption checks during log recovery. 477f922cd90SDarrick J. Wong */ 478f922cd90SDarrick J. Wong STATIC int 479f922cd90SDarrick J. Wong xfs_rmap_unmap( 480f922cd90SDarrick J. Wong struct xfs_btree_cur *cur, 481f922cd90SDarrick J. Wong xfs_agblock_t bno, 482f922cd90SDarrick J. Wong xfs_extlen_t len, 483f922cd90SDarrick J. Wong bool unwritten, 48466e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 485f922cd90SDarrick J. Wong { 486f922cd90SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 487f922cd90SDarrick J. Wong struct xfs_rmap_irec ltrec; 488f922cd90SDarrick J. Wong uint64_t ltoff; 489f922cd90SDarrick J. Wong int error = 0; 490f922cd90SDarrick J. Wong int i; 491f922cd90SDarrick J. Wong uint64_t owner; 492f922cd90SDarrick J. Wong uint64_t offset; 493f922cd90SDarrick J. Wong unsigned int flags; 494f922cd90SDarrick J. Wong bool ignore_off; 495f922cd90SDarrick J. Wong 496f922cd90SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 497f922cd90SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 498f922cd90SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 499f922cd90SDarrick J. Wong if (unwritten) 500f922cd90SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 501f922cd90SDarrick J. Wong trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, 502f922cd90SDarrick J. Wong unwritten, oinfo); 503f922cd90SDarrick J. Wong 504f922cd90SDarrick J. Wong /* 505f922cd90SDarrick J. Wong * We should always have a left record because there's a static record 506f922cd90SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 507f922cd90SDarrick J. Wong * will not ever be removed from the tree. 508f922cd90SDarrick J. Wong */ 509f922cd90SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); 510f922cd90SDarrick J. Wong if (error) 511f922cd90SDarrick J. Wong goto out_error; 512f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 513f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 514f9e03706SDarrick J. Wong goto out_error; 515f9e03706SDarrick J. Wong } 516f922cd90SDarrick J. Wong 517f922cd90SDarrick J. Wong error = xfs_rmap_get_rec(cur, <rec, &i); 518f922cd90SDarrick J. Wong if (error) 519f922cd90SDarrick J. Wong goto out_error; 520f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 521f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 522f9e03706SDarrick J. Wong goto out_error; 523f9e03706SDarrick J. Wong } 524f922cd90SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 525f922cd90SDarrick J. Wong cur->bc_private.a.agno, ltrec.rm_startblock, 526f922cd90SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 527f922cd90SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 528f922cd90SDarrick J. Wong ltoff = ltrec.rm_offset; 529f922cd90SDarrick J. Wong 530f922cd90SDarrick J. Wong /* 531f922cd90SDarrick J. Wong * For growfs, the incoming extent must be beyond the left record we 532f922cd90SDarrick J. Wong * just found as it is new space and won't be used by anyone. This is 533f922cd90SDarrick J. Wong * just a corruption check as we don't actually do anything with this 534f922cd90SDarrick J. Wong * extent. Note that we need to use >= instead of > because it might 535f922cd90SDarrick J. Wong * be the case that the "left" extent goes all the way to EOFS. 536f922cd90SDarrick J. Wong */ 537f922cd90SDarrick J. Wong if (owner == XFS_RMAP_OWN_NULL) { 538f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 539f9e03706SDarrick J. Wong bno < 540f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount)) { 541f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 542f9e03706SDarrick J. Wong goto out_error; 543f9e03706SDarrick J. Wong } 544f922cd90SDarrick J. Wong goto out_done; 545f922cd90SDarrick J. Wong } 546f922cd90SDarrick J. Wong 54733df3a9cSDarrick J. Wong /* 54833df3a9cSDarrick J. Wong * If we're doing an unknown-owner removal for EFI recovery, we expect 54933df3a9cSDarrick J. Wong * to find the full range in the rmapbt or nothing at all. If we 55033df3a9cSDarrick J. Wong * don't find any rmaps overlapping either end of the range, we're 55133df3a9cSDarrick J. Wong * done. Hopefully this means that the EFI creator already queued 55233df3a9cSDarrick J. Wong * (and finished) a RUI to remove the rmap. 55333df3a9cSDarrick J. Wong */ 55433df3a9cSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN && 55533df3a9cSDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 55633df3a9cSDarrick J. Wong struct xfs_rmap_irec rtrec; 55733df3a9cSDarrick J. Wong 55833df3a9cSDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 55933df3a9cSDarrick J. Wong if (error) 56033df3a9cSDarrick J. Wong goto out_error; 56133df3a9cSDarrick J. Wong if (i == 0) 56233df3a9cSDarrick J. Wong goto out_done; 56333df3a9cSDarrick J. Wong error = xfs_rmap_get_rec(cur, &rtrec, &i); 56433df3a9cSDarrick J. Wong if (error) 56533df3a9cSDarrick J. Wong goto out_error; 566f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 567f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 568f9e03706SDarrick J. Wong goto out_error; 569f9e03706SDarrick J. Wong } 57033df3a9cSDarrick J. Wong if (rtrec.rm_startblock >= bno + len) 57133df3a9cSDarrick J. Wong goto out_done; 57233df3a9cSDarrick J. Wong } 57333df3a9cSDarrick J. Wong 574f922cd90SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 575f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 576f9e03706SDarrick J. Wong ltrec.rm_startblock > bno || 577f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount < 578f9e03706SDarrick J. Wong bno + len)) { 579f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 580f9e03706SDarrick J. Wong goto out_error; 581f9e03706SDarrick J. Wong } 582f922cd90SDarrick J. Wong 58368c58e9bSDarrick J. Wong /* Check owner information. */ 584a1f69417SEric Sandeen error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner, 58568c58e9bSDarrick J. Wong offset, flags); 58668c58e9bSDarrick J. Wong if (error) 58768c58e9bSDarrick J. Wong goto out_error; 588f922cd90SDarrick J. Wong 589f922cd90SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 590f922cd90SDarrick J. Wong /* exact match, simply remove the record from rmap tree */ 591f922cd90SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 592f922cd90SDarrick J. Wong ltrec.rm_startblock, ltrec.rm_blockcount, 593f922cd90SDarrick J. Wong ltrec.rm_owner, ltrec.rm_offset, 594f922cd90SDarrick J. Wong ltrec.rm_flags); 595f922cd90SDarrick J. Wong error = xfs_btree_delete(cur, &i); 596f922cd90SDarrick J. Wong if (error) 597f922cd90SDarrick J. Wong goto out_error; 598f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 599f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 600f9e03706SDarrick J. Wong goto out_error; 601f9e03706SDarrick J. Wong } 602f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 603f922cd90SDarrick J. Wong /* 604f922cd90SDarrick J. Wong * overlap left hand side of extent: move the start, trim the 605f922cd90SDarrick J. Wong * length and update the current record. 606f922cd90SDarrick J. Wong * 607f922cd90SDarrick J. Wong * ltbno ltlen 608f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 609f922cd90SDarrick J. Wong * Freeing: |fffffffff| 610f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 611f922cd90SDarrick J. Wong * bno len 612f922cd90SDarrick J. Wong */ 613f922cd90SDarrick J. Wong ltrec.rm_startblock += len; 614f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 615f922cd90SDarrick J. Wong if (!ignore_off) 616f922cd90SDarrick J. Wong ltrec.rm_offset += len; 617f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 618f922cd90SDarrick J. Wong if (error) 619f922cd90SDarrick J. Wong goto out_error; 620f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 621f922cd90SDarrick J. Wong /* 622f922cd90SDarrick J. Wong * overlap right hand side of extent: trim the length and update 623f922cd90SDarrick J. Wong * the current record. 624f922cd90SDarrick J. Wong * 625f922cd90SDarrick J. Wong * ltbno ltlen 626f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 627f922cd90SDarrick J. Wong * Freeing: |fffffffff| 628f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 629f922cd90SDarrick J. Wong * bno len 630f922cd90SDarrick J. Wong */ 631f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 632f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 633f922cd90SDarrick J. Wong if (error) 634f922cd90SDarrick J. Wong goto out_error; 635f922cd90SDarrick J. Wong } else { 636f922cd90SDarrick J. Wong 637f922cd90SDarrick J. Wong /* 638f922cd90SDarrick J. Wong * overlap middle of extent: trim the length of the existing 639f922cd90SDarrick J. Wong * record to the length of the new left-extent size, increment 640f922cd90SDarrick J. Wong * the insertion position so we can insert a new record 641f922cd90SDarrick J. Wong * containing the remaining right-extent space. 642f922cd90SDarrick J. Wong * 643f922cd90SDarrick J. Wong * ltbno ltlen 644f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 645f922cd90SDarrick J. Wong * Freeing: |fffffffff| 646f922cd90SDarrick J. Wong * Result: |rrrrr| |rrrr| 647f922cd90SDarrick J. Wong * bno len 648f922cd90SDarrick J. Wong */ 649f922cd90SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 650f922cd90SDarrick J. Wong 651f922cd90SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 652f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 653f922cd90SDarrick J. Wong if (error) 654f922cd90SDarrick J. Wong goto out_error; 655f922cd90SDarrick J. Wong 656f922cd90SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 657f922cd90SDarrick J. Wong if (error) 658f922cd90SDarrick J. Wong goto out_error; 659f922cd90SDarrick J. Wong 660f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno + len; 661f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount = orig_len - len - 662f922cd90SDarrick J. Wong ltrec.rm_blockcount; 663f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner = ltrec.rm_owner; 664f922cd90SDarrick J. Wong if (ignore_off) 665f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = 0; 666f922cd90SDarrick J. Wong else 667f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = offset + len; 668f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 669f922cd90SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, 670f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock, 671f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount, 672f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner, 673f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset, 674f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags); 675f922cd90SDarrick J. Wong error = xfs_btree_insert(cur, &i); 676f922cd90SDarrick J. Wong if (error) 677f922cd90SDarrick J. Wong goto out_error; 678f922cd90SDarrick J. Wong } 679f922cd90SDarrick J. Wong 680f922cd90SDarrick J. Wong out_done: 681f922cd90SDarrick J. Wong trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, 682f922cd90SDarrick J. Wong unwritten, oinfo); 683f922cd90SDarrick J. Wong out_error: 684f922cd90SDarrick J. Wong if (error) 685f922cd90SDarrick J. Wong trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno, 686f922cd90SDarrick J. Wong error, _RET_IP_); 687f922cd90SDarrick J. Wong return error; 688f922cd90SDarrick J. Wong } 689f922cd90SDarrick J. Wong 690f922cd90SDarrick J. Wong /* 691f922cd90SDarrick J. Wong * Remove a reference to an extent in the rmap btree. 692f922cd90SDarrick J. Wong */ 693673930c3SDarrick J. Wong int 694673930c3SDarrick J. Wong xfs_rmap_free( 695673930c3SDarrick J. Wong struct xfs_trans *tp, 696673930c3SDarrick J. Wong struct xfs_buf *agbp, 697673930c3SDarrick J. Wong xfs_agnumber_t agno, 698673930c3SDarrick J. Wong xfs_agblock_t bno, 699673930c3SDarrick J. Wong xfs_extlen_t len, 70066e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 701673930c3SDarrick J. Wong { 702673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 703f922cd90SDarrick J. Wong struct xfs_btree_cur *cur; 704f922cd90SDarrick J. Wong int error; 705673930c3SDarrick J. Wong 706673930c3SDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 707673930c3SDarrick J. Wong return 0; 708673930c3SDarrick J. Wong 709f922cd90SDarrick J. Wong cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 710f922cd90SDarrick J. Wong 711f922cd90SDarrick J. Wong error = xfs_rmap_unmap(cur, bno, len, false, oinfo); 712f922cd90SDarrick J. Wong 7130b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 714673930c3SDarrick J. Wong return error; 715673930c3SDarrick J. Wong } 716673930c3SDarrick J. Wong 7170a1b0b38SDarrick J. Wong /* 7180a1b0b38SDarrick J. Wong * A mergeable rmap must have the same owner and the same values for 7190a1b0b38SDarrick J. Wong * the unwritten, attr_fork, and bmbt flags. The startblock and 7200a1b0b38SDarrick J. Wong * offset are checked separately. 7210a1b0b38SDarrick J. Wong */ 7220a1b0b38SDarrick J. Wong static bool 7230a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable( 7240a1b0b38SDarrick J. Wong struct xfs_rmap_irec *irec, 7250a1b0b38SDarrick J. Wong uint64_t owner, 7260a1b0b38SDarrick J. Wong unsigned int flags) 7270a1b0b38SDarrick J. Wong { 7280a1b0b38SDarrick J. Wong if (irec->rm_owner == XFS_RMAP_OWN_NULL) 7290a1b0b38SDarrick J. Wong return false; 7300a1b0b38SDarrick J. Wong if (irec->rm_owner != owner) 7310a1b0b38SDarrick J. Wong return false; 7320a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_UNWRITTEN) ^ 7330a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_UNWRITTEN)) 7340a1b0b38SDarrick J. Wong return false; 7350a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_ATTR_FORK) ^ 7360a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_ATTR_FORK)) 7370a1b0b38SDarrick J. Wong return false; 7380a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_BMBT_BLOCK) ^ 7390a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) 7400a1b0b38SDarrick J. Wong return false; 7410a1b0b38SDarrick J. Wong return true; 7420a1b0b38SDarrick J. Wong } 7430a1b0b38SDarrick J. Wong 7440a1b0b38SDarrick J. Wong /* 7450a1b0b38SDarrick J. Wong * When we allocate a new block, the first thing we do is add a reference to 7460a1b0b38SDarrick J. Wong * the extent in the rmap btree. This takes the form of a [agbno, length, 7470a1b0b38SDarrick J. Wong * owner, offset] record. Flags are encoded in the high bits of the offset 7480a1b0b38SDarrick J. Wong * field. 7490a1b0b38SDarrick J. Wong */ 7500a1b0b38SDarrick J. Wong STATIC int 7510a1b0b38SDarrick J. Wong xfs_rmap_map( 7520a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur, 7530a1b0b38SDarrick J. Wong xfs_agblock_t bno, 7540a1b0b38SDarrick J. Wong xfs_extlen_t len, 7550a1b0b38SDarrick J. Wong bool unwritten, 75666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 7570a1b0b38SDarrick J. Wong { 7580a1b0b38SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 7590a1b0b38SDarrick J. Wong struct xfs_rmap_irec ltrec; 7600a1b0b38SDarrick J. Wong struct xfs_rmap_irec gtrec; 7610a1b0b38SDarrick J. Wong int have_gt; 7620a1b0b38SDarrick J. Wong int have_lt; 7630a1b0b38SDarrick J. Wong int error = 0; 7640a1b0b38SDarrick J. Wong int i; 7650a1b0b38SDarrick J. Wong uint64_t owner; 7660a1b0b38SDarrick J. Wong uint64_t offset; 7670a1b0b38SDarrick J. Wong unsigned int flags = 0; 7680a1b0b38SDarrick J. Wong bool ignore_off; 7690a1b0b38SDarrick J. Wong 7700a1b0b38SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 7710a1b0b38SDarrick J. Wong ASSERT(owner != 0); 7720a1b0b38SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 7730a1b0b38SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 7740a1b0b38SDarrick J. Wong if (unwritten) 7750a1b0b38SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 7760a1b0b38SDarrick J. Wong trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 7770a1b0b38SDarrick J. Wong unwritten, oinfo); 77833df3a9cSDarrick J. Wong ASSERT(!xfs_rmap_should_skip_owner_update(oinfo)); 7790a1b0b38SDarrick J. Wong 7800a1b0b38SDarrick J. Wong /* 7810a1b0b38SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 7820a1b0b38SDarrick J. Wong * record for our insertion point. This will also give us the record for 7830a1b0b38SDarrick J. Wong * start block contiguity tests. 7840a1b0b38SDarrick J. Wong */ 7850a1b0b38SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, 7860a1b0b38SDarrick J. Wong &have_lt); 7870a1b0b38SDarrick J. Wong if (error) 7880a1b0b38SDarrick J. Wong goto out_error; 789fa248de9SDarrick J. Wong if (have_lt) { 7900a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, <rec, &have_lt); 7910a1b0b38SDarrick J. Wong if (error) 7920a1b0b38SDarrick J. Wong goto out_error; 793f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_lt != 1)) { 794f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 795f9e03706SDarrick J. Wong goto out_error; 796f9e03706SDarrick J. Wong } 7970a1b0b38SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 7980a1b0b38SDarrick J. Wong cur->bc_private.a.agno, ltrec.rm_startblock, 7990a1b0b38SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 8000a1b0b38SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 8010a1b0b38SDarrick J. Wong 8020a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(<rec, owner, flags)) 8030a1b0b38SDarrick J. Wong have_lt = 0; 804fa248de9SDarrick J. Wong } 8050a1b0b38SDarrick J. Wong 806f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 807f9e03706SDarrick J. Wong have_lt != 0 && 808f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount > bno)) { 809f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 810f9e03706SDarrick J. Wong goto out_error; 811f9e03706SDarrick J. Wong } 8120a1b0b38SDarrick J. Wong 8130a1b0b38SDarrick J. Wong /* 8140a1b0b38SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 8150a1b0b38SDarrick J. Wong * insertion point. This will give us the record for end block 8160a1b0b38SDarrick J. Wong * contiguity tests. 8170a1b0b38SDarrick J. Wong */ 8180a1b0b38SDarrick J. Wong error = xfs_btree_increment(cur, 0, &have_gt); 8190a1b0b38SDarrick J. Wong if (error) 8200a1b0b38SDarrick J. Wong goto out_error; 8210a1b0b38SDarrick J. Wong if (have_gt) { 8220a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 8230a1b0b38SDarrick J. Wong if (error) 8240a1b0b38SDarrick J. Wong goto out_error; 825f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) { 826f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 827f9e03706SDarrick J. Wong goto out_error; 828f9e03706SDarrick J. Wong } 829f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) { 830f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 831f9e03706SDarrick J. Wong goto out_error; 832f9e03706SDarrick J. Wong } 8330a1b0b38SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 8340a1b0b38SDarrick J. Wong cur->bc_private.a.agno, gtrec.rm_startblock, 8350a1b0b38SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 8360a1b0b38SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 8370a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 8380a1b0b38SDarrick J. Wong have_gt = 0; 8390a1b0b38SDarrick J. Wong } 8400a1b0b38SDarrick J. Wong 8410a1b0b38SDarrick J. Wong /* 8420a1b0b38SDarrick J. Wong * Note: cursor currently points one record to the right of ltrec, even 8430a1b0b38SDarrick J. Wong * if there is no record in the tree to the right. 8440a1b0b38SDarrick J. Wong */ 8450a1b0b38SDarrick J. Wong if (have_lt && 8460a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 8470a1b0b38SDarrick J. Wong (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { 8480a1b0b38SDarrick J. Wong /* 8490a1b0b38SDarrick J. Wong * left edge contiguous, merge into left record. 8500a1b0b38SDarrick J. Wong * 8510a1b0b38SDarrick J. Wong * ltbno ltlen 8520a1b0b38SDarrick J. Wong * orig: |ooooooooo| 8530a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8540a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 8550a1b0b38SDarrick J. Wong * bno len 8560a1b0b38SDarrick J. Wong */ 8570a1b0b38SDarrick J. Wong ltrec.rm_blockcount += len; 8580a1b0b38SDarrick J. Wong if (have_gt && 8590a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 8600a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset) && 8610a1b0b38SDarrick J. Wong (unsigned long)ltrec.rm_blockcount + len + 8620a1b0b38SDarrick J. Wong gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { 8630a1b0b38SDarrick J. Wong /* 8640a1b0b38SDarrick J. Wong * right edge also contiguous, delete right record 8650a1b0b38SDarrick J. Wong * and merge into left record. 8660a1b0b38SDarrick J. Wong * 8670a1b0b38SDarrick J. Wong * ltbno ltlen gtbno gtlen 8680a1b0b38SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 8690a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8700a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 8710a1b0b38SDarrick J. Wong */ 8720a1b0b38SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 8730a1b0b38SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 8740a1b0b38SDarrick J. Wong gtrec.rm_startblock, 8750a1b0b38SDarrick J. Wong gtrec.rm_blockcount, 8760a1b0b38SDarrick J. Wong gtrec.rm_owner, 8770a1b0b38SDarrick J. Wong gtrec.rm_offset, 8780a1b0b38SDarrick J. Wong gtrec.rm_flags); 8790a1b0b38SDarrick J. Wong error = xfs_btree_delete(cur, &i); 8800a1b0b38SDarrick J. Wong if (error) 8810a1b0b38SDarrick J. Wong goto out_error; 882f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 883f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 884f9e03706SDarrick J. Wong goto out_error; 885f9e03706SDarrick J. Wong } 8860a1b0b38SDarrick J. Wong } 8870a1b0b38SDarrick J. Wong 8880a1b0b38SDarrick J. Wong /* point the cursor back to the left record and update */ 8890a1b0b38SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &have_gt); 8900a1b0b38SDarrick J. Wong if (error) 8910a1b0b38SDarrick J. Wong goto out_error; 8920a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 8930a1b0b38SDarrick J. Wong if (error) 8940a1b0b38SDarrick J. Wong goto out_error; 8950a1b0b38SDarrick J. Wong } else if (have_gt && 8960a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 8970a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset)) { 8980a1b0b38SDarrick J. Wong /* 8990a1b0b38SDarrick J. Wong * right edge contiguous, merge into right record. 9000a1b0b38SDarrick J. Wong * 9010a1b0b38SDarrick J. Wong * gtbno gtlen 9020a1b0b38SDarrick J. Wong * Orig: |ooooooooo| 9030a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 9040a1b0b38SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 9050a1b0b38SDarrick J. Wong * bno len 9060a1b0b38SDarrick J. Wong */ 9070a1b0b38SDarrick J. Wong gtrec.rm_startblock = bno; 9080a1b0b38SDarrick J. Wong gtrec.rm_blockcount += len; 9090a1b0b38SDarrick J. Wong if (!ignore_off) 9100a1b0b38SDarrick J. Wong gtrec.rm_offset = offset; 9110a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, >rec); 9120a1b0b38SDarrick J. Wong if (error) 9130a1b0b38SDarrick J. Wong goto out_error; 9140a1b0b38SDarrick J. Wong } else { 9150a1b0b38SDarrick J. Wong /* 9160a1b0b38SDarrick J. Wong * no contiguous edge with identical owner, insert 9170a1b0b38SDarrick J. Wong * new record at current cursor position. 9180a1b0b38SDarrick J. Wong */ 9190a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 9200a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 9210a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 9220a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 9230a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 9240a1b0b38SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, 9250a1b0b38SDarrick J. Wong owner, offset, flags); 9260a1b0b38SDarrick J. Wong error = xfs_btree_insert(cur, &i); 9270a1b0b38SDarrick J. Wong if (error) 9280a1b0b38SDarrick J. Wong goto out_error; 929f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 930f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 931f9e03706SDarrick J. Wong goto out_error; 932f9e03706SDarrick J. Wong } 9330a1b0b38SDarrick J. Wong } 9340a1b0b38SDarrick J. Wong 9350a1b0b38SDarrick J. Wong trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, 9360a1b0b38SDarrick J. Wong unwritten, oinfo); 9370a1b0b38SDarrick J. Wong out_error: 9380a1b0b38SDarrick J. Wong if (error) 9390a1b0b38SDarrick J. Wong trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno, 9400a1b0b38SDarrick J. Wong error, _RET_IP_); 9410a1b0b38SDarrick J. Wong return error; 9420a1b0b38SDarrick J. Wong } 9430a1b0b38SDarrick J. Wong 9440a1b0b38SDarrick J. Wong /* 9450a1b0b38SDarrick J. Wong * Add a reference to an extent in the rmap btree. 9460a1b0b38SDarrick J. Wong */ 947673930c3SDarrick J. Wong int 948673930c3SDarrick J. Wong xfs_rmap_alloc( 949673930c3SDarrick J. Wong struct xfs_trans *tp, 950673930c3SDarrick J. Wong struct xfs_buf *agbp, 951673930c3SDarrick J. Wong xfs_agnumber_t agno, 952673930c3SDarrick J. Wong xfs_agblock_t bno, 953673930c3SDarrick J. Wong xfs_extlen_t len, 95466e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 955673930c3SDarrick J. Wong { 956673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 9570a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur; 9580a1b0b38SDarrick J. Wong int error; 959673930c3SDarrick J. Wong 960673930c3SDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 961673930c3SDarrick J. Wong return 0; 962673930c3SDarrick J. Wong 9630a1b0b38SDarrick J. Wong cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 9640a1b0b38SDarrick J. Wong error = xfs_rmap_map(cur, bno, len, false, oinfo); 9650a1b0b38SDarrick J. Wong 9660b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 967673930c3SDarrick J. Wong return error; 968673930c3SDarrick J. Wong } 969c543838aSDarrick J. Wong 970fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG (1 << 0) 971fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG (1 << 1) 972fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING (1 << 2) 973fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING (1 << 3) 974fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID (1 << 6) 975fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID (1 << 7) 976fb7d9267SDarrick J. Wong 977fb7d9267SDarrick J. Wong #define LEFT r[0] 978fb7d9267SDarrick J. Wong #define RIGHT r[1] 979fb7d9267SDarrick J. Wong #define PREV r[2] 980fb7d9267SDarrick J. Wong #define NEW r[3] 981fb7d9267SDarrick J. Wong 982fb7d9267SDarrick J. Wong /* 983fb7d9267SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. 984fb7d9267SDarrick J. Wong * Does not handle overlapping extents. 985fb7d9267SDarrick J. Wong */ 986fb7d9267SDarrick J. Wong STATIC int 987fb7d9267SDarrick J. Wong xfs_rmap_convert( 988fb7d9267SDarrick J. Wong struct xfs_btree_cur *cur, 989fb7d9267SDarrick J. Wong xfs_agblock_t bno, 990fb7d9267SDarrick J. Wong xfs_extlen_t len, 991fb7d9267SDarrick J. Wong bool unwritten, 99266e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 993fb7d9267SDarrick J. Wong { 994fb7d9267SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 995fb7d9267SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 99666e3237eSDarrick J. Wong /* left is 0, right is 1, */ 99766e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 998fb7d9267SDarrick J. Wong uint64_t owner; 999fb7d9267SDarrick J. Wong uint64_t offset; 1000fb7d9267SDarrick J. Wong uint64_t new_endoff; 1001fb7d9267SDarrick J. Wong unsigned int oldext; 1002fb7d9267SDarrick J. Wong unsigned int newext; 1003fb7d9267SDarrick J. Wong unsigned int flags = 0; 1004fb7d9267SDarrick J. Wong int i; 1005fb7d9267SDarrick J. Wong int state = 0; 1006fb7d9267SDarrick J. Wong int error; 1007fb7d9267SDarrick J. Wong 1008fb7d9267SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1009fb7d9267SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 1010fb7d9267SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 1011fb7d9267SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 1012fb7d9267SDarrick J. Wong new_endoff = offset + len; 1013fb7d9267SDarrick J. Wong trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, 1014fb7d9267SDarrick J. Wong unwritten, oinfo); 1015fb7d9267SDarrick J. Wong 1016fb7d9267SDarrick J. Wong /* 1017fb7d9267SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 1018fb7d9267SDarrick J. Wong * record for our insertion point. This will also give us the record for 1019fb7d9267SDarrick J. Wong * start block contiguity tests. 1020fb7d9267SDarrick J. Wong */ 1021fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); 1022fb7d9267SDarrick J. Wong if (error) 1023fb7d9267SDarrick J. Wong goto done; 1024f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1025f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1026f9e03706SDarrick J. Wong goto done; 1027f9e03706SDarrick J. Wong } 1028fb7d9267SDarrick J. Wong 1029fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &PREV, &i); 1030fb7d9267SDarrick J. Wong if (error) 1031fb7d9267SDarrick J. Wong goto done; 1032f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1033f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1034f9e03706SDarrick J. Wong goto done; 1035f9e03706SDarrick J. Wong } 1036fb7d9267SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 1037fb7d9267SDarrick J. Wong cur->bc_private.a.agno, PREV.rm_startblock, 1038fb7d9267SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 1039fb7d9267SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 1040fb7d9267SDarrick J. Wong 1041fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 1042fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 1043fb7d9267SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 1044fb7d9267SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 1045fb7d9267SDarrick J. Wong 1046fb7d9267SDarrick J. Wong /* 1047fb7d9267SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 1048fb7d9267SDarrick J. Wong * extent is being replaced by a newext allocation. 1049fb7d9267SDarrick J. Wong */ 1050fb7d9267SDarrick J. Wong if (PREV.rm_offset == offset) 1051fb7d9267SDarrick J. Wong state |= RMAP_LEFT_FILLING; 1052fb7d9267SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 1053fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 1054fb7d9267SDarrick J. Wong 1055fb7d9267SDarrick J. Wong /* 1056fb7d9267SDarrick J. Wong * Decrement the cursor to see if we have a left-adjacent record to our 1057fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1058fb7d9267SDarrick J. Wong * contiguity tests. 1059fb7d9267SDarrick J. Wong */ 1060fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1061fb7d9267SDarrick J. Wong if (error) 1062fb7d9267SDarrick J. Wong goto done; 1063fb7d9267SDarrick J. Wong if (i) { 1064fb7d9267SDarrick J. Wong state |= RMAP_LEFT_VALID; 1065fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &LEFT, &i); 1066fb7d9267SDarrick J. Wong if (error) 1067fb7d9267SDarrick J. Wong goto done; 1068f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1069f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1070f9e03706SDarrick J. Wong goto done; 1071f9e03706SDarrick J. Wong } 1072f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1073f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount > 1074f9e03706SDarrick J. Wong bno)) { 1075f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1076f9e03706SDarrick J. Wong goto done; 1077f9e03706SDarrick J. Wong } 1078fb7d9267SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 1079fb7d9267SDarrick J. Wong cur->bc_private.a.agno, LEFT.rm_startblock, 1080fb7d9267SDarrick J. Wong LEFT.rm_blockcount, LEFT.rm_owner, 1081fb7d9267SDarrick J. Wong LEFT.rm_offset, LEFT.rm_flags); 1082fb7d9267SDarrick J. Wong if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && 1083fb7d9267SDarrick J. Wong LEFT.rm_offset + LEFT.rm_blockcount == offset && 1084fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&LEFT, owner, newext)) 1085fb7d9267SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 1086fb7d9267SDarrick J. Wong } 1087fb7d9267SDarrick J. Wong 1088fb7d9267SDarrick J. Wong /* 1089fb7d9267SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 1090fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1091fb7d9267SDarrick J. Wong * contiguity tests. 1092fb7d9267SDarrick J. Wong */ 1093fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1094fb7d9267SDarrick J. Wong if (error) 1095fb7d9267SDarrick J. Wong goto done; 1096f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1097f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1098f9e03706SDarrick J. Wong goto done; 1099f9e03706SDarrick J. Wong } 1100fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1101fb7d9267SDarrick J. Wong if (error) 1102fb7d9267SDarrick J. Wong goto done; 1103fb7d9267SDarrick J. Wong if (i) { 1104fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_VALID; 1105fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 1106fb7d9267SDarrick J. Wong if (error) 1107fb7d9267SDarrick J. Wong goto done; 1108f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1109f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1110f9e03706SDarrick J. Wong goto done; 1111f9e03706SDarrick J. Wong } 1112f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { 1113f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1114f9e03706SDarrick J. Wong goto done; 1115f9e03706SDarrick J. Wong } 1116fb7d9267SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 1117fb7d9267SDarrick J. Wong cur->bc_private.a.agno, RIGHT.rm_startblock, 1118fb7d9267SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 1119fb7d9267SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 1120fb7d9267SDarrick J. Wong if (bno + len == RIGHT.rm_startblock && 1121fb7d9267SDarrick J. Wong offset + len == RIGHT.rm_offset && 1122fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 1123fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 1124fb7d9267SDarrick J. Wong } 1125fb7d9267SDarrick J. Wong 1126fb7d9267SDarrick J. Wong /* check that left + prev + right is not too long */ 1127fb7d9267SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1128fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 1129fb7d9267SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1130fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 1131fb7d9267SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 1132fb7d9267SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 1133fb7d9267SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 1134fb7d9267SDarrick J. Wong 1135fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 1136fb7d9267SDarrick J. Wong _RET_IP_); 1137fb7d9267SDarrick J. Wong 1138fb7d9267SDarrick J. Wong /* reset the cursor back to PREV */ 1139fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); 1140fb7d9267SDarrick J. Wong if (error) 1141fb7d9267SDarrick J. Wong goto done; 1142f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1143f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1144f9e03706SDarrick J. Wong goto done; 1145f9e03706SDarrick J. Wong } 1146fb7d9267SDarrick J. Wong 1147fb7d9267SDarrick J. Wong /* 1148fb7d9267SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 1149fb7d9267SDarrick J. Wong */ 1150fb7d9267SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1151fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 1152fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1153fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1154fb7d9267SDarrick J. Wong /* 1155fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1156fb7d9267SDarrick J. Wong * The left and right neighbors are both contiguous with new. 1157fb7d9267SDarrick J. Wong */ 1158fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1159fb7d9267SDarrick J. Wong if (error) 1160fb7d9267SDarrick J. Wong goto done; 1161f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1162f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1163f9e03706SDarrick J. Wong goto done; 1164f9e03706SDarrick J. Wong } 1165fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1166fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1167fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1168fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1169fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1170fb7d9267SDarrick J. Wong if (error) 1171fb7d9267SDarrick J. Wong goto done; 1172f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1173f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1174f9e03706SDarrick J. Wong goto done; 1175f9e03706SDarrick J. Wong } 1176fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1177fb7d9267SDarrick J. Wong if (error) 1178fb7d9267SDarrick J. Wong goto done; 1179f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1180f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1181f9e03706SDarrick J. Wong goto done; 1182f9e03706SDarrick J. Wong } 1183fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1184fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1185fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1186fb7d9267SDarrick J. Wong PREV.rm_flags); 1187fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1188fb7d9267SDarrick J. Wong if (error) 1189fb7d9267SDarrick J. Wong goto done; 1190f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1191f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1192f9e03706SDarrick J. Wong goto done; 1193f9e03706SDarrick J. Wong } 1194fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1195fb7d9267SDarrick J. Wong if (error) 1196fb7d9267SDarrick J. Wong goto done; 1197f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1198f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1199f9e03706SDarrick J. Wong goto done; 1200f9e03706SDarrick J. Wong } 1201fb7d9267SDarrick J. Wong NEW = LEFT; 1202fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 1203fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1204fb7d9267SDarrick J. Wong if (error) 1205fb7d9267SDarrick J. Wong goto done; 1206fb7d9267SDarrick J. Wong break; 1207fb7d9267SDarrick J. Wong 1208fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1209fb7d9267SDarrick J. Wong /* 1210fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1211fb7d9267SDarrick J. Wong * The left neighbor is contiguous, the right is not. 1212fb7d9267SDarrick J. Wong */ 1213fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1214fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1215fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1216fb7d9267SDarrick J. Wong PREV.rm_flags); 1217fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1218fb7d9267SDarrick J. Wong if (error) 1219fb7d9267SDarrick J. Wong goto done; 1220f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1221f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1222f9e03706SDarrick J. Wong goto done; 1223f9e03706SDarrick J. Wong } 1224fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1225fb7d9267SDarrick J. Wong if (error) 1226fb7d9267SDarrick J. Wong goto done; 1227f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1228f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1229f9e03706SDarrick J. Wong goto done; 1230f9e03706SDarrick J. Wong } 1231fb7d9267SDarrick J. Wong NEW = LEFT; 1232fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 1233fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1234fb7d9267SDarrick J. Wong if (error) 1235fb7d9267SDarrick J. Wong goto done; 1236fb7d9267SDarrick J. Wong break; 1237fb7d9267SDarrick J. Wong 1238fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1239fb7d9267SDarrick J. Wong /* 1240fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1241fb7d9267SDarrick J. Wong * The right neighbor is contiguous, the left is not. 1242fb7d9267SDarrick J. Wong */ 1243fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1244fb7d9267SDarrick J. Wong if (error) 1245fb7d9267SDarrick J. Wong goto done; 1246f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1247f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1248f9e03706SDarrick J. Wong goto done; 1249f9e03706SDarrick J. Wong } 1250fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1251fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1252fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1253fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1254fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1255fb7d9267SDarrick J. Wong if (error) 1256fb7d9267SDarrick J. Wong goto done; 1257f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1258f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1259f9e03706SDarrick J. Wong goto done; 1260f9e03706SDarrick J. Wong } 1261fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1262fb7d9267SDarrick J. Wong if (error) 1263fb7d9267SDarrick J. Wong goto done; 1264f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1265f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1266f9e03706SDarrick J. Wong goto done; 1267f9e03706SDarrick J. Wong } 1268fb7d9267SDarrick J. Wong NEW = PREV; 1269fb7d9267SDarrick J. Wong NEW.rm_blockcount = len + RIGHT.rm_blockcount; 1270fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1271fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1272fb7d9267SDarrick J. Wong if (error) 1273fb7d9267SDarrick J. Wong goto done; 1274fb7d9267SDarrick J. Wong break; 1275fb7d9267SDarrick J. Wong 1276fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1277fb7d9267SDarrick J. Wong /* 1278fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1279fb7d9267SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 1280fb7d9267SDarrick J. Wong * the new one. 1281fb7d9267SDarrick J. Wong */ 1282fb7d9267SDarrick J. Wong NEW = PREV; 1283fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1284fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1285fb7d9267SDarrick J. Wong if (error) 1286fb7d9267SDarrick J. Wong goto done; 1287fb7d9267SDarrick J. Wong break; 1288fb7d9267SDarrick J. Wong 1289fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1290fb7d9267SDarrick J. Wong /* 1291fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1292fb7d9267SDarrick J. Wong * The left neighbor is contiguous. 1293fb7d9267SDarrick J. Wong */ 1294fb7d9267SDarrick J. Wong NEW = PREV; 1295fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1296fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1297fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1298fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1299fb7d9267SDarrick J. Wong if (error) 1300fb7d9267SDarrick J. Wong goto done; 1301fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1302fb7d9267SDarrick J. Wong if (error) 1303fb7d9267SDarrick J. Wong goto done; 1304fb7d9267SDarrick J. Wong NEW = LEFT; 1305fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1306fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1307fb7d9267SDarrick J. Wong if (error) 1308fb7d9267SDarrick J. Wong goto done; 1309fb7d9267SDarrick J. Wong break; 1310fb7d9267SDarrick J. Wong 1311fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING: 1312fb7d9267SDarrick J. Wong /* 1313fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1314fb7d9267SDarrick J. Wong * The left neighbor is not contiguous. 1315fb7d9267SDarrick J. Wong */ 1316fb7d9267SDarrick J. Wong NEW = PREV; 1317fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1318fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1319fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1320fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1321fb7d9267SDarrick J. Wong if (error) 1322fb7d9267SDarrick J. Wong goto done; 1323fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1324fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1325fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1326fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1327fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1328fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1329fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, 1330fb7d9267SDarrick J. Wong len, owner, offset, newext); 1331fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1332fb7d9267SDarrick J. Wong if (error) 1333fb7d9267SDarrick J. Wong goto done; 1334f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1335f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1336f9e03706SDarrick J. Wong goto done; 1337f9e03706SDarrick J. Wong } 1338fb7d9267SDarrick J. Wong break; 1339fb7d9267SDarrick J. Wong 1340fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1341fb7d9267SDarrick J. Wong /* 1342fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1343fb7d9267SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 1344fb7d9267SDarrick J. Wong */ 1345fb7d9267SDarrick J. Wong NEW = PREV; 1346fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1347fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1348fb7d9267SDarrick J. Wong if (error) 1349fb7d9267SDarrick J. Wong goto done; 1350fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1351fb7d9267SDarrick J. Wong if (error) 1352fb7d9267SDarrick J. Wong goto done; 1353fb7d9267SDarrick J. Wong NEW = RIGHT; 1354fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1355fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1356fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1357fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1358fb7d9267SDarrick J. Wong if (error) 1359fb7d9267SDarrick J. Wong goto done; 1360fb7d9267SDarrick J. Wong break; 1361fb7d9267SDarrick J. Wong 1362fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING: 1363fb7d9267SDarrick J. Wong /* 1364fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1365fb7d9267SDarrick J. Wong * The right neighbor is not contiguous. 1366fb7d9267SDarrick J. Wong */ 1367fb7d9267SDarrick J. Wong NEW = PREV; 1368fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1369fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1370fb7d9267SDarrick J. Wong if (error) 1371fb7d9267SDarrick J. Wong goto done; 1372fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1373fb7d9267SDarrick J. Wong oldext, &i); 1374fb7d9267SDarrick J. Wong if (error) 1375fb7d9267SDarrick J. Wong goto done; 1376f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) { 1377f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1378f9e03706SDarrick J. Wong goto done; 1379f9e03706SDarrick J. Wong } 1380fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1381fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1382fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1383fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1384fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1385fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1386fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, 1387fb7d9267SDarrick J. Wong len, owner, offset, newext); 1388fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1389fb7d9267SDarrick J. Wong if (error) 1390fb7d9267SDarrick J. Wong goto done; 1391f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1392f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1393f9e03706SDarrick J. Wong goto done; 1394f9e03706SDarrick J. Wong } 1395fb7d9267SDarrick J. Wong break; 1396fb7d9267SDarrick J. Wong 1397fb7d9267SDarrick J. Wong case 0: 1398fb7d9267SDarrick J. Wong /* 1399fb7d9267SDarrick J. Wong * Setting the middle part of a previous oldext extent to 1400fb7d9267SDarrick J. Wong * newext. Contiguity is impossible here. 1401fb7d9267SDarrick J. Wong * One extent becomes three extents. 1402fb7d9267SDarrick J. Wong */ 1403fb7d9267SDarrick J. Wong /* new right extent - oldext */ 1404fb7d9267SDarrick J. Wong NEW.rm_startblock = bno + len; 1405fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1406fb7d9267SDarrick J. Wong NEW.rm_offset = new_endoff; 1407fb7d9267SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 1408fb7d9267SDarrick J. Wong new_endoff; 1409fb7d9267SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 1410fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1411fb7d9267SDarrick J. Wong if (error) 1412fb7d9267SDarrick J. Wong goto done; 1413fb7d9267SDarrick J. Wong /* new left extent - oldext */ 1414fb7d9267SDarrick J. Wong NEW = PREV; 1415fb7d9267SDarrick J. Wong NEW.rm_blockcount = offset - PREV.rm_offset; 1416fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1417fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, 1418fb7d9267SDarrick J. Wong NEW.rm_startblock, NEW.rm_blockcount, 1419fb7d9267SDarrick J. Wong NEW.rm_owner, NEW.rm_offset, 1420fb7d9267SDarrick J. Wong NEW.rm_flags); 1421fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1422fb7d9267SDarrick J. Wong if (error) 1423fb7d9267SDarrick J. Wong goto done; 1424f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1425f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1426f9e03706SDarrick J. Wong goto done; 1427f9e03706SDarrick J. Wong } 1428fb7d9267SDarrick J. Wong /* 1429fb7d9267SDarrick J. Wong * Reset the cursor to the position of the new extent 1430fb7d9267SDarrick J. Wong * we are about to insert as we can't trust it after 1431fb7d9267SDarrick J. Wong * the previous insert. 1432fb7d9267SDarrick J. Wong */ 1433fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1434fb7d9267SDarrick J. Wong oldext, &i); 1435fb7d9267SDarrick J. Wong if (error) 1436fb7d9267SDarrick J. Wong goto done; 1437f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) { 1438f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1439f9e03706SDarrick J. Wong goto done; 1440f9e03706SDarrick J. Wong } 1441fb7d9267SDarrick J. Wong /* new middle extent - newext */ 1442fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; 1443fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags |= newext; 1444fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, 1445fb7d9267SDarrick J. Wong owner, offset, newext); 1446fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1447fb7d9267SDarrick J. Wong if (error) 1448fb7d9267SDarrick J. Wong goto done; 1449f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1450f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1451f9e03706SDarrick J. Wong goto done; 1452f9e03706SDarrick J. Wong } 1453fb7d9267SDarrick J. Wong break; 1454fb7d9267SDarrick J. Wong 1455fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1456fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1457fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 1458fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1459fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1460fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG: 1461fb7d9267SDarrick J. Wong case RMAP_RIGHT_CONTIG: 1462fb7d9267SDarrick J. Wong /* 1463fb7d9267SDarrick J. Wong * These cases are all impossible. 1464fb7d9267SDarrick J. Wong */ 1465fb7d9267SDarrick J. Wong ASSERT(0); 1466fb7d9267SDarrick J. Wong } 1467fb7d9267SDarrick J. Wong 1468fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, 1469fb7d9267SDarrick J. Wong unwritten, oinfo); 1470fb7d9267SDarrick J. Wong done: 1471fb7d9267SDarrick J. Wong if (error) 1472fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 1473fb7d9267SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 1474fb7d9267SDarrick J. Wong return error; 1475fb7d9267SDarrick J. Wong } 1476fb7d9267SDarrick J. Wong 14773f165b33SDarrick J. Wong /* 14783f165b33SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. If there is no 14793f165b33SDarrick J. Wong * possibility of overlapping extents, delegate to the simpler convert 14803f165b33SDarrick J. Wong * function. 14813f165b33SDarrick J. Wong */ 14823f165b33SDarrick J. Wong STATIC int 14833f165b33SDarrick J. Wong xfs_rmap_convert_shared( 14843f165b33SDarrick J. Wong struct xfs_btree_cur *cur, 14853f165b33SDarrick J. Wong xfs_agblock_t bno, 14863f165b33SDarrick J. Wong xfs_extlen_t len, 14873f165b33SDarrick J. Wong bool unwritten, 148866e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 14893f165b33SDarrick J. Wong { 14903f165b33SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 14913f165b33SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 149266e3237eSDarrick J. Wong /* left is 0, right is 1, */ 149366e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 14943f165b33SDarrick J. Wong uint64_t owner; 14953f165b33SDarrick J. Wong uint64_t offset; 14963f165b33SDarrick J. Wong uint64_t new_endoff; 14973f165b33SDarrick J. Wong unsigned int oldext; 14983f165b33SDarrick J. Wong unsigned int newext; 14993f165b33SDarrick J. Wong unsigned int flags = 0; 15003f165b33SDarrick J. Wong int i; 15013f165b33SDarrick J. Wong int state = 0; 15023f165b33SDarrick J. Wong int error; 15033f165b33SDarrick J. Wong 15043f165b33SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 15053f165b33SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 15063f165b33SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 15073f165b33SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 15083f165b33SDarrick J. Wong new_endoff = offset + len; 15093f165b33SDarrick J. Wong trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, 15103f165b33SDarrick J. Wong unwritten, oinfo); 15113f165b33SDarrick J. Wong 15123f165b33SDarrick J. Wong /* 15133f165b33SDarrick J. Wong * For the initial lookup, look for and exact match or the left-adjacent 15143f165b33SDarrick J. Wong * record for our insertion point. This will also give us the record for 15153f165b33SDarrick J. Wong * start block contiguity tests. 15163f165b33SDarrick J. Wong */ 15173f165b33SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 15183f165b33SDarrick J. Wong &PREV, &i); 151952101dfeSDarrick J. Wong if (error) 152052101dfeSDarrick J. Wong goto done; 1521f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1522f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1523f9e03706SDarrick J. Wong goto done; 1524f9e03706SDarrick J. Wong } 15253f165b33SDarrick J. Wong 15263f165b33SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 15273f165b33SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 15283f165b33SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 15293f165b33SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 15303f165b33SDarrick J. Wong 15313f165b33SDarrick J. Wong /* 15323f165b33SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 15333f165b33SDarrick J. Wong * extent is being replaced by a newext allocation. 15343f165b33SDarrick J. Wong */ 15353f165b33SDarrick J. Wong if (PREV.rm_offset == offset) 15363f165b33SDarrick J. Wong state |= RMAP_LEFT_FILLING; 15373f165b33SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 15383f165b33SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 15393f165b33SDarrick J. Wong 15403f165b33SDarrick J. Wong /* Is there a left record that abuts our range? */ 15413f165b33SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, 15423f165b33SDarrick J. Wong &LEFT, &i); 15433f165b33SDarrick J. Wong if (error) 15443f165b33SDarrick J. Wong goto done; 15453f165b33SDarrick J. Wong if (i) { 15463f165b33SDarrick J. Wong state |= RMAP_LEFT_VALID; 1547f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1548f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount > 1549f9e03706SDarrick J. Wong bno)) { 1550f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1551f9e03706SDarrick J. Wong goto done; 1552f9e03706SDarrick J. Wong } 15533f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) 15543f165b33SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 15553f165b33SDarrick J. Wong } 15563f165b33SDarrick J. Wong 15573f165b33SDarrick J. Wong /* Is there a right record that abuts our range? */ 15583f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 15593f165b33SDarrick J. Wong newext, &i); 15603f165b33SDarrick J. Wong if (error) 15613f165b33SDarrick J. Wong goto done; 15623f165b33SDarrick J. Wong if (i) { 15633f165b33SDarrick J. Wong state |= RMAP_RIGHT_VALID; 15643f165b33SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 15653f165b33SDarrick J. Wong if (error) 15663f165b33SDarrick J. Wong goto done; 1567f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1568f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1569f9e03706SDarrick J. Wong goto done; 1570f9e03706SDarrick J. Wong } 1571f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { 1572f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1573f9e03706SDarrick J. Wong goto done; 1574f9e03706SDarrick J. Wong } 15753f165b33SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 15763f165b33SDarrick J. Wong cur->bc_private.a.agno, RIGHT.rm_startblock, 15773f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 15783f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 15793f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 15803f165b33SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 15813f165b33SDarrick J. Wong } 15823f165b33SDarrick J. Wong 15833f165b33SDarrick J. Wong /* check that left + prev + right is not too long */ 15843f165b33SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 15853f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 15863f165b33SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 15873f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 15883f165b33SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 15893f165b33SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 15903f165b33SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 15913f165b33SDarrick J. Wong 15923f165b33SDarrick J. Wong trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 15933f165b33SDarrick J. Wong _RET_IP_); 15943f165b33SDarrick J. Wong /* 15953f165b33SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 15963f165b33SDarrick J. Wong */ 15973f165b33SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 15983f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 15993f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16003f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 16013f165b33SDarrick J. Wong /* 16023f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16033f165b33SDarrick J. Wong * The left and right neighbors are both contiguous with new. 16043f165b33SDarrick J. Wong */ 16053f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 16063f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 16073f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 16083f165b33SDarrick J. Wong if (error) 16093f165b33SDarrick J. Wong goto done; 16103f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 16113f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 16123f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 16133f165b33SDarrick J. Wong if (error) 16143f165b33SDarrick J. Wong goto done; 16153f165b33SDarrick J. Wong NEW = LEFT; 16163f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16173f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16183f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16193f165b33SDarrick J. Wong if (error) 16203f165b33SDarrick J. Wong goto done; 1621f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1622f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1623f9e03706SDarrick J. Wong goto done; 1624f9e03706SDarrick J. Wong } 16253f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 16263f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16273f165b33SDarrick J. Wong if (error) 16283f165b33SDarrick J. Wong goto done; 16293f165b33SDarrick J. Wong break; 16303f165b33SDarrick J. Wong 16313f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 16323f165b33SDarrick J. Wong /* 16333f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16343f165b33SDarrick J. Wong * The left neighbor is contiguous, the right is not. 16353f165b33SDarrick J. Wong */ 16363f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 16373f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 16383f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 16393f165b33SDarrick J. Wong if (error) 16403f165b33SDarrick J. Wong goto done; 16413f165b33SDarrick J. Wong NEW = LEFT; 16423f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16433f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16443f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16453f165b33SDarrick J. Wong if (error) 16463f165b33SDarrick J. Wong goto done; 1647f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1648f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1649f9e03706SDarrick J. Wong goto done; 1650f9e03706SDarrick J. Wong } 16513f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 16523f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16533f165b33SDarrick J. Wong if (error) 16543f165b33SDarrick J. Wong goto done; 16553f165b33SDarrick J. Wong break; 16563f165b33SDarrick J. Wong 16573f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 16583f165b33SDarrick J. Wong /* 16593f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16603f165b33SDarrick J. Wong * The right neighbor is contiguous, the left is not. 16613f165b33SDarrick J. Wong */ 16623f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 16633f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 16643f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 16653f165b33SDarrick J. Wong if (error) 16663f165b33SDarrick J. Wong goto done; 16673f165b33SDarrick J. Wong NEW = PREV; 16683f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16693f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16703f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16713f165b33SDarrick J. Wong if (error) 16723f165b33SDarrick J. Wong goto done; 1673f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1674f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1675f9e03706SDarrick J. Wong goto done; 1676f9e03706SDarrick J. Wong } 16773f165b33SDarrick J. Wong NEW.rm_blockcount += RIGHT.rm_blockcount; 16783f165b33SDarrick J. Wong NEW.rm_flags = RIGHT.rm_flags; 16793f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16803f165b33SDarrick J. Wong if (error) 16813f165b33SDarrick J. Wong goto done; 16823f165b33SDarrick J. Wong break; 16833f165b33SDarrick J. Wong 16843f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 16853f165b33SDarrick J. Wong /* 16863f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16873f165b33SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 16883f165b33SDarrick J. Wong * the new one. 16893f165b33SDarrick J. Wong */ 16903f165b33SDarrick J. Wong NEW = PREV; 16913f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16923f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16933f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16943f165b33SDarrick J. Wong if (error) 16953f165b33SDarrick J. Wong goto done; 1696f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1697f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1698f9e03706SDarrick J. Wong goto done; 1699f9e03706SDarrick J. Wong } 17003f165b33SDarrick J. Wong NEW.rm_flags = newext; 17013f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17023f165b33SDarrick J. Wong if (error) 17033f165b33SDarrick J. Wong goto done; 17043f165b33SDarrick J. Wong break; 17053f165b33SDarrick J. Wong 17063f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 17073f165b33SDarrick J. Wong /* 17083f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 17093f165b33SDarrick J. Wong * The left neighbor is contiguous. 17103f165b33SDarrick J. Wong */ 17113f165b33SDarrick J. Wong NEW = PREV; 17123f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 17133f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17143f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17153f165b33SDarrick J. Wong if (error) 17163f165b33SDarrick J. Wong goto done; 17173f165b33SDarrick J. Wong NEW.rm_offset += len; 17183f165b33SDarrick J. Wong NEW.rm_startblock += len; 17193f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 17203f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 17213f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17223f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17233f165b33SDarrick J. Wong if (error) 17243f165b33SDarrick J. Wong goto done; 17253f165b33SDarrick J. Wong NEW = LEFT; 17263f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17273f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17283f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17293f165b33SDarrick J. Wong if (error) 17303f165b33SDarrick J. Wong goto done; 1731f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1732f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1733f9e03706SDarrick J. Wong goto done; 1734f9e03706SDarrick J. Wong } 17353f165b33SDarrick J. Wong NEW.rm_blockcount += len; 17363f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17373f165b33SDarrick J. Wong if (error) 17383f165b33SDarrick J. Wong goto done; 17393f165b33SDarrick J. Wong break; 17403f165b33SDarrick J. Wong 17413f165b33SDarrick J. Wong case RMAP_LEFT_FILLING: 17423f165b33SDarrick J. Wong /* 17433f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 17443f165b33SDarrick J. Wong * The left neighbor is not contiguous. 17453f165b33SDarrick J. Wong */ 17463f165b33SDarrick J. Wong NEW = PREV; 17473f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 17483f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17493f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17503f165b33SDarrick J. Wong if (error) 17513f165b33SDarrick J. Wong goto done; 17523f165b33SDarrick J. Wong NEW.rm_offset += len; 17533f165b33SDarrick J. Wong NEW.rm_startblock += len; 17543f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 17553f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 17563f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17573f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17583f165b33SDarrick J. Wong if (error) 17593f165b33SDarrick J. Wong goto done; 17603f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 17613f165b33SDarrick J. Wong if (error) 17623f165b33SDarrick J. Wong goto done; 17633f165b33SDarrick J. Wong break; 17643f165b33SDarrick J. Wong 17653f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 17663f165b33SDarrick J. Wong /* 17673f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 17683f165b33SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 17693f165b33SDarrick J. Wong */ 17703f165b33SDarrick J. Wong NEW = PREV; 17713f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17723f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17733f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17743f165b33SDarrick J. Wong if (error) 17753f165b33SDarrick J. Wong goto done; 1776f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1777f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1778f9e03706SDarrick J. Wong goto done; 1779f9e03706SDarrick J. Wong } 17803f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 17813f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17823f165b33SDarrick J. Wong if (error) 17833f165b33SDarrick J. Wong goto done; 17843f165b33SDarrick J. Wong NEW = RIGHT; 17853f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 17863f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17873f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17883f165b33SDarrick J. Wong if (error) 17893f165b33SDarrick J. Wong goto done; 17903f165b33SDarrick J. Wong NEW.rm_offset = offset; 17913f165b33SDarrick J. Wong NEW.rm_startblock = bno; 17923f165b33SDarrick J. Wong NEW.rm_blockcount += len; 17933f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 17943f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17953f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17963f165b33SDarrick J. Wong if (error) 17973f165b33SDarrick J. Wong goto done; 17983f165b33SDarrick J. Wong break; 17993f165b33SDarrick J. Wong 18003f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING: 18013f165b33SDarrick J. Wong /* 18023f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 18033f165b33SDarrick J. Wong * The right neighbor is not contiguous. 18043f165b33SDarrick J. Wong */ 18053f165b33SDarrick J. Wong NEW = PREV; 18063f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18073f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18083f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18093f165b33SDarrick J. Wong if (error) 18103f165b33SDarrick J. Wong goto done; 1811f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1812f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1813f9e03706SDarrick J. Wong goto done; 1814f9e03706SDarrick J. Wong } 18153f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 18163f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18173f165b33SDarrick J. Wong if (error) 18183f165b33SDarrick J. Wong goto done; 18193f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 18203f165b33SDarrick J. Wong if (error) 18213f165b33SDarrick J. Wong goto done; 18223f165b33SDarrick J. Wong break; 18233f165b33SDarrick J. Wong 18243f165b33SDarrick J. Wong case 0: 18253f165b33SDarrick J. Wong /* 18263f165b33SDarrick J. Wong * Setting the middle part of a previous oldext extent to 18273f165b33SDarrick J. Wong * newext. Contiguity is impossible here. 18283f165b33SDarrick J. Wong * One extent becomes three extents. 18293f165b33SDarrick J. Wong */ 18303f165b33SDarrick J. Wong /* new right extent - oldext */ 18313f165b33SDarrick J. Wong NEW.rm_startblock = bno + len; 18323f165b33SDarrick J. Wong NEW.rm_owner = owner; 18333f165b33SDarrick J. Wong NEW.rm_offset = new_endoff; 18343f165b33SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 18353f165b33SDarrick J. Wong new_endoff; 18363f165b33SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 18373f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18383f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 18393f165b33SDarrick J. Wong NEW.rm_flags); 18403f165b33SDarrick J. Wong if (error) 18413f165b33SDarrick J. Wong goto done; 18423f165b33SDarrick J. Wong /* new left extent - oldext */ 18433f165b33SDarrick J. Wong NEW = PREV; 18443f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18453f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18463f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18473f165b33SDarrick J. Wong if (error) 18483f165b33SDarrick J. Wong goto done; 1849f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1850f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1851f9e03706SDarrick J. Wong goto done; 1852f9e03706SDarrick J. Wong } 18533f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 18543f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18553f165b33SDarrick J. Wong if (error) 18563f165b33SDarrick J. Wong goto done; 18573f165b33SDarrick J. Wong /* new middle extent - newext */ 18583f165b33SDarrick J. Wong NEW.rm_startblock = bno; 18593f165b33SDarrick J. Wong NEW.rm_blockcount = len; 18603f165b33SDarrick J. Wong NEW.rm_owner = owner; 18613f165b33SDarrick J. Wong NEW.rm_offset = offset; 18623f165b33SDarrick J. Wong NEW.rm_flags = newext; 18633f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18643f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 18653f165b33SDarrick J. Wong NEW.rm_flags); 18663f165b33SDarrick J. Wong if (error) 18673f165b33SDarrick J. Wong goto done; 18683f165b33SDarrick J. Wong break; 18693f165b33SDarrick J. Wong 18703f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 18713f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 18723f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 18733f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 18743f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 18753f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG: 18763f165b33SDarrick J. Wong case RMAP_RIGHT_CONTIG: 18773f165b33SDarrick J. Wong /* 18783f165b33SDarrick J. Wong * These cases are all impossible. 18793f165b33SDarrick J. Wong */ 18803f165b33SDarrick J. Wong ASSERT(0); 18813f165b33SDarrick J. Wong } 18823f165b33SDarrick J. Wong 18833f165b33SDarrick J. Wong trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, 18843f165b33SDarrick J. Wong unwritten, oinfo); 18853f165b33SDarrick J. Wong done: 18863f165b33SDarrick J. Wong if (error) 18873f165b33SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 18883f165b33SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 18893f165b33SDarrick J. Wong return error; 18903f165b33SDarrick J. Wong } 18913f165b33SDarrick J. Wong 1892fb7d9267SDarrick J. Wong #undef NEW 1893fb7d9267SDarrick J. Wong #undef LEFT 1894fb7d9267SDarrick J. Wong #undef RIGHT 1895fb7d9267SDarrick J. Wong #undef PREV 1896fb7d9267SDarrick J. Wong 1897ceeb9c83SDarrick J. Wong /* 1898ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and unmap it. For rmap extent types that 1899ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1900ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1901ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1902ceeb9c83SDarrick J. Wong * 1903ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1904ceeb9c83SDarrick J. Wong * so we can call the regular _free function. 1905ceeb9c83SDarrick J. Wong */ 1906ceeb9c83SDarrick J. Wong STATIC int 1907ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared( 1908ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1909ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1910ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1911ceeb9c83SDarrick J. Wong bool unwritten, 191266e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1913ceeb9c83SDarrick J. Wong { 1914ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1915ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 1916ceeb9c83SDarrick J. Wong uint64_t ltoff; 1917ceeb9c83SDarrick J. Wong int error = 0; 1918ceeb9c83SDarrick J. Wong int i; 1919ceeb9c83SDarrick J. Wong uint64_t owner; 1920ceeb9c83SDarrick J. Wong uint64_t offset; 1921ceeb9c83SDarrick J. Wong unsigned int flags; 1922ceeb9c83SDarrick J. Wong 1923ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1924ceeb9c83SDarrick J. Wong if (unwritten) 1925ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 1926ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, 1927ceeb9c83SDarrick J. Wong unwritten, oinfo); 1928ceeb9c83SDarrick J. Wong 1929ceeb9c83SDarrick J. Wong /* 1930ceeb9c83SDarrick J. Wong * We should always have a left record because there's a static record 1931ceeb9c83SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 1932ceeb9c83SDarrick J. Wong * will not ever be removed from the tree. 1933ceeb9c83SDarrick J. Wong */ 1934ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 1935ceeb9c83SDarrick J. Wong <rec, &i); 1936ceeb9c83SDarrick J. Wong if (error) 1937ceeb9c83SDarrick J. Wong goto out_error; 1938f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1939f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1940f9e03706SDarrick J. Wong goto out_error; 1941f9e03706SDarrick J. Wong } 1942ceeb9c83SDarrick J. Wong ltoff = ltrec.rm_offset; 1943ceeb9c83SDarrick J. Wong 1944ceeb9c83SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 1945f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1946f9e03706SDarrick J. Wong ltrec.rm_startblock > bno || 1947f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount < 1948f9e03706SDarrick J. Wong bno + len)) { 1949f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1950f9e03706SDarrick J. Wong goto out_error; 1951f9e03706SDarrick J. Wong } 1952ceeb9c83SDarrick J. Wong 1953ceeb9c83SDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 1954f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) { 1955f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1956f9e03706SDarrick J. Wong goto out_error; 1957f9e03706SDarrick J. Wong } 1958ceeb9c83SDarrick J. Wong 1959ceeb9c83SDarrick J. Wong /* Make sure the unwritten flag matches. */ 1960f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1961f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) != 1962f9e03706SDarrick J. Wong (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) { 1963f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1964f9e03706SDarrick J. Wong goto out_error; 1965f9e03706SDarrick J. Wong } 1966ceeb9c83SDarrick J. Wong 1967ceeb9c83SDarrick J. Wong /* Check the offset. */ 1968f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) { 1969f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1970f9e03706SDarrick J. Wong goto out_error; 1971f9e03706SDarrick J. Wong } 1972f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) { 1973f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1974f9e03706SDarrick J. Wong goto out_error; 1975f9e03706SDarrick J. Wong } 1976ceeb9c83SDarrick J. Wong 1977ceeb9c83SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 1978ceeb9c83SDarrick J. Wong /* Exact match, simply remove the record from rmap tree. */ 1979ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 1980ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1981ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1982ceeb9c83SDarrick J. Wong if (error) 1983ceeb9c83SDarrick J. Wong goto out_error; 1984ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 1985ceeb9c83SDarrick J. Wong /* 1986ceeb9c83SDarrick J. Wong * Overlap left hand side of extent: move the start, trim the 1987ceeb9c83SDarrick J. Wong * length and update the current record. 1988ceeb9c83SDarrick J. Wong * 1989ceeb9c83SDarrick J. Wong * ltbno ltlen 1990ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1991ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1992ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 1993ceeb9c83SDarrick J. Wong * bno len 1994ceeb9c83SDarrick J. Wong */ 1995ceeb9c83SDarrick J. Wong 1996ceeb9c83SDarrick J. Wong /* Delete prev rmap. */ 1997ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 1998ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1999ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2000ceeb9c83SDarrick J. Wong if (error) 2001ceeb9c83SDarrick J. Wong goto out_error; 2002ceeb9c83SDarrick J. Wong 2003ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset. */ 2004ceeb9c83SDarrick J. Wong ltrec.rm_startblock += len; 2005ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 2006ceeb9c83SDarrick J. Wong ltrec.rm_offset += len; 2007ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, ltrec.rm_startblock, 2008ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2009ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2010ceeb9c83SDarrick J. Wong if (error) 2011ceeb9c83SDarrick J. Wong goto out_error; 2012ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 2013ceeb9c83SDarrick J. Wong /* 2014ceeb9c83SDarrick J. Wong * Overlap right hand side of extent: trim the length and 2015ceeb9c83SDarrick J. Wong * update the current record. 2016ceeb9c83SDarrick J. Wong * 2017ceeb9c83SDarrick J. Wong * ltbno ltlen 2018ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2019ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2020ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 2021ceeb9c83SDarrick J. Wong * bno len 2022ceeb9c83SDarrick J. Wong */ 2023ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2024ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2025ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2026ceeb9c83SDarrick J. Wong if (error) 2027ceeb9c83SDarrick J. Wong goto out_error; 2028f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2029f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2030f9e03706SDarrick J. Wong goto out_error; 2031f9e03706SDarrick J. Wong } 2032ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 2033ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2034ceeb9c83SDarrick J. Wong if (error) 2035ceeb9c83SDarrick J. Wong goto out_error; 2036ceeb9c83SDarrick J. Wong } else { 2037ceeb9c83SDarrick J. Wong /* 2038ceeb9c83SDarrick J. Wong * Overlap middle of extent: trim the length of the existing 2039ceeb9c83SDarrick J. Wong * record to the length of the new left-extent size, increment 2040ceeb9c83SDarrick J. Wong * the insertion position so we can insert a new record 2041ceeb9c83SDarrick J. Wong * containing the remaining right-extent space. 2042ceeb9c83SDarrick J. Wong * 2043ceeb9c83SDarrick J. Wong * ltbno ltlen 2044ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2045ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2046ceeb9c83SDarrick J. Wong * Result: |rrrrr| |rrrr| 2047ceeb9c83SDarrick J. Wong * bno len 2048ceeb9c83SDarrick J. Wong */ 2049ceeb9c83SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 2050ceeb9c83SDarrick J. Wong 2051ceeb9c83SDarrick J. Wong /* Shrink the left side of the rmap */ 2052ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2053ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2054ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2055ceeb9c83SDarrick J. Wong if (error) 2056ceeb9c83SDarrick J. Wong goto out_error; 2057f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2058f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2059f9e03706SDarrick J. Wong goto out_error; 2060f9e03706SDarrick J. Wong } 2061ceeb9c83SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 2062ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2063ceeb9c83SDarrick J. Wong if (error) 2064ceeb9c83SDarrick J. Wong goto out_error; 2065ceeb9c83SDarrick J. Wong 2066ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset */ 2067ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno + len, 2068ceeb9c83SDarrick J. Wong orig_len - len - ltrec.rm_blockcount, 2069ceeb9c83SDarrick J. Wong ltrec.rm_owner, offset + len, 2070ceeb9c83SDarrick J. Wong ltrec.rm_flags); 2071ceeb9c83SDarrick J. Wong if (error) 2072ceeb9c83SDarrick J. Wong goto out_error; 2073ceeb9c83SDarrick J. Wong } 2074ceeb9c83SDarrick J. Wong 2075ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, 2076ceeb9c83SDarrick J. Wong unwritten, oinfo); 2077ceeb9c83SDarrick J. Wong out_error: 2078ceeb9c83SDarrick J. Wong if (error) 2079ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_error(cur->bc_mp, 2080ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 2081ceeb9c83SDarrick J. Wong return error; 2082ceeb9c83SDarrick J. Wong } 2083ceeb9c83SDarrick J. Wong 2084ceeb9c83SDarrick J. Wong /* 2085ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and map it. For rmap extent types that 2086ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 2087ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 2088ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 2089ceeb9c83SDarrick J. Wong * 2090ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 2091ceeb9c83SDarrick J. Wong * so we can call the regular _alloc function. 2092ceeb9c83SDarrick J. Wong */ 2093ceeb9c83SDarrick J. Wong STATIC int 2094ceeb9c83SDarrick J. Wong xfs_rmap_map_shared( 2095ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 2096ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 2097ceeb9c83SDarrick J. Wong xfs_extlen_t len, 2098ceeb9c83SDarrick J. Wong bool unwritten, 209966e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 2100ceeb9c83SDarrick J. Wong { 2101ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 2102ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 2103ceeb9c83SDarrick J. Wong struct xfs_rmap_irec gtrec; 2104ceeb9c83SDarrick J. Wong int have_gt; 2105ceeb9c83SDarrick J. Wong int have_lt; 2106ceeb9c83SDarrick J. Wong int error = 0; 2107ceeb9c83SDarrick J. Wong int i; 2108ceeb9c83SDarrick J. Wong uint64_t owner; 2109ceeb9c83SDarrick J. Wong uint64_t offset; 2110ceeb9c83SDarrick J. Wong unsigned int flags = 0; 2111ceeb9c83SDarrick J. Wong 2112ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2113ceeb9c83SDarrick J. Wong if (unwritten) 2114ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 2115ceeb9c83SDarrick J. Wong trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 2116ceeb9c83SDarrick J. Wong unwritten, oinfo); 2117ceeb9c83SDarrick J. Wong 2118ceeb9c83SDarrick J. Wong /* Is there a left record that abuts our range? */ 2119ceeb9c83SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, 2120ceeb9c83SDarrick J. Wong <rec, &have_lt); 2121ceeb9c83SDarrick J. Wong if (error) 2122ceeb9c83SDarrick J. Wong goto out_error; 2123ceeb9c83SDarrick J. Wong if (have_lt && 2124ceeb9c83SDarrick J. Wong !xfs_rmap_is_mergeable(<rec, owner, flags)) 2125ceeb9c83SDarrick J. Wong have_lt = 0; 2126ceeb9c83SDarrick J. Wong 2127ceeb9c83SDarrick J. Wong /* Is there a right record that abuts our range? */ 2128ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 2129ceeb9c83SDarrick J. Wong flags, &have_gt); 2130ceeb9c83SDarrick J. Wong if (error) 2131ceeb9c83SDarrick J. Wong goto out_error; 2132ceeb9c83SDarrick J. Wong if (have_gt) { 2133ceeb9c83SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 2134ceeb9c83SDarrick J. Wong if (error) 2135ceeb9c83SDarrick J. Wong goto out_error; 2136f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) { 2137f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2138f9e03706SDarrick J. Wong goto out_error; 2139f9e03706SDarrick J. Wong } 2140ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 2141ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, gtrec.rm_startblock, 2142ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2143ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2144ceeb9c83SDarrick J. Wong 2145ceeb9c83SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 2146ceeb9c83SDarrick J. Wong have_gt = 0; 2147ceeb9c83SDarrick J. Wong } 2148ceeb9c83SDarrick J. Wong 2149ceeb9c83SDarrick J. Wong if (have_lt && 2150ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 2151ceeb9c83SDarrick J. Wong ltrec.rm_offset + ltrec.rm_blockcount == offset) { 2152ceeb9c83SDarrick J. Wong /* 2153ceeb9c83SDarrick J. Wong * Left edge contiguous, merge into left record. 2154ceeb9c83SDarrick J. Wong * 2155ceeb9c83SDarrick J. Wong * ltbno ltlen 2156ceeb9c83SDarrick J. Wong * orig: |ooooooooo| 2157ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2158ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 2159ceeb9c83SDarrick J. Wong * bno len 2160ceeb9c83SDarrick J. Wong */ 2161ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += len; 2162ceeb9c83SDarrick J. Wong if (have_gt && 2163ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 2164ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 2165ceeb9c83SDarrick J. Wong /* 2166ceeb9c83SDarrick J. Wong * Right edge also contiguous, delete right record 2167ceeb9c83SDarrick J. Wong * and merge into left record. 2168ceeb9c83SDarrick J. Wong * 2169ceeb9c83SDarrick J. Wong * ltbno ltlen gtbno gtlen 2170ceeb9c83SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 2171ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2172ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 2173ceeb9c83SDarrick J. Wong */ 2174ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 2175ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2176ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2177ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2178ceeb9c83SDarrick J. Wong if (error) 2179ceeb9c83SDarrick J. Wong goto out_error; 2180ceeb9c83SDarrick J. Wong } 2181ceeb9c83SDarrick J. Wong 2182ceeb9c83SDarrick J. Wong /* Point the cursor back to the left record and update. */ 2183ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2184ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2185ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2186ceeb9c83SDarrick J. Wong if (error) 2187ceeb9c83SDarrick J. Wong goto out_error; 2188f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2189f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2190f9e03706SDarrick J. Wong goto out_error; 2191f9e03706SDarrick J. Wong } 2192ceeb9c83SDarrick J. Wong 2193ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2194ceeb9c83SDarrick J. Wong if (error) 2195ceeb9c83SDarrick J. Wong goto out_error; 2196ceeb9c83SDarrick J. Wong } else if (have_gt && 2197ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 2198ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 2199ceeb9c83SDarrick J. Wong /* 2200ceeb9c83SDarrick J. Wong * Right edge contiguous, merge into right record. 2201ceeb9c83SDarrick J. Wong * 2202ceeb9c83SDarrick J. Wong * gtbno gtlen 2203ceeb9c83SDarrick J. Wong * Orig: |ooooooooo| 2204ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2205ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 2206ceeb9c83SDarrick J. Wong * bno len 2207ceeb9c83SDarrick J. Wong */ 2208ceeb9c83SDarrick J. Wong /* Delete the old record. */ 2209ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2210ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2211ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2212ceeb9c83SDarrick J. Wong if (error) 2213ceeb9c83SDarrick J. Wong goto out_error; 2214ceeb9c83SDarrick J. Wong 2215ceeb9c83SDarrick J. Wong /* Move the start and re-add it. */ 2216ceeb9c83SDarrick J. Wong gtrec.rm_startblock = bno; 2217ceeb9c83SDarrick J. Wong gtrec.rm_blockcount += len; 2218ceeb9c83SDarrick J. Wong gtrec.rm_offset = offset; 2219ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, gtrec.rm_startblock, 2220ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2221ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2222ceeb9c83SDarrick J. Wong if (error) 2223ceeb9c83SDarrick J. Wong goto out_error; 2224ceeb9c83SDarrick J. Wong } else { 2225ceeb9c83SDarrick J. Wong /* 2226ceeb9c83SDarrick J. Wong * No contiguous edge with identical owner, insert 2227ceeb9c83SDarrick J. Wong * new record at current cursor position. 2228ceeb9c83SDarrick J. Wong */ 2229ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); 2230ceeb9c83SDarrick J. Wong if (error) 2231ceeb9c83SDarrick J. Wong goto out_error; 2232ceeb9c83SDarrick J. Wong } 2233ceeb9c83SDarrick J. Wong 2234ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, 2235ceeb9c83SDarrick J. Wong unwritten, oinfo); 2236ceeb9c83SDarrick J. Wong out_error: 2237ceeb9c83SDarrick J. Wong if (error) 2238ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_error(cur->bc_mp, 2239ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 2240ceeb9c83SDarrick J. Wong return error; 2241ceeb9c83SDarrick J. Wong } 2242ceeb9c83SDarrick J. Wong 22434d4f86b4SDarrick J. Wong /* Insert a raw rmap into the rmapbt. */ 22444d4f86b4SDarrick J. Wong int 22454d4f86b4SDarrick J. Wong xfs_rmap_map_raw( 22464d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 22474d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rmap) 22484d4f86b4SDarrick J. Wong { 22494d4f86b4SDarrick J. Wong struct xfs_owner_info oinfo; 22504d4f86b4SDarrick J. Wong 22514d4f86b4SDarrick J. Wong oinfo.oi_owner = rmap->rm_owner; 22524d4f86b4SDarrick J. Wong oinfo.oi_offset = rmap->rm_offset; 22534d4f86b4SDarrick J. Wong oinfo.oi_flags = 0; 22544d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_ATTR_FORK) 22554d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK; 22564d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK) 22574d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; 22584d4f86b4SDarrick J. Wong 22594d4f86b4SDarrick J. Wong if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner)) 22604d4f86b4SDarrick J. Wong return xfs_rmap_map(cur, rmap->rm_startblock, 22614d4f86b4SDarrick J. Wong rmap->rm_blockcount, 22624d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 22634d4f86b4SDarrick J. Wong &oinfo); 22644d4f86b4SDarrick J. Wong 22654d4f86b4SDarrick J. Wong return xfs_rmap_map_shared(cur, rmap->rm_startblock, 22664d4f86b4SDarrick J. Wong rmap->rm_blockcount, 22674d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 22684d4f86b4SDarrick J. Wong &oinfo); 22694d4f86b4SDarrick J. Wong } 22704d4f86b4SDarrick J. Wong 2271c543838aSDarrick J. Wong struct xfs_rmap_query_range_info { 2272c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn; 2273c543838aSDarrick J. Wong void *priv; 2274c543838aSDarrick J. Wong }; 2275c543838aSDarrick J. Wong 2276c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */ 2277c543838aSDarrick J. Wong STATIC int 2278c543838aSDarrick J. Wong xfs_rmap_query_range_helper( 2279c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2280c543838aSDarrick J. Wong union xfs_btree_rec *rec, 2281c543838aSDarrick J. Wong void *priv) 2282c543838aSDarrick J. Wong { 2283c543838aSDarrick J. Wong struct xfs_rmap_query_range_info *query = priv; 2284c543838aSDarrick J. Wong struct xfs_rmap_irec irec; 2285c543838aSDarrick J. Wong int error; 2286c543838aSDarrick J. Wong 2287c543838aSDarrick J. Wong error = xfs_rmap_btrec_to_irec(rec, &irec); 2288c543838aSDarrick J. Wong if (error) 2289c543838aSDarrick J. Wong return error; 2290c543838aSDarrick J. Wong return query->fn(cur, &irec, query->priv); 2291c543838aSDarrick J. Wong } 2292c543838aSDarrick J. Wong 2293c543838aSDarrick J. Wong /* Find all rmaps between two keys. */ 2294c543838aSDarrick J. Wong int 2295c543838aSDarrick J. Wong xfs_rmap_query_range( 2296c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2297c543838aSDarrick J. Wong struct xfs_rmap_irec *low_rec, 2298c543838aSDarrick J. Wong struct xfs_rmap_irec *high_rec, 2299c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2300c543838aSDarrick J. Wong void *priv) 2301c543838aSDarrick J. Wong { 2302c543838aSDarrick J. Wong union xfs_btree_irec low_brec; 2303c543838aSDarrick J. Wong union xfs_btree_irec high_brec; 2304c543838aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2305c543838aSDarrick J. Wong 2306c543838aSDarrick J. Wong low_brec.r = *low_rec; 2307c543838aSDarrick J. Wong high_brec.r = *high_rec; 2308c543838aSDarrick J. Wong query.priv = priv; 2309c543838aSDarrick J. Wong query.fn = fn; 2310c543838aSDarrick J. Wong return xfs_btree_query_range(cur, &low_brec, &high_brec, 2311c543838aSDarrick J. Wong xfs_rmap_query_range_helper, &query); 2312e9a2599aSDarrick J. Wong } 2313e9a2599aSDarrick J. Wong 2314e9a2599aSDarrick J. Wong /* Find all rmaps. */ 2315e9a2599aSDarrick J. Wong int 2316e9a2599aSDarrick J. Wong xfs_rmap_query_all( 2317e9a2599aSDarrick J. Wong struct xfs_btree_cur *cur, 2318e9a2599aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2319e9a2599aSDarrick J. Wong void *priv) 2320e9a2599aSDarrick J. Wong { 2321e9a2599aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2322e9a2599aSDarrick J. Wong 2323e9a2599aSDarrick J. Wong query.priv = priv; 2324e9a2599aSDarrick J. Wong query.fn = fn; 2325e9a2599aSDarrick J. Wong return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query); 2326c543838aSDarrick J. Wong } 23279c194644SDarrick J. Wong 23289c194644SDarrick J. Wong /* Clean up after calling xfs_rmap_finish_one. */ 23299c194644SDarrick J. Wong void 23309c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup( 23319c194644SDarrick J. Wong struct xfs_trans *tp, 23329c194644SDarrick J. Wong struct xfs_btree_cur *rcur, 23339c194644SDarrick J. Wong int error) 23349c194644SDarrick J. Wong { 23359c194644SDarrick J. Wong struct xfs_buf *agbp; 23369c194644SDarrick J. Wong 23379c194644SDarrick J. Wong if (rcur == NULL) 23389c194644SDarrick J. Wong return; 23399c194644SDarrick J. Wong agbp = rcur->bc_private.a.agbp; 23400b04b6b8SDarrick J. Wong xfs_btree_del_cursor(rcur, error); 23419c194644SDarrick J. Wong if (error) 23429c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 23439c194644SDarrick J. Wong } 23449c194644SDarrick J. Wong 23459c194644SDarrick J. Wong /* 23469c194644SDarrick J. Wong * Process one of the deferred rmap operations. We pass back the 23479c194644SDarrick J. Wong * btree cursor to maintain our lock on the rmapbt between calls. 23489c194644SDarrick J. Wong * This saves time and eliminates a buffer deadlock between the 23499c194644SDarrick J. Wong * superblock and the AGF because we'll always grab them in the same 23509c194644SDarrick J. Wong * order. 23519c194644SDarrick J. Wong */ 23529c194644SDarrick J. Wong int 23539c194644SDarrick J. Wong xfs_rmap_finish_one( 23549c194644SDarrick J. Wong struct xfs_trans *tp, 23559c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2356c8ce540dSDarrick J. Wong uint64_t owner, 23579c194644SDarrick J. Wong int whichfork, 23589c194644SDarrick J. Wong xfs_fileoff_t startoff, 23599c194644SDarrick J. Wong xfs_fsblock_t startblock, 23609c194644SDarrick J. Wong xfs_filblks_t blockcount, 23619c194644SDarrick J. Wong xfs_exntst_t state, 23629c194644SDarrick J. Wong struct xfs_btree_cur **pcur) 23639c194644SDarrick J. Wong { 23649c194644SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 23659c194644SDarrick J. Wong struct xfs_btree_cur *rcur; 23669c194644SDarrick J. Wong struct xfs_buf *agbp = NULL; 23679c194644SDarrick J. Wong int error = 0; 23689c194644SDarrick J. Wong xfs_agnumber_t agno; 23699c194644SDarrick J. Wong struct xfs_owner_info oinfo; 23709c194644SDarrick J. Wong xfs_agblock_t bno; 23719c194644SDarrick J. Wong bool unwritten; 23729c194644SDarrick J. Wong 23739c194644SDarrick J. Wong agno = XFS_FSB_TO_AGNO(mp, startblock); 23749c194644SDarrick J. Wong ASSERT(agno != NULLAGNUMBER); 23759c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(mp, startblock); 23769c194644SDarrick J. Wong 23779c194644SDarrick J. Wong trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, 23789c194644SDarrick J. Wong startoff, blockcount, state); 23799c194644SDarrick J. Wong 23809c194644SDarrick J. Wong if (XFS_TEST_ERROR(false, mp, 23819e24cfd0SDarrick J. Wong XFS_ERRTAG_RMAP_FINISH_ONE)) 23829c194644SDarrick J. Wong return -EIO; 23839c194644SDarrick J. Wong 23849c194644SDarrick J. Wong /* 23859c194644SDarrick J. Wong * If we haven't gotten a cursor or the cursor AG doesn't match 23869c194644SDarrick J. Wong * the startblock, get one now. 23879c194644SDarrick J. Wong */ 23889c194644SDarrick J. Wong rcur = *pcur; 23899c194644SDarrick J. Wong if (rcur != NULL && rcur->bc_private.a.agno != agno) { 23909c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup(tp, rcur, 0); 23919c194644SDarrick J. Wong rcur = NULL; 23929c194644SDarrick J. Wong *pcur = NULL; 23939c194644SDarrick J. Wong } 23949c194644SDarrick J. Wong if (rcur == NULL) { 23959c194644SDarrick J. Wong /* 23969c194644SDarrick J. Wong * Refresh the freelist before we start changing the 23979c194644SDarrick J. Wong * rmapbt, because a shape change could cause us to 23989c194644SDarrick J. Wong * allocate blocks. 23999c194644SDarrick J. Wong */ 24009c194644SDarrick J. Wong error = xfs_free_extent_fix_freelist(tp, agno, &agbp); 24019c194644SDarrick J. Wong if (error) 24029c194644SDarrick J. Wong return error; 24039c194644SDarrick J. Wong if (!agbp) 24049c194644SDarrick J. Wong return -EFSCORRUPTED; 24059c194644SDarrick J. Wong 24069c194644SDarrick J. Wong rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 24079c194644SDarrick J. Wong if (!rcur) { 24089c194644SDarrick J. Wong error = -ENOMEM; 24099c194644SDarrick J. Wong goto out_cur; 24109c194644SDarrick J. Wong } 24119c194644SDarrick J. Wong } 24129c194644SDarrick J. Wong *pcur = rcur; 24139c194644SDarrick J. Wong 24149c194644SDarrick J. Wong xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff); 24159c194644SDarrick J. Wong unwritten = state == XFS_EXT_UNWRITTEN; 24169c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock); 24179c194644SDarrick J. Wong 24189c194644SDarrick J. Wong switch (type) { 24199c194644SDarrick J. Wong case XFS_RMAP_ALLOC: 24209c194644SDarrick J. Wong case XFS_RMAP_MAP: 24219c194644SDarrick J. Wong error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); 24229c194644SDarrick J. Wong break; 2423ceeb9c83SDarrick J. Wong case XFS_RMAP_MAP_SHARED: 2424ceeb9c83SDarrick J. Wong error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten, 2425ceeb9c83SDarrick J. Wong &oinfo); 2426ceeb9c83SDarrick J. Wong break; 24279c194644SDarrick J. Wong case XFS_RMAP_FREE: 24289c194644SDarrick J. Wong case XFS_RMAP_UNMAP: 24299c194644SDarrick J. Wong error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, 24309c194644SDarrick J. Wong &oinfo); 24319c194644SDarrick J. Wong break; 2432ceeb9c83SDarrick J. Wong case XFS_RMAP_UNMAP_SHARED: 2433ceeb9c83SDarrick J. Wong error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten, 2434ceeb9c83SDarrick J. Wong &oinfo); 2435ceeb9c83SDarrick J. Wong break; 24369c194644SDarrick J. Wong case XFS_RMAP_CONVERT: 24379c194644SDarrick J. Wong error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, 24389c194644SDarrick J. Wong &oinfo); 24399c194644SDarrick J. Wong break; 24403f165b33SDarrick J. Wong case XFS_RMAP_CONVERT_SHARED: 24413f165b33SDarrick J. Wong error = xfs_rmap_convert_shared(rcur, bno, blockcount, 24423f165b33SDarrick J. Wong !unwritten, &oinfo); 24433f165b33SDarrick J. Wong break; 24449c194644SDarrick J. Wong default: 24459c194644SDarrick J. Wong ASSERT(0); 24469c194644SDarrick J. Wong error = -EFSCORRUPTED; 24479c194644SDarrick J. Wong } 24489c194644SDarrick J. Wong return error; 24499c194644SDarrick J. Wong 24509c194644SDarrick J. Wong out_cur: 24519c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 24529c194644SDarrick J. Wong 24539c194644SDarrick J. Wong return error; 24549c194644SDarrick J. Wong } 24559c194644SDarrick J. Wong 24569c194644SDarrick J. Wong /* 24579c194644SDarrick J. Wong * Don't defer an rmap if we aren't an rmap filesystem. 24589c194644SDarrick J. Wong */ 24599c194644SDarrick J. Wong static bool 24609c194644SDarrick J. Wong xfs_rmap_update_is_needed( 24613993baebSDarrick J. Wong struct xfs_mount *mp, 24623993baebSDarrick J. Wong int whichfork) 24639c194644SDarrick J. Wong { 24643993baebSDarrick J. Wong return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK; 24659c194644SDarrick J. Wong } 24669c194644SDarrick J. Wong 24679c194644SDarrick J. Wong /* 24689c194644SDarrick J. Wong * Record a rmap intent; the list is kept sorted first by AG and then by 24699c194644SDarrick J. Wong * increasing age. 24709c194644SDarrick J. Wong */ 2471bc46ac64SDarrick J. Wong static void 24729c194644SDarrick J. Wong __xfs_rmap_add( 24730f37d178SBrian Foster struct xfs_trans *tp, 24749c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2475c8ce540dSDarrick J. Wong uint64_t owner, 24769c194644SDarrick J. Wong int whichfork, 24779c194644SDarrick J. Wong struct xfs_bmbt_irec *bmap) 24789c194644SDarrick J. Wong { 24799c194644SDarrick J. Wong struct xfs_rmap_intent *ri; 24809c194644SDarrick J. Wong 24810f37d178SBrian Foster trace_xfs_rmap_defer(tp->t_mountp, 24820f37d178SBrian Foster XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock), 24839c194644SDarrick J. Wong type, 24840f37d178SBrian Foster XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock), 24859c194644SDarrick J. Wong owner, whichfork, 24869c194644SDarrick J. Wong bmap->br_startoff, 24879c194644SDarrick J. Wong bmap->br_blockcount, 24889c194644SDarrick J. Wong bmap->br_state); 24899c194644SDarrick J. Wong 2490707e0ddaSTetsuo Handa ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS); 24919c194644SDarrick J. Wong INIT_LIST_HEAD(&ri->ri_list); 24929c194644SDarrick J. Wong ri->ri_type = type; 24939c194644SDarrick J. Wong ri->ri_owner = owner; 24949c194644SDarrick J. Wong ri->ri_whichfork = whichfork; 24959c194644SDarrick J. Wong ri->ri_bmap = *bmap; 24969c194644SDarrick J. Wong 24970f37d178SBrian Foster xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); 24989c194644SDarrick J. Wong } 24999c194644SDarrick J. Wong 25009c194644SDarrick J. Wong /* Map an extent into a file. */ 2501bc46ac64SDarrick J. Wong void 25029c194644SDarrick J. Wong xfs_rmap_map_extent( 25030f37d178SBrian Foster struct xfs_trans *tp, 25049c194644SDarrick J. Wong struct xfs_inode *ip, 25059c194644SDarrick J. Wong int whichfork, 25069c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25079c194644SDarrick J. Wong { 25080f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2509bc46ac64SDarrick J. Wong return; 25109c194644SDarrick J. Wong 2511bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? 2512ceeb9c83SDarrick J. Wong XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino, 25139c194644SDarrick J. Wong whichfork, PREV); 25149c194644SDarrick J. Wong } 25159c194644SDarrick J. Wong 25169c194644SDarrick J. Wong /* Unmap an extent out of a file. */ 2517bc46ac64SDarrick J. Wong void 25189c194644SDarrick J. Wong xfs_rmap_unmap_extent( 25190f37d178SBrian Foster struct xfs_trans *tp, 25209c194644SDarrick J. Wong struct xfs_inode *ip, 25219c194644SDarrick J. Wong int whichfork, 25229c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25239c194644SDarrick J. Wong { 25240f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2525bc46ac64SDarrick J. Wong return; 25269c194644SDarrick J. Wong 2527bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? 2528ceeb9c83SDarrick J. Wong XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino, 25299c194644SDarrick J. Wong whichfork, PREV); 25309c194644SDarrick J. Wong } 25319c194644SDarrick J. Wong 25320f37d178SBrian Foster /* 25330f37d178SBrian Foster * Convert a data fork extent from unwritten to real or vice versa. 25340f37d178SBrian Foster * 25350f37d178SBrian Foster * Note that tp can be NULL here as no transaction is used for COW fork 25360f37d178SBrian Foster * unwritten conversion. 25370f37d178SBrian Foster */ 2538bc46ac64SDarrick J. Wong void 25399c194644SDarrick J. Wong xfs_rmap_convert_extent( 25409c194644SDarrick J. Wong struct xfs_mount *mp, 25410f37d178SBrian Foster struct xfs_trans *tp, 25429c194644SDarrick J. Wong struct xfs_inode *ip, 25439c194644SDarrick J. Wong int whichfork, 25449c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25459c194644SDarrick J. Wong { 25463993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 2547bc46ac64SDarrick J. Wong return; 25489c194644SDarrick J. Wong 2549bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? 25503f165b33SDarrick J. Wong XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino, 25519c194644SDarrick J. Wong whichfork, PREV); 25529c194644SDarrick J. Wong } 25539c194644SDarrick J. Wong 25549c194644SDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */ 2555bc46ac64SDarrick J. Wong void 25569c194644SDarrick J. Wong xfs_rmap_alloc_extent( 25570f37d178SBrian Foster struct xfs_trans *tp, 25589c194644SDarrick J. Wong xfs_agnumber_t agno, 25599c194644SDarrick J. Wong xfs_agblock_t bno, 25609c194644SDarrick J. Wong xfs_extlen_t len, 2561c8ce540dSDarrick J. Wong uint64_t owner) 25629c194644SDarrick J. Wong { 25639c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 25649c194644SDarrick J. Wong 25650f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2566bc46ac64SDarrick J. Wong return; 25679c194644SDarrick J. Wong 25680f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 25699c194644SDarrick J. Wong bmap.br_blockcount = len; 25709c194644SDarrick J. Wong bmap.br_startoff = 0; 25719c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 25729c194644SDarrick J. Wong 2573bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap); 25749c194644SDarrick J. Wong } 25759c194644SDarrick J. Wong 25769c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */ 2577bc46ac64SDarrick J. Wong void 25789c194644SDarrick J. Wong xfs_rmap_free_extent( 25790f37d178SBrian Foster struct xfs_trans *tp, 25809c194644SDarrick J. Wong xfs_agnumber_t agno, 25819c194644SDarrick J. Wong xfs_agblock_t bno, 25829c194644SDarrick J. Wong xfs_extlen_t len, 2583c8ce540dSDarrick J. Wong uint64_t owner) 25849c194644SDarrick J. Wong { 25859c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 25869c194644SDarrick J. Wong 25870f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2588bc46ac64SDarrick J. Wong return; 25899c194644SDarrick J. Wong 25900f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 25919c194644SDarrick J. Wong bmap.br_blockcount = len; 25929c194644SDarrick J. Wong bmap.br_startoff = 0; 25939c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 25949c194644SDarrick J. Wong 2595bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap); 25969c194644SDarrick J. Wong } 2597e89c0413SDarrick J. Wong 2598e89c0413SDarrick J. Wong /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ 2599e89c0413SDarrick J. Wong int 2600e89c0413SDarrick J. Wong xfs_rmap_compare( 2601e89c0413SDarrick J. Wong const struct xfs_rmap_irec *a, 2602e89c0413SDarrick J. Wong const struct xfs_rmap_irec *b) 2603e89c0413SDarrick J. Wong { 2604e89c0413SDarrick J. Wong __u64 oa; 2605e89c0413SDarrick J. Wong __u64 ob; 2606e89c0413SDarrick J. Wong 2607e89c0413SDarrick J. Wong oa = xfs_rmap_irec_offset_pack(a); 2608e89c0413SDarrick J. Wong ob = xfs_rmap_irec_offset_pack(b); 2609e89c0413SDarrick J. Wong 2610e89c0413SDarrick J. Wong if (a->rm_startblock < b->rm_startblock) 2611e89c0413SDarrick J. Wong return -1; 2612e89c0413SDarrick J. Wong else if (a->rm_startblock > b->rm_startblock) 2613e89c0413SDarrick J. Wong return 1; 2614e89c0413SDarrick J. Wong else if (a->rm_owner < b->rm_owner) 2615e89c0413SDarrick J. Wong return -1; 2616e89c0413SDarrick J. Wong else if (a->rm_owner > b->rm_owner) 2617e89c0413SDarrick J. Wong return 1; 2618e89c0413SDarrick J. Wong else if (oa < ob) 2619e89c0413SDarrick J. Wong return -1; 2620e89c0413SDarrick J. Wong else if (oa > ob) 2621e89c0413SDarrick J. Wong return 1; 2622e89c0413SDarrick J. Wong else 2623e89c0413SDarrick J. Wong return 0; 2624e89c0413SDarrick J. Wong } 2625ed7c52d4SDarrick J. Wong 2626ed7c52d4SDarrick J. Wong /* Is there a record covering a given extent? */ 2627ed7c52d4SDarrick J. Wong int 2628ed7c52d4SDarrick J. Wong xfs_rmap_has_record( 2629ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2630ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2631ed7c52d4SDarrick J. Wong xfs_extlen_t len, 2632ed7c52d4SDarrick J. Wong bool *exists) 2633ed7c52d4SDarrick J. Wong { 2634ed7c52d4SDarrick J. Wong union xfs_btree_irec low; 2635ed7c52d4SDarrick J. Wong union xfs_btree_irec high; 2636ed7c52d4SDarrick J. Wong 2637ed7c52d4SDarrick J. Wong memset(&low, 0, sizeof(low)); 2638ed7c52d4SDarrick J. Wong low.r.rm_startblock = bno; 2639ed7c52d4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 2640ed7c52d4SDarrick J. Wong high.r.rm_startblock = bno + len - 1; 2641ed7c52d4SDarrick J. Wong 2642ed7c52d4SDarrick J. Wong return xfs_btree_has_record(cur, &low, &high, exists); 2643ed7c52d4SDarrick J. Wong } 2644ed7c52d4SDarrick J. Wong 2645ed7c52d4SDarrick J. Wong /* 2646ed7c52d4SDarrick J. Wong * Is there a record for this owner completely covering a given physical 2647ed7c52d4SDarrick J. Wong * extent? If so, *has_rmap will be set to true. If there is no record 2648ed7c52d4SDarrick J. Wong * or the record only covers part of the range, we set *has_rmap to false. 2649ed7c52d4SDarrick J. Wong * This function doesn't perform range lookups or offset checks, so it is 2650ed7c52d4SDarrick J. Wong * not suitable for checking data fork blocks. 2651ed7c52d4SDarrick J. Wong */ 2652ed7c52d4SDarrick J. Wong int 2653ed7c52d4SDarrick J. Wong xfs_rmap_record_exists( 2654ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2655ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2656ed7c52d4SDarrick J. Wong xfs_extlen_t len, 265766e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 2658ed7c52d4SDarrick J. Wong bool *has_rmap) 2659ed7c52d4SDarrick J. Wong { 2660ed7c52d4SDarrick J. Wong uint64_t owner; 2661ed7c52d4SDarrick J. Wong uint64_t offset; 2662ed7c52d4SDarrick J. Wong unsigned int flags; 2663ed7c52d4SDarrick J. Wong int has_record; 2664ed7c52d4SDarrick J. Wong struct xfs_rmap_irec irec; 2665ed7c52d4SDarrick J. Wong int error; 2666ed7c52d4SDarrick J. Wong 2667ed7c52d4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2668ed7c52d4SDarrick J. Wong ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || 2669ed7c52d4SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK)); 2670ed7c52d4SDarrick J. Wong 2671ed7c52d4SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, 2672ed7c52d4SDarrick J. Wong &has_record); 2673ed7c52d4SDarrick J. Wong if (error) 2674ed7c52d4SDarrick J. Wong return error; 2675ed7c52d4SDarrick J. Wong if (!has_record) { 2676ed7c52d4SDarrick J. Wong *has_rmap = false; 2677ed7c52d4SDarrick J. Wong return 0; 2678ed7c52d4SDarrick J. Wong } 2679ed7c52d4SDarrick J. Wong 2680ed7c52d4SDarrick J. Wong error = xfs_rmap_get_rec(cur, &irec, &has_record); 2681ed7c52d4SDarrick J. Wong if (error) 2682ed7c52d4SDarrick J. Wong return error; 2683ed7c52d4SDarrick J. Wong if (!has_record) { 2684ed7c52d4SDarrick J. Wong *has_rmap = false; 2685ed7c52d4SDarrick J. Wong return 0; 2686ed7c52d4SDarrick J. Wong } 2687ed7c52d4SDarrick J. Wong 2688ed7c52d4SDarrick J. Wong *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno && 2689ed7c52d4SDarrick J. Wong irec.rm_startblock + irec.rm_blockcount >= bno + len); 2690ed7c52d4SDarrick J. Wong return 0; 2691ed7c52d4SDarrick J. Wong } 26924d4f86b4SDarrick J. Wong 26934d4f86b4SDarrick J. Wong struct xfs_rmap_key_state { 26944d4f86b4SDarrick J. Wong uint64_t owner; 26954d4f86b4SDarrick J. Wong uint64_t offset; 26964d4f86b4SDarrick J. Wong unsigned int flags; 26974d4f86b4SDarrick J. Wong bool has_rmap; 26984d4f86b4SDarrick J. Wong }; 26994d4f86b4SDarrick J. Wong 27004d4f86b4SDarrick J. Wong /* For each rmap given, figure out if it doesn't match the key we want. */ 27014d4f86b4SDarrick J. Wong STATIC int 27024d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper( 27034d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 27044d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rec, 27054d4f86b4SDarrick J. Wong void *priv) 27064d4f86b4SDarrick J. Wong { 27074d4f86b4SDarrick J. Wong struct xfs_rmap_key_state *rks = priv; 27084d4f86b4SDarrick J. Wong 27094d4f86b4SDarrick J. Wong if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset && 27104d4f86b4SDarrick J. Wong ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags) 27114d4f86b4SDarrick J. Wong return 0; 27124d4f86b4SDarrick J. Wong rks->has_rmap = true; 2713e7ee96dfSDarrick J. Wong return -ECANCELED; 27144d4f86b4SDarrick J. Wong } 27154d4f86b4SDarrick J. Wong 27164d4f86b4SDarrick J. Wong /* 27174d4f86b4SDarrick J. Wong * Given an extent and some owner info, can we find records overlapping 27184d4f86b4SDarrick J. Wong * the extent whose owner info does not match the given owner? 27194d4f86b4SDarrick J. Wong */ 27204d4f86b4SDarrick J. Wong int 27214d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys( 27224d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 27234d4f86b4SDarrick J. Wong xfs_agblock_t bno, 27244d4f86b4SDarrick J. Wong xfs_extlen_t len, 272566e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 27264d4f86b4SDarrick J. Wong bool *has_rmap) 27274d4f86b4SDarrick J. Wong { 27284d4f86b4SDarrick J. Wong struct xfs_rmap_irec low = {0}; 27294d4f86b4SDarrick J. Wong struct xfs_rmap_irec high; 27304d4f86b4SDarrick J. Wong struct xfs_rmap_key_state rks; 27314d4f86b4SDarrick J. Wong int error; 27324d4f86b4SDarrick J. Wong 27334d4f86b4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags); 27344d4f86b4SDarrick J. Wong rks.has_rmap = false; 27354d4f86b4SDarrick J. Wong 27364d4f86b4SDarrick J. Wong low.rm_startblock = bno; 27374d4f86b4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 27384d4f86b4SDarrick J. Wong high.rm_startblock = bno + len - 1; 27394d4f86b4SDarrick J. Wong 27404d4f86b4SDarrick J. Wong error = xfs_rmap_query_range(cur, &low, &high, 27414d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper, &rks); 27427380e8feSDarrick J. Wong if (error < 0) 27434d4f86b4SDarrick J. Wong return error; 27447380e8feSDarrick J. Wong 27457380e8feSDarrick J. Wong *has_rmap = rks.has_rmap; 27467380e8feSDarrick J. Wong return 0; 27474d4f86b4SDarrick J. Wong } 27487280fedaSDarrick J. Wong 27497280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = { 27507280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_NULL, 27517280fedaSDarrick J. Wong }; 27527280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = { 27537280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_UNKNOWN, 27547280fedaSDarrick J. Wong }; 27557280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_FS = { 27567280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_FS, 27577280fedaSDarrick J. Wong }; 27587280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_LOG = { 27597280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_LOG, 27607280fedaSDarrick J. Wong }; 27617280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_AG = { 27627280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_AG, 27637280fedaSDarrick J. Wong }; 27647280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = { 27657280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INOBT, 27667280fedaSDarrick J. Wong }; 27677280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INODES = { 27687280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INODES, 27697280fedaSDarrick J. Wong }; 27707280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_REFC = { 27717280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_REFC, 27727280fedaSDarrick J. Wong }; 27737280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_COW = { 27747280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_COW, 27757280fedaSDarrick J. Wong }; 2776