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; 116abf09233SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done); 117abf09233SDarrick J. Wong 118abf09233SDarrick J. Wong rcur->bc_rec.r.rm_startblock = agbno; 119abf09233SDarrick J. Wong rcur->bc_rec.r.rm_blockcount = len; 120abf09233SDarrick J. Wong rcur->bc_rec.r.rm_owner = owner; 121abf09233SDarrick J. Wong rcur->bc_rec.r.rm_offset = offset; 122abf09233SDarrick J. Wong rcur->bc_rec.r.rm_flags = flags; 123abf09233SDarrick J. Wong error = xfs_btree_insert(rcur, &i); 124abf09233SDarrick J. Wong if (error) 125abf09233SDarrick J. Wong goto done; 126abf09233SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); 127abf09233SDarrick J. Wong done: 128abf09233SDarrick J. Wong if (error) 129abf09233SDarrick J. Wong trace_xfs_rmap_insert_error(rcur->bc_mp, 130abf09233SDarrick J. Wong rcur->bc_private.a.agno, error, _RET_IP_); 131abf09233SDarrick J. Wong return error; 1324b8ed677SDarrick J. Wong } 1334b8ed677SDarrick J. Wong 134ceeb9c83SDarrick J. Wong STATIC int 135ceeb9c83SDarrick J. Wong xfs_rmap_delete( 136ceeb9c83SDarrick J. Wong struct xfs_btree_cur *rcur, 137ceeb9c83SDarrick J. Wong xfs_agblock_t agbno, 138ceeb9c83SDarrick J. Wong xfs_extlen_t len, 139ceeb9c83SDarrick J. Wong uint64_t owner, 140ceeb9c83SDarrick J. Wong uint64_t offset, 141ceeb9c83SDarrick J. Wong unsigned int flags) 142ceeb9c83SDarrick J. Wong { 143ceeb9c83SDarrick J. Wong int i; 144ceeb9c83SDarrick J. Wong int error; 145ceeb9c83SDarrick J. Wong 146ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, 147ceeb9c83SDarrick J. Wong len, owner, offset, flags); 148ceeb9c83SDarrick J. Wong 149ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); 150ceeb9c83SDarrick J. Wong if (error) 151ceeb9c83SDarrick J. Wong goto done; 152ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); 153ceeb9c83SDarrick J. Wong 154ceeb9c83SDarrick J. Wong error = xfs_btree_delete(rcur, &i); 155ceeb9c83SDarrick J. Wong if (error) 156ceeb9c83SDarrick J. Wong goto done; 157ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); 158ceeb9c83SDarrick J. Wong done: 159ceeb9c83SDarrick J. Wong if (error) 160ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete_error(rcur->bc_mp, 161ceeb9c83SDarrick J. Wong rcur->bc_private.a.agno, error, _RET_IP_); 162ceeb9c83SDarrick J. Wong return error; 163ceeb9c83SDarrick J. Wong } 164ceeb9c83SDarrick J. Wong 16526788097SDarrick J. Wong /* Convert an internal btree record to an rmap record. */ 16626788097SDarrick J. Wong int 1674b8ed677SDarrick J. Wong xfs_rmap_btrec_to_irec( 1684b8ed677SDarrick J. Wong union xfs_btree_rec *rec, 1694b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec) 1704b8ed677SDarrick J. Wong { 1714b8ed677SDarrick J. Wong irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); 1724b8ed677SDarrick J. Wong irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); 1734b8ed677SDarrick J. Wong irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); 1744b8ed677SDarrick J. Wong return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), 1754b8ed677SDarrick J. Wong irec); 1764b8ed677SDarrick J. Wong } 1774b8ed677SDarrick J. Wong 1784b8ed677SDarrick J. Wong /* 1794b8ed677SDarrick J. Wong * Get the data from the pointed-to record. 1804b8ed677SDarrick J. Wong */ 1814b8ed677SDarrick J. Wong int 1824b8ed677SDarrick J. Wong xfs_rmap_get_rec( 1834b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 1844b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec, 1854b8ed677SDarrick J. Wong int *stat) 1864b8ed677SDarrick J. Wong { 1879e6c08d4SDave Chinner struct xfs_mount *mp = cur->bc_mp; 1889e6c08d4SDave Chinner xfs_agnumber_t agno = cur->bc_private.a.agno; 1894b8ed677SDarrick J. Wong union xfs_btree_rec *rec; 1904b8ed677SDarrick J. Wong int error; 1914b8ed677SDarrick J. Wong 1924b8ed677SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat); 1934b8ed677SDarrick J. Wong if (error || !*stat) 1944b8ed677SDarrick J. Wong return error; 1954b8ed677SDarrick J. Wong 1969e6c08d4SDave Chinner if (xfs_rmap_btrec_to_irec(rec, irec)) 1979e6c08d4SDave Chinner goto out_bad_rec; 1989e6c08d4SDave Chinner 1999e6c08d4SDave Chinner if (irec->rm_blockcount == 0) 2009e6c08d4SDave Chinner goto out_bad_rec; 2019e6c08d4SDave Chinner if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) { 2029e6c08d4SDave Chinner if (irec->rm_owner != XFS_RMAP_OWN_FS) 2039e6c08d4SDave Chinner goto out_bad_rec; 2049e6c08d4SDave Chinner if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1) 2059e6c08d4SDave Chinner goto out_bad_rec; 2069e6c08d4SDave Chinner } else { 2079e6c08d4SDave Chinner /* check for valid extent range, including overflow */ 2089e6c08d4SDave Chinner if (!xfs_verify_agbno(mp, agno, irec->rm_startblock)) 2099e6c08d4SDave Chinner goto out_bad_rec; 2109e6c08d4SDave Chinner if (irec->rm_startblock > 2119e6c08d4SDave Chinner irec->rm_startblock + irec->rm_blockcount) 2129e6c08d4SDave Chinner goto out_bad_rec; 2139e6c08d4SDave Chinner if (!xfs_verify_agbno(mp, agno, 2149e6c08d4SDave Chinner irec->rm_startblock + irec->rm_blockcount - 1)) 2159e6c08d4SDave Chinner goto out_bad_rec; 2169e6c08d4SDave Chinner } 2179e6c08d4SDave Chinner 2189e6c08d4SDave Chinner if (!(xfs_verify_ino(mp, irec->rm_owner) || 2199e6c08d4SDave Chinner (irec->rm_owner <= XFS_RMAP_OWN_FS && 2209e6c08d4SDave Chinner irec->rm_owner >= XFS_RMAP_OWN_MIN))) 2219e6c08d4SDave Chinner goto out_bad_rec; 2229e6c08d4SDave Chinner 2239e6c08d4SDave Chinner return 0; 2249e6c08d4SDave Chinner out_bad_rec: 2259e6c08d4SDave Chinner xfs_warn(mp, 2269e6c08d4SDave Chinner "Reverse Mapping BTree record corruption in AG %d detected!", 2279e6c08d4SDave Chinner agno); 2289e6c08d4SDave Chinner xfs_warn(mp, 2299e6c08d4SDave Chinner "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", 2309e6c08d4SDave Chinner irec->rm_owner, irec->rm_flags, irec->rm_startblock, 2319e6c08d4SDave Chinner irec->rm_blockcount); 2329e6c08d4SDave Chinner return -EFSCORRUPTED; 2334b8ed677SDarrick J. Wong } 2344b8ed677SDarrick J. Wong 235ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info { 236ceeb9c83SDarrick J. Wong struct xfs_rmap_irec high; 237ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec; 238ceeb9c83SDarrick J. Wong int *stat; 239ceeb9c83SDarrick J. Wong }; 240ceeb9c83SDarrick J. Wong 241ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 242ceeb9c83SDarrick J. Wong STATIC int 243ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper( 244ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 245ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *rec, 246ceeb9c83SDarrick J. Wong void *priv) 247ceeb9c83SDarrick J. Wong { 248ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 249ceeb9c83SDarrick J. Wong 250ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, 251ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, rec->rm_startblock, 252ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 253ceeb9c83SDarrick J. Wong rec->rm_flags); 254ceeb9c83SDarrick J. Wong 255ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 256ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 257ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 258ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 259ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) 260ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 261ceeb9c83SDarrick J. Wong 262ceeb9c83SDarrick J. Wong *info->irec = *rec; 263ceeb9c83SDarrick J. Wong *info->stat = 1; 264e7ee96dfSDarrick J. Wong return -ECANCELED; 265ceeb9c83SDarrick J. Wong } 266ceeb9c83SDarrick J. Wong 267ceeb9c83SDarrick J. Wong /* 268ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 269ceeb9c83SDarrick J. Wong * return a match with the same owner and adjacent physical and logical 270ceeb9c83SDarrick J. Wong * block ranges. 271ceeb9c83SDarrick J. Wong */ 272ceeb9c83SDarrick J. Wong int 273ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor( 274ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 275ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 276ceeb9c83SDarrick J. Wong uint64_t owner, 277ceeb9c83SDarrick J. Wong uint64_t offset, 278ceeb9c83SDarrick J. Wong unsigned int flags, 279ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 280ceeb9c83SDarrick J. Wong int *stat) 281ceeb9c83SDarrick J. Wong { 282ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 283ceeb9c83SDarrick J. Wong int error; 284ceeb9c83SDarrick J. Wong 285ceeb9c83SDarrick J. Wong *stat = 0; 286ceeb9c83SDarrick J. Wong if (bno == 0) 287ceeb9c83SDarrick J. Wong return 0; 288ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno - 1; 289ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 290ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && 291ceeb9c83SDarrick J. Wong !(flags & XFS_RMAP_BMBT_BLOCK)) { 292ceeb9c83SDarrick J. Wong if (offset == 0) 293ceeb9c83SDarrick J. Wong return 0; 294ceeb9c83SDarrick J. Wong info.high.rm_offset = offset - 1; 295ceeb9c83SDarrick J. Wong } else 296ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 297ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 298ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 299ceeb9c83SDarrick J. Wong info.irec = irec; 300ceeb9c83SDarrick J. Wong info.stat = stat; 301ceeb9c83SDarrick J. Wong 302ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, 303ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, bno, 0, owner, offset, flags); 304ceeb9c83SDarrick J. Wong 305ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 306ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper, &info); 307e7ee96dfSDarrick J. Wong if (error == -ECANCELED) 308ceeb9c83SDarrick J. Wong error = 0; 309ceeb9c83SDarrick J. Wong if (*stat) 310ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 311ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, irec->rm_startblock, 312ceeb9c83SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, 313ceeb9c83SDarrick J. Wong irec->rm_offset, irec->rm_flags); 314ceeb9c83SDarrick J. Wong return error; 315ceeb9c83SDarrick J. Wong } 316ceeb9c83SDarrick J. Wong 317ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 318ceeb9c83SDarrick J. Wong STATIC int 319ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper( 320ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 321ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *rec, 322ceeb9c83SDarrick J. Wong void *priv) 323ceeb9c83SDarrick J. Wong { 324ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 325ceeb9c83SDarrick J. Wong 326ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, 327ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, rec->rm_startblock, 328ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 329ceeb9c83SDarrick J. Wong rec->rm_flags); 330ceeb9c83SDarrick J. Wong 331ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 332ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 333ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 334ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 335ceeb9c83SDarrick J. Wong (rec->rm_offset > info->high.rm_offset || 336ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) 337ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 338ceeb9c83SDarrick J. Wong 339ceeb9c83SDarrick J. Wong *info->irec = *rec; 340ceeb9c83SDarrick J. Wong *info->stat = 1; 341e7ee96dfSDarrick J. Wong return -ECANCELED; 342ceeb9c83SDarrick J. Wong } 343ceeb9c83SDarrick J. Wong 344ceeb9c83SDarrick J. Wong /* 345ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 346ceeb9c83SDarrick J. Wong * return a match with the same owner and overlapping physical and logical 347ceeb9c83SDarrick J. Wong * block ranges. This is the overlapping-interval version of 348ceeb9c83SDarrick J. Wong * xfs_rmap_lookup_le. 349ceeb9c83SDarrick J. Wong */ 350ceeb9c83SDarrick J. Wong int 351ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range( 352ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 353ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 354ceeb9c83SDarrick J. Wong uint64_t owner, 355ceeb9c83SDarrick J. Wong uint64_t offset, 356ceeb9c83SDarrick J. Wong unsigned int flags, 357ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 358ceeb9c83SDarrick J. Wong int *stat) 359ceeb9c83SDarrick J. Wong { 360ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 361ceeb9c83SDarrick J. Wong int error; 362ceeb9c83SDarrick J. Wong 363ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno; 364ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 365ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) 366ceeb9c83SDarrick J. Wong info.high.rm_offset = offset; 367ceeb9c83SDarrick J. Wong else 368ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 369ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 370ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 371ceeb9c83SDarrick J. Wong *stat = 0; 372ceeb9c83SDarrick J. Wong info.irec = irec; 373ceeb9c83SDarrick J. Wong info.stat = stat; 374ceeb9c83SDarrick J. Wong 375ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range(cur->bc_mp, 376ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, bno, 0, owner, offset, flags); 377ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 378ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper, &info); 379e7ee96dfSDarrick J. Wong if (error == -ECANCELED) 380ceeb9c83SDarrick J. Wong error = 0; 381ceeb9c83SDarrick J. Wong if (*stat) 382ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 383ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, irec->rm_startblock, 384ceeb9c83SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, 385ceeb9c83SDarrick J. Wong irec->rm_offset, irec->rm_flags); 386ceeb9c83SDarrick J. Wong return error; 387ceeb9c83SDarrick J. Wong } 388ceeb9c83SDarrick J. Wong 389f922cd90SDarrick J. Wong /* 39068c58e9bSDarrick J. Wong * Perform all the relevant owner checks for a removal op. If we're doing an 39168c58e9bSDarrick J. Wong * unknown-owner removal then we have no owner information to check. 39268c58e9bSDarrick J. Wong */ 39368c58e9bSDarrick J. Wong static int 39468c58e9bSDarrick J. Wong xfs_rmap_free_check_owner( 39568c58e9bSDarrick J. Wong struct xfs_mount *mp, 39668c58e9bSDarrick J. Wong uint64_t ltoff, 39768c58e9bSDarrick J. Wong struct xfs_rmap_irec *rec, 39868c58e9bSDarrick J. Wong xfs_filblks_t len, 39968c58e9bSDarrick J. Wong uint64_t owner, 40068c58e9bSDarrick J. Wong uint64_t offset, 40168c58e9bSDarrick J. Wong unsigned int flags) 40268c58e9bSDarrick J. Wong { 40368c58e9bSDarrick J. Wong int error = 0; 40468c58e9bSDarrick J. Wong 40568c58e9bSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN) 40668c58e9bSDarrick J. Wong return 0; 40768c58e9bSDarrick J. Wong 40868c58e9bSDarrick J. Wong /* Make sure the unwritten flag matches. */ 40968c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == 41068c58e9bSDarrick J. Wong (rec->rm_flags & XFS_RMAP_UNWRITTEN), out); 41168c58e9bSDarrick J. Wong 41268c58e9bSDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 41368c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out); 41468c58e9bSDarrick J. Wong 41568c58e9bSDarrick J. Wong /* Check the offset, if necessary. */ 41668c58e9bSDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(owner)) 41768c58e9bSDarrick J. Wong goto out; 41868c58e9bSDarrick J. Wong 41968c58e9bSDarrick J. Wong if (flags & XFS_RMAP_BMBT_BLOCK) { 42068c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK, 42168c58e9bSDarrick J. Wong out); 42268c58e9bSDarrick J. Wong } else { 42368c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out); 42468c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 42568c58e9bSDarrick J. Wong ltoff + rec->rm_blockcount >= offset + len, 42668c58e9bSDarrick J. Wong out); 42768c58e9bSDarrick J. Wong } 42868c58e9bSDarrick J. Wong 42968c58e9bSDarrick J. Wong out: 43068c58e9bSDarrick J. Wong return error; 43168c58e9bSDarrick J. Wong } 43268c58e9bSDarrick J. Wong 43368c58e9bSDarrick J. Wong /* 434f922cd90SDarrick J. Wong * Find the extent in the rmap btree and remove it. 435f922cd90SDarrick J. Wong * 436f922cd90SDarrick J. Wong * The record we find should always be an exact match for the extent that we're 437f922cd90SDarrick J. Wong * looking for, since we insert them into the btree without modification. 438f922cd90SDarrick J. Wong * 439f922cd90SDarrick J. Wong * Special Case #1: when growing the filesystem, we "free" an extent when 440f922cd90SDarrick J. Wong * growing the last AG. This extent is new space and so it is not tracked as 441f922cd90SDarrick J. Wong * used space in the btree. The growfs code will pass in an owner of 442f922cd90SDarrick J. Wong * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this 443f922cd90SDarrick J. Wong * extent. We verify that - the extent lookup result in a record that does not 444f922cd90SDarrick J. Wong * overlap. 445f922cd90SDarrick J. Wong * 446f922cd90SDarrick J. Wong * Special Case #2: EFIs do not record the owner of the extent, so when 447f922cd90SDarrick J. Wong * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap 448f922cd90SDarrick J. Wong * btree to ignore the owner (i.e. wildcard match) so we don't trigger 449f922cd90SDarrick J. Wong * corruption checks during log recovery. 450f922cd90SDarrick J. Wong */ 451f922cd90SDarrick J. Wong STATIC int 452f922cd90SDarrick J. Wong xfs_rmap_unmap( 453f922cd90SDarrick J. Wong struct xfs_btree_cur *cur, 454f922cd90SDarrick J. Wong xfs_agblock_t bno, 455f922cd90SDarrick J. Wong xfs_extlen_t len, 456f922cd90SDarrick J. Wong bool unwritten, 45766e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 458f922cd90SDarrick J. Wong { 459f922cd90SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 460f922cd90SDarrick J. Wong struct xfs_rmap_irec ltrec; 461f922cd90SDarrick J. Wong uint64_t ltoff; 462f922cd90SDarrick J. Wong int error = 0; 463f922cd90SDarrick J. Wong int i; 464f922cd90SDarrick J. Wong uint64_t owner; 465f922cd90SDarrick J. Wong uint64_t offset; 466f922cd90SDarrick J. Wong unsigned int flags; 467f922cd90SDarrick J. Wong bool ignore_off; 468f922cd90SDarrick J. Wong 469f922cd90SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 470f922cd90SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 471f922cd90SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 472f922cd90SDarrick J. Wong if (unwritten) 473f922cd90SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 474f922cd90SDarrick J. Wong trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, 475f922cd90SDarrick J. Wong unwritten, oinfo); 476f922cd90SDarrick J. Wong 477f922cd90SDarrick J. Wong /* 478f922cd90SDarrick J. Wong * We should always have a left record because there's a static record 479f922cd90SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 480f922cd90SDarrick J. Wong * will not ever be removed from the tree. 481f922cd90SDarrick J. Wong */ 482f922cd90SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); 483f922cd90SDarrick J. Wong if (error) 484f922cd90SDarrick J. Wong goto out_error; 485f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 486f922cd90SDarrick J. Wong 487f922cd90SDarrick J. Wong error = xfs_rmap_get_rec(cur, <rec, &i); 488f922cd90SDarrick J. Wong if (error) 489f922cd90SDarrick J. Wong goto out_error; 490f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 491f922cd90SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 492f922cd90SDarrick J. Wong cur->bc_private.a.agno, ltrec.rm_startblock, 493f922cd90SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 494f922cd90SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 495f922cd90SDarrick J. Wong ltoff = ltrec.rm_offset; 496f922cd90SDarrick J. Wong 497f922cd90SDarrick J. Wong /* 498f922cd90SDarrick J. Wong * For growfs, the incoming extent must be beyond the left record we 499f922cd90SDarrick J. Wong * just found as it is new space and won't be used by anyone. This is 500f922cd90SDarrick J. Wong * just a corruption check as we don't actually do anything with this 501f922cd90SDarrick J. Wong * extent. Note that we need to use >= instead of > because it might 502f922cd90SDarrick J. Wong * be the case that the "left" extent goes all the way to EOFS. 503f922cd90SDarrick J. Wong */ 504f922cd90SDarrick J. Wong if (owner == XFS_RMAP_OWN_NULL) { 505f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock + 506f922cd90SDarrick J. Wong ltrec.rm_blockcount, out_error); 507f922cd90SDarrick J. Wong goto out_done; 508f922cd90SDarrick J. Wong } 509f922cd90SDarrick J. Wong 51033df3a9cSDarrick J. Wong /* 51133df3a9cSDarrick J. Wong * If we're doing an unknown-owner removal for EFI recovery, we expect 51233df3a9cSDarrick J. Wong * to find the full range in the rmapbt or nothing at all. If we 51333df3a9cSDarrick J. Wong * don't find any rmaps overlapping either end of the range, we're 51433df3a9cSDarrick J. Wong * done. Hopefully this means that the EFI creator already queued 51533df3a9cSDarrick J. Wong * (and finished) a RUI to remove the rmap. 51633df3a9cSDarrick J. Wong */ 51733df3a9cSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN && 51833df3a9cSDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 51933df3a9cSDarrick J. Wong struct xfs_rmap_irec rtrec; 52033df3a9cSDarrick J. Wong 52133df3a9cSDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 52233df3a9cSDarrick J. Wong if (error) 52333df3a9cSDarrick J. Wong goto out_error; 52433df3a9cSDarrick J. Wong if (i == 0) 52533df3a9cSDarrick J. Wong goto out_done; 52633df3a9cSDarrick J. Wong error = xfs_rmap_get_rec(cur, &rtrec, &i); 52733df3a9cSDarrick J. Wong if (error) 52833df3a9cSDarrick J. Wong goto out_error; 52933df3a9cSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 53033df3a9cSDarrick J. Wong if (rtrec.rm_startblock >= bno + len) 53133df3a9cSDarrick J. Wong goto out_done; 53233df3a9cSDarrick J. Wong } 53333df3a9cSDarrick J. Wong 534f922cd90SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 535f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && 536f922cd90SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount >= 537f922cd90SDarrick J. Wong bno + len, out_error); 538f922cd90SDarrick J. Wong 53968c58e9bSDarrick J. Wong /* Check owner information. */ 540a1f69417SEric Sandeen error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner, 54168c58e9bSDarrick J. Wong offset, flags); 54268c58e9bSDarrick J. Wong if (error) 54368c58e9bSDarrick J. Wong goto out_error; 544f922cd90SDarrick J. Wong 545f922cd90SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 546f922cd90SDarrick J. Wong /* exact match, simply remove the record from rmap tree */ 547f922cd90SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 548f922cd90SDarrick J. Wong ltrec.rm_startblock, ltrec.rm_blockcount, 549f922cd90SDarrick J. Wong ltrec.rm_owner, ltrec.rm_offset, 550f922cd90SDarrick J. Wong ltrec.rm_flags); 551f922cd90SDarrick J. Wong error = xfs_btree_delete(cur, &i); 552f922cd90SDarrick J. Wong if (error) 553f922cd90SDarrick J. Wong goto out_error; 554f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 555f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 556f922cd90SDarrick J. Wong /* 557f922cd90SDarrick J. Wong * overlap left hand side of extent: move the start, trim the 558f922cd90SDarrick J. Wong * length and update the current record. 559f922cd90SDarrick J. Wong * 560f922cd90SDarrick J. Wong * ltbno ltlen 561f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 562f922cd90SDarrick J. Wong * Freeing: |fffffffff| 563f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 564f922cd90SDarrick J. Wong * bno len 565f922cd90SDarrick J. Wong */ 566f922cd90SDarrick J. Wong ltrec.rm_startblock += len; 567f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 568f922cd90SDarrick J. Wong if (!ignore_off) 569f922cd90SDarrick J. Wong ltrec.rm_offset += len; 570f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 571f922cd90SDarrick J. Wong if (error) 572f922cd90SDarrick J. Wong goto out_error; 573f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 574f922cd90SDarrick J. Wong /* 575f922cd90SDarrick J. Wong * overlap right hand side of extent: trim the length and update 576f922cd90SDarrick J. Wong * the current record. 577f922cd90SDarrick J. Wong * 578f922cd90SDarrick J. Wong * ltbno ltlen 579f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 580f922cd90SDarrick J. Wong * Freeing: |fffffffff| 581f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 582f922cd90SDarrick J. Wong * bno len 583f922cd90SDarrick J. Wong */ 584f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 585f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 586f922cd90SDarrick J. Wong if (error) 587f922cd90SDarrick J. Wong goto out_error; 588f922cd90SDarrick J. Wong } else { 589f922cd90SDarrick J. Wong 590f922cd90SDarrick J. Wong /* 591f922cd90SDarrick J. Wong * overlap middle of extent: trim the length of the existing 592f922cd90SDarrick J. Wong * record to the length of the new left-extent size, increment 593f922cd90SDarrick J. Wong * the insertion position so we can insert a new record 594f922cd90SDarrick J. Wong * containing the remaining right-extent space. 595f922cd90SDarrick J. Wong * 596f922cd90SDarrick J. Wong * ltbno ltlen 597f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 598f922cd90SDarrick J. Wong * Freeing: |fffffffff| 599f922cd90SDarrick J. Wong * Result: |rrrrr| |rrrr| 600f922cd90SDarrick J. Wong * bno len 601f922cd90SDarrick J. Wong */ 602f922cd90SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 603f922cd90SDarrick J. Wong 604f922cd90SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 605f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 606f922cd90SDarrick J. Wong if (error) 607f922cd90SDarrick J. Wong goto out_error; 608f922cd90SDarrick J. Wong 609f922cd90SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 610f922cd90SDarrick J. Wong if (error) 611f922cd90SDarrick J. Wong goto out_error; 612f922cd90SDarrick J. Wong 613f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno + len; 614f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount = orig_len - len - 615f922cd90SDarrick J. Wong ltrec.rm_blockcount; 616f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner = ltrec.rm_owner; 617f922cd90SDarrick J. Wong if (ignore_off) 618f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = 0; 619f922cd90SDarrick J. Wong else 620f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = offset + len; 621f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 622f922cd90SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, 623f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock, 624f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount, 625f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner, 626f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset, 627f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags); 628f922cd90SDarrick J. Wong error = xfs_btree_insert(cur, &i); 629f922cd90SDarrick J. Wong if (error) 630f922cd90SDarrick J. Wong goto out_error; 631f922cd90SDarrick J. Wong } 632f922cd90SDarrick J. Wong 633f922cd90SDarrick J. Wong out_done: 634f922cd90SDarrick J. Wong trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, 635f922cd90SDarrick J. Wong unwritten, oinfo); 636f922cd90SDarrick J. Wong out_error: 637f922cd90SDarrick J. Wong if (error) 638f922cd90SDarrick J. Wong trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno, 639f922cd90SDarrick J. Wong error, _RET_IP_); 640f922cd90SDarrick J. Wong return error; 641f922cd90SDarrick J. Wong } 642f922cd90SDarrick J. Wong 643f922cd90SDarrick J. Wong /* 644f922cd90SDarrick J. Wong * Remove a reference to an extent in the rmap btree. 645f922cd90SDarrick J. Wong */ 646673930c3SDarrick J. Wong int 647673930c3SDarrick J. Wong xfs_rmap_free( 648673930c3SDarrick J. Wong struct xfs_trans *tp, 649673930c3SDarrick J. Wong struct xfs_buf *agbp, 650673930c3SDarrick J. Wong xfs_agnumber_t agno, 651673930c3SDarrick J. Wong xfs_agblock_t bno, 652673930c3SDarrick J. Wong xfs_extlen_t len, 65366e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 654673930c3SDarrick J. Wong { 655673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 656f922cd90SDarrick J. Wong struct xfs_btree_cur *cur; 657f922cd90SDarrick J. Wong int error; 658673930c3SDarrick J. Wong 659673930c3SDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 660673930c3SDarrick J. Wong return 0; 661673930c3SDarrick J. Wong 662f922cd90SDarrick J. Wong cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 663f922cd90SDarrick J. Wong 664f922cd90SDarrick J. Wong error = xfs_rmap_unmap(cur, bno, len, false, oinfo); 665f922cd90SDarrick J. Wong 6660b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 667673930c3SDarrick J. Wong return error; 668673930c3SDarrick J. Wong } 669673930c3SDarrick J. Wong 6700a1b0b38SDarrick J. Wong /* 6710a1b0b38SDarrick J. Wong * A mergeable rmap must have the same owner and the same values for 6720a1b0b38SDarrick J. Wong * the unwritten, attr_fork, and bmbt flags. The startblock and 6730a1b0b38SDarrick J. Wong * offset are checked separately. 6740a1b0b38SDarrick J. Wong */ 6750a1b0b38SDarrick J. Wong static bool 6760a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable( 6770a1b0b38SDarrick J. Wong struct xfs_rmap_irec *irec, 6780a1b0b38SDarrick J. Wong uint64_t owner, 6790a1b0b38SDarrick J. Wong unsigned int flags) 6800a1b0b38SDarrick J. Wong { 6810a1b0b38SDarrick J. Wong if (irec->rm_owner == XFS_RMAP_OWN_NULL) 6820a1b0b38SDarrick J. Wong return false; 6830a1b0b38SDarrick J. Wong if (irec->rm_owner != owner) 6840a1b0b38SDarrick J. Wong return false; 6850a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_UNWRITTEN) ^ 6860a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_UNWRITTEN)) 6870a1b0b38SDarrick J. Wong return false; 6880a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_ATTR_FORK) ^ 6890a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_ATTR_FORK)) 6900a1b0b38SDarrick J. Wong return false; 6910a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_BMBT_BLOCK) ^ 6920a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) 6930a1b0b38SDarrick J. Wong return false; 6940a1b0b38SDarrick J. Wong return true; 6950a1b0b38SDarrick J. Wong } 6960a1b0b38SDarrick J. Wong 6970a1b0b38SDarrick J. Wong /* 6980a1b0b38SDarrick J. Wong * When we allocate a new block, the first thing we do is add a reference to 6990a1b0b38SDarrick J. Wong * the extent in the rmap btree. This takes the form of a [agbno, length, 7000a1b0b38SDarrick J. Wong * owner, offset] record. Flags are encoded in the high bits of the offset 7010a1b0b38SDarrick J. Wong * field. 7020a1b0b38SDarrick J. Wong */ 7030a1b0b38SDarrick J. Wong STATIC int 7040a1b0b38SDarrick J. Wong xfs_rmap_map( 7050a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur, 7060a1b0b38SDarrick J. Wong xfs_agblock_t bno, 7070a1b0b38SDarrick J. Wong xfs_extlen_t len, 7080a1b0b38SDarrick J. Wong bool unwritten, 70966e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 7100a1b0b38SDarrick J. Wong { 7110a1b0b38SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 7120a1b0b38SDarrick J. Wong struct xfs_rmap_irec ltrec; 7130a1b0b38SDarrick J. Wong struct xfs_rmap_irec gtrec; 7140a1b0b38SDarrick J. Wong int have_gt; 7150a1b0b38SDarrick J. Wong int have_lt; 7160a1b0b38SDarrick J. Wong int error = 0; 7170a1b0b38SDarrick J. Wong int i; 7180a1b0b38SDarrick J. Wong uint64_t owner; 7190a1b0b38SDarrick J. Wong uint64_t offset; 7200a1b0b38SDarrick J. Wong unsigned int flags = 0; 7210a1b0b38SDarrick J. Wong bool ignore_off; 7220a1b0b38SDarrick J. Wong 7230a1b0b38SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 7240a1b0b38SDarrick J. Wong ASSERT(owner != 0); 7250a1b0b38SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 7260a1b0b38SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 7270a1b0b38SDarrick J. Wong if (unwritten) 7280a1b0b38SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 7290a1b0b38SDarrick J. Wong trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 7300a1b0b38SDarrick J. Wong unwritten, oinfo); 73133df3a9cSDarrick J. Wong ASSERT(!xfs_rmap_should_skip_owner_update(oinfo)); 7320a1b0b38SDarrick J. Wong 7330a1b0b38SDarrick J. Wong /* 7340a1b0b38SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 7350a1b0b38SDarrick J. Wong * record for our insertion point. This will also give us the record for 7360a1b0b38SDarrick J. Wong * start block contiguity tests. 7370a1b0b38SDarrick J. Wong */ 7380a1b0b38SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, 7390a1b0b38SDarrick J. Wong &have_lt); 7400a1b0b38SDarrick J. Wong if (error) 7410a1b0b38SDarrick J. Wong goto out_error; 742fa248de9SDarrick J. Wong if (have_lt) { 7430a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, <rec, &have_lt); 7440a1b0b38SDarrick J. Wong if (error) 7450a1b0b38SDarrick J. Wong goto out_error; 7460a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); 7470a1b0b38SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 7480a1b0b38SDarrick J. Wong cur->bc_private.a.agno, ltrec.rm_startblock, 7490a1b0b38SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 7500a1b0b38SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 7510a1b0b38SDarrick J. Wong 7520a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(<rec, owner, flags)) 7530a1b0b38SDarrick J. Wong have_lt = 0; 754fa248de9SDarrick J. Wong } 7550a1b0b38SDarrick J. Wong 7560a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 7570a1b0b38SDarrick J. Wong have_lt == 0 || 7580a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); 7590a1b0b38SDarrick J. Wong 7600a1b0b38SDarrick J. Wong /* 7610a1b0b38SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 7620a1b0b38SDarrick J. Wong * insertion point. This will give us the record for end block 7630a1b0b38SDarrick J. Wong * contiguity tests. 7640a1b0b38SDarrick J. Wong */ 7650a1b0b38SDarrick J. Wong error = xfs_btree_increment(cur, 0, &have_gt); 7660a1b0b38SDarrick J. Wong if (error) 7670a1b0b38SDarrick J. Wong goto out_error; 7680a1b0b38SDarrick J. Wong if (have_gt) { 7690a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 7700a1b0b38SDarrick J. Wong if (error) 7710a1b0b38SDarrick J. Wong goto out_error; 7720a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); 7730a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock, 7740a1b0b38SDarrick J. Wong out_error); 7750a1b0b38SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 7760a1b0b38SDarrick J. Wong cur->bc_private.a.agno, gtrec.rm_startblock, 7770a1b0b38SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 7780a1b0b38SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 7790a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 7800a1b0b38SDarrick J. Wong have_gt = 0; 7810a1b0b38SDarrick J. Wong } 7820a1b0b38SDarrick J. Wong 7830a1b0b38SDarrick J. Wong /* 7840a1b0b38SDarrick J. Wong * Note: cursor currently points one record to the right of ltrec, even 7850a1b0b38SDarrick J. Wong * if there is no record in the tree to the right. 7860a1b0b38SDarrick J. Wong */ 7870a1b0b38SDarrick J. Wong if (have_lt && 7880a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 7890a1b0b38SDarrick J. Wong (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { 7900a1b0b38SDarrick J. Wong /* 7910a1b0b38SDarrick J. Wong * left edge contiguous, merge into left record. 7920a1b0b38SDarrick J. Wong * 7930a1b0b38SDarrick J. Wong * ltbno ltlen 7940a1b0b38SDarrick J. Wong * orig: |ooooooooo| 7950a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 7960a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 7970a1b0b38SDarrick J. Wong * bno len 7980a1b0b38SDarrick J. Wong */ 7990a1b0b38SDarrick J. Wong ltrec.rm_blockcount += len; 8000a1b0b38SDarrick J. Wong if (have_gt && 8010a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 8020a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset) && 8030a1b0b38SDarrick J. Wong (unsigned long)ltrec.rm_blockcount + len + 8040a1b0b38SDarrick J. Wong gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { 8050a1b0b38SDarrick J. Wong /* 8060a1b0b38SDarrick J. Wong * right edge also contiguous, delete right record 8070a1b0b38SDarrick J. Wong * and merge into left record. 8080a1b0b38SDarrick J. Wong * 8090a1b0b38SDarrick J. Wong * ltbno ltlen gtbno gtlen 8100a1b0b38SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 8110a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8120a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 8130a1b0b38SDarrick J. Wong */ 8140a1b0b38SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 8150a1b0b38SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 8160a1b0b38SDarrick J. Wong gtrec.rm_startblock, 8170a1b0b38SDarrick J. Wong gtrec.rm_blockcount, 8180a1b0b38SDarrick J. Wong gtrec.rm_owner, 8190a1b0b38SDarrick J. Wong gtrec.rm_offset, 8200a1b0b38SDarrick J. Wong gtrec.rm_flags); 8210a1b0b38SDarrick J. Wong error = xfs_btree_delete(cur, &i); 8220a1b0b38SDarrick J. Wong if (error) 8230a1b0b38SDarrick J. Wong goto out_error; 8240a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 8250a1b0b38SDarrick J. Wong } 8260a1b0b38SDarrick J. Wong 8270a1b0b38SDarrick J. Wong /* point the cursor back to the left record and update */ 8280a1b0b38SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &have_gt); 8290a1b0b38SDarrick J. Wong if (error) 8300a1b0b38SDarrick J. Wong goto out_error; 8310a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 8320a1b0b38SDarrick J. Wong if (error) 8330a1b0b38SDarrick J. Wong goto out_error; 8340a1b0b38SDarrick J. Wong } else if (have_gt && 8350a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 8360a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset)) { 8370a1b0b38SDarrick J. Wong /* 8380a1b0b38SDarrick J. Wong * right edge contiguous, merge into right record. 8390a1b0b38SDarrick J. Wong * 8400a1b0b38SDarrick J. Wong * gtbno gtlen 8410a1b0b38SDarrick J. Wong * Orig: |ooooooooo| 8420a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8430a1b0b38SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 8440a1b0b38SDarrick J. Wong * bno len 8450a1b0b38SDarrick J. Wong */ 8460a1b0b38SDarrick J. Wong gtrec.rm_startblock = bno; 8470a1b0b38SDarrick J. Wong gtrec.rm_blockcount += len; 8480a1b0b38SDarrick J. Wong if (!ignore_off) 8490a1b0b38SDarrick J. Wong gtrec.rm_offset = offset; 8500a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, >rec); 8510a1b0b38SDarrick J. Wong if (error) 8520a1b0b38SDarrick J. Wong goto out_error; 8530a1b0b38SDarrick J. Wong } else { 8540a1b0b38SDarrick J. Wong /* 8550a1b0b38SDarrick J. Wong * no contiguous edge with identical owner, insert 8560a1b0b38SDarrick J. Wong * new record at current cursor position. 8570a1b0b38SDarrick J. Wong */ 8580a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 8590a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 8600a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 8610a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 8620a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 8630a1b0b38SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, 8640a1b0b38SDarrick J. Wong owner, offset, flags); 8650a1b0b38SDarrick J. Wong error = xfs_btree_insert(cur, &i); 8660a1b0b38SDarrick J. Wong if (error) 8670a1b0b38SDarrick J. Wong goto out_error; 8680a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 8690a1b0b38SDarrick J. Wong } 8700a1b0b38SDarrick J. Wong 8710a1b0b38SDarrick J. Wong trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, 8720a1b0b38SDarrick J. Wong unwritten, oinfo); 8730a1b0b38SDarrick J. Wong out_error: 8740a1b0b38SDarrick J. Wong if (error) 8750a1b0b38SDarrick J. Wong trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno, 8760a1b0b38SDarrick J. Wong error, _RET_IP_); 8770a1b0b38SDarrick J. Wong return error; 8780a1b0b38SDarrick J. Wong } 8790a1b0b38SDarrick J. Wong 8800a1b0b38SDarrick J. Wong /* 8810a1b0b38SDarrick J. Wong * Add a reference to an extent in the rmap btree. 8820a1b0b38SDarrick J. Wong */ 883673930c3SDarrick J. Wong int 884673930c3SDarrick J. Wong xfs_rmap_alloc( 885673930c3SDarrick J. Wong struct xfs_trans *tp, 886673930c3SDarrick J. Wong struct xfs_buf *agbp, 887673930c3SDarrick J. Wong xfs_agnumber_t agno, 888673930c3SDarrick J. Wong xfs_agblock_t bno, 889673930c3SDarrick J. Wong xfs_extlen_t len, 89066e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 891673930c3SDarrick J. Wong { 892673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 8930a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur; 8940a1b0b38SDarrick J. Wong int error; 895673930c3SDarrick J. Wong 896673930c3SDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 897673930c3SDarrick J. Wong return 0; 898673930c3SDarrick J. Wong 8990a1b0b38SDarrick J. Wong cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 9000a1b0b38SDarrick J. Wong error = xfs_rmap_map(cur, bno, len, false, oinfo); 9010a1b0b38SDarrick J. Wong 9020b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 903673930c3SDarrick J. Wong return error; 904673930c3SDarrick J. Wong } 905c543838aSDarrick J. Wong 906fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG (1 << 0) 907fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG (1 << 1) 908fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING (1 << 2) 909fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING (1 << 3) 910fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID (1 << 6) 911fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID (1 << 7) 912fb7d9267SDarrick J. Wong 913fb7d9267SDarrick J. Wong #define LEFT r[0] 914fb7d9267SDarrick J. Wong #define RIGHT r[1] 915fb7d9267SDarrick J. Wong #define PREV r[2] 916fb7d9267SDarrick J. Wong #define NEW r[3] 917fb7d9267SDarrick J. Wong 918fb7d9267SDarrick J. Wong /* 919fb7d9267SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. 920fb7d9267SDarrick J. Wong * Does not handle overlapping extents. 921fb7d9267SDarrick J. Wong */ 922fb7d9267SDarrick J. Wong STATIC int 923fb7d9267SDarrick J. Wong xfs_rmap_convert( 924fb7d9267SDarrick J. Wong struct xfs_btree_cur *cur, 925fb7d9267SDarrick J. Wong xfs_agblock_t bno, 926fb7d9267SDarrick J. Wong xfs_extlen_t len, 927fb7d9267SDarrick J. Wong bool unwritten, 92866e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 929fb7d9267SDarrick J. Wong { 930fb7d9267SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 931fb7d9267SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 93266e3237eSDarrick J. Wong /* left is 0, right is 1, */ 93366e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 934fb7d9267SDarrick J. Wong uint64_t owner; 935fb7d9267SDarrick J. Wong uint64_t offset; 936fb7d9267SDarrick J. Wong uint64_t new_endoff; 937fb7d9267SDarrick J. Wong unsigned int oldext; 938fb7d9267SDarrick J. Wong unsigned int newext; 939fb7d9267SDarrick J. Wong unsigned int flags = 0; 940fb7d9267SDarrick J. Wong int i; 941fb7d9267SDarrick J. Wong int state = 0; 942fb7d9267SDarrick J. Wong int error; 943fb7d9267SDarrick J. Wong 944fb7d9267SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 945fb7d9267SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 946fb7d9267SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 947fb7d9267SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 948fb7d9267SDarrick J. Wong new_endoff = offset + len; 949fb7d9267SDarrick J. Wong trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, 950fb7d9267SDarrick J. Wong unwritten, oinfo); 951fb7d9267SDarrick J. Wong 952fb7d9267SDarrick J. Wong /* 953fb7d9267SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 954fb7d9267SDarrick J. Wong * record for our insertion point. This will also give us the record for 955fb7d9267SDarrick J. Wong * start block contiguity tests. 956fb7d9267SDarrick J. Wong */ 957fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); 958fb7d9267SDarrick J. Wong if (error) 959fb7d9267SDarrick J. Wong goto done; 960fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 961fb7d9267SDarrick J. Wong 962fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &PREV, &i); 963fb7d9267SDarrick J. Wong if (error) 964fb7d9267SDarrick J. Wong goto done; 965fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 966fb7d9267SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 967fb7d9267SDarrick J. Wong cur->bc_private.a.agno, PREV.rm_startblock, 968fb7d9267SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 969fb7d9267SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 970fb7d9267SDarrick J. Wong 971fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 972fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 973fb7d9267SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 974fb7d9267SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 975fb7d9267SDarrick J. Wong 976fb7d9267SDarrick J. Wong /* 977fb7d9267SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 978fb7d9267SDarrick J. Wong * extent is being replaced by a newext allocation. 979fb7d9267SDarrick J. Wong */ 980fb7d9267SDarrick J. Wong if (PREV.rm_offset == offset) 981fb7d9267SDarrick J. Wong state |= RMAP_LEFT_FILLING; 982fb7d9267SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 983fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 984fb7d9267SDarrick J. Wong 985fb7d9267SDarrick J. Wong /* 986fb7d9267SDarrick J. Wong * Decrement the cursor to see if we have a left-adjacent record to our 987fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 988fb7d9267SDarrick J. Wong * contiguity tests. 989fb7d9267SDarrick J. Wong */ 990fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 991fb7d9267SDarrick J. Wong if (error) 992fb7d9267SDarrick J. Wong goto done; 993fb7d9267SDarrick J. Wong if (i) { 994fb7d9267SDarrick J. Wong state |= RMAP_LEFT_VALID; 995fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &LEFT, &i); 996fb7d9267SDarrick J. Wong if (error) 997fb7d9267SDarrick J. Wong goto done; 998fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 999fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 1000fb7d9267SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount <= bno, 1001fb7d9267SDarrick J. Wong done); 1002fb7d9267SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 1003fb7d9267SDarrick J. Wong cur->bc_private.a.agno, LEFT.rm_startblock, 1004fb7d9267SDarrick J. Wong LEFT.rm_blockcount, LEFT.rm_owner, 1005fb7d9267SDarrick J. Wong LEFT.rm_offset, LEFT.rm_flags); 1006fb7d9267SDarrick J. Wong if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && 1007fb7d9267SDarrick J. Wong LEFT.rm_offset + LEFT.rm_blockcount == offset && 1008fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&LEFT, owner, newext)) 1009fb7d9267SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 1010fb7d9267SDarrick J. Wong } 1011fb7d9267SDarrick J. Wong 1012fb7d9267SDarrick J. Wong /* 1013fb7d9267SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 1014fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1015fb7d9267SDarrick J. Wong * contiguity tests. 1016fb7d9267SDarrick J. Wong */ 1017fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1018fb7d9267SDarrick J. Wong if (error) 1019fb7d9267SDarrick J. Wong goto done; 1020fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1021fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1022fb7d9267SDarrick J. Wong if (error) 1023fb7d9267SDarrick J. Wong goto done; 1024fb7d9267SDarrick J. Wong if (i) { 1025fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_VALID; 1026fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 1027fb7d9267SDarrick J. Wong if (error) 1028fb7d9267SDarrick J. Wong goto done; 1029fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1030fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, 1031fb7d9267SDarrick J. Wong done); 1032fb7d9267SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 1033fb7d9267SDarrick J. Wong cur->bc_private.a.agno, RIGHT.rm_startblock, 1034fb7d9267SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 1035fb7d9267SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 1036fb7d9267SDarrick J. Wong if (bno + len == RIGHT.rm_startblock && 1037fb7d9267SDarrick J. Wong offset + len == RIGHT.rm_offset && 1038fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 1039fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 1040fb7d9267SDarrick J. Wong } 1041fb7d9267SDarrick J. Wong 1042fb7d9267SDarrick J. Wong /* check that left + prev + right is not too long */ 1043fb7d9267SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1044fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 1045fb7d9267SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1046fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 1047fb7d9267SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 1048fb7d9267SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 1049fb7d9267SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 1050fb7d9267SDarrick J. Wong 1051fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 1052fb7d9267SDarrick J. Wong _RET_IP_); 1053fb7d9267SDarrick J. Wong 1054fb7d9267SDarrick J. Wong /* reset the cursor back to PREV */ 1055fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); 1056fb7d9267SDarrick J. Wong if (error) 1057fb7d9267SDarrick J. Wong goto done; 1058fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1059fb7d9267SDarrick J. Wong 1060fb7d9267SDarrick J. Wong /* 1061fb7d9267SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 1062fb7d9267SDarrick J. Wong */ 1063fb7d9267SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1064fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 1065fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1066fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1067fb7d9267SDarrick J. Wong /* 1068fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1069fb7d9267SDarrick J. Wong * The left and right neighbors are both contiguous with new. 1070fb7d9267SDarrick J. Wong */ 1071fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1072fb7d9267SDarrick J. Wong if (error) 1073fb7d9267SDarrick J. Wong goto done; 1074fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1075fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1076fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1077fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1078fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1079fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1080fb7d9267SDarrick J. Wong if (error) 1081fb7d9267SDarrick J. Wong goto done; 1082fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1083fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1084fb7d9267SDarrick J. Wong if (error) 1085fb7d9267SDarrick J. Wong goto done; 1086fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1087fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1088fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1089fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1090fb7d9267SDarrick J. Wong PREV.rm_flags); 1091fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1092fb7d9267SDarrick J. Wong if (error) 1093fb7d9267SDarrick J. Wong goto done; 1094fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1095fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1096fb7d9267SDarrick J. Wong if (error) 1097fb7d9267SDarrick J. Wong goto done; 1098fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1099fb7d9267SDarrick J. Wong NEW = LEFT; 1100fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 1101fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1102fb7d9267SDarrick J. Wong if (error) 1103fb7d9267SDarrick J. Wong goto done; 1104fb7d9267SDarrick J. Wong break; 1105fb7d9267SDarrick J. Wong 1106fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1107fb7d9267SDarrick J. Wong /* 1108fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1109fb7d9267SDarrick J. Wong * The left neighbor is contiguous, the right is not. 1110fb7d9267SDarrick J. Wong */ 1111fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1112fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1113fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1114fb7d9267SDarrick J. Wong PREV.rm_flags); 1115fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1116fb7d9267SDarrick J. Wong if (error) 1117fb7d9267SDarrick J. Wong goto done; 1118fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1119fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1120fb7d9267SDarrick J. Wong if (error) 1121fb7d9267SDarrick J. Wong goto done; 1122fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1123fb7d9267SDarrick J. Wong NEW = LEFT; 1124fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 1125fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1126fb7d9267SDarrick J. Wong if (error) 1127fb7d9267SDarrick J. Wong goto done; 1128fb7d9267SDarrick J. Wong break; 1129fb7d9267SDarrick J. Wong 1130fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1131fb7d9267SDarrick J. Wong /* 1132fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1133fb7d9267SDarrick J. Wong * The right neighbor is contiguous, the left is not. 1134fb7d9267SDarrick J. Wong */ 1135fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1136fb7d9267SDarrick J. Wong if (error) 1137fb7d9267SDarrick J. Wong goto done; 1138fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1139fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1140fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1141fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1142fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1143fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1144fb7d9267SDarrick J. Wong if (error) 1145fb7d9267SDarrick J. Wong goto done; 1146fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1147fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1148fb7d9267SDarrick J. Wong if (error) 1149fb7d9267SDarrick J. Wong goto done; 1150fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1151fb7d9267SDarrick J. Wong NEW = PREV; 1152fb7d9267SDarrick J. Wong NEW.rm_blockcount = len + RIGHT.rm_blockcount; 1153fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1154fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1155fb7d9267SDarrick J. Wong if (error) 1156fb7d9267SDarrick J. Wong goto done; 1157fb7d9267SDarrick J. Wong break; 1158fb7d9267SDarrick J. Wong 1159fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1160fb7d9267SDarrick J. Wong /* 1161fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1162fb7d9267SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 1163fb7d9267SDarrick J. Wong * the new one. 1164fb7d9267SDarrick J. Wong */ 1165fb7d9267SDarrick J. Wong NEW = PREV; 1166fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1167fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1168fb7d9267SDarrick J. Wong if (error) 1169fb7d9267SDarrick J. Wong goto done; 1170fb7d9267SDarrick J. Wong break; 1171fb7d9267SDarrick J. Wong 1172fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1173fb7d9267SDarrick J. Wong /* 1174fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1175fb7d9267SDarrick J. Wong * The left neighbor is contiguous. 1176fb7d9267SDarrick J. Wong */ 1177fb7d9267SDarrick J. Wong NEW = PREV; 1178fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1179fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1180fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1181fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1182fb7d9267SDarrick J. Wong if (error) 1183fb7d9267SDarrick J. Wong goto done; 1184fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1185fb7d9267SDarrick J. Wong if (error) 1186fb7d9267SDarrick J. Wong goto done; 1187fb7d9267SDarrick J. Wong NEW = LEFT; 1188fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1189fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1190fb7d9267SDarrick J. Wong if (error) 1191fb7d9267SDarrick J. Wong goto done; 1192fb7d9267SDarrick J. Wong break; 1193fb7d9267SDarrick J. Wong 1194fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING: 1195fb7d9267SDarrick J. Wong /* 1196fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1197fb7d9267SDarrick J. Wong * The left neighbor is not contiguous. 1198fb7d9267SDarrick J. Wong */ 1199fb7d9267SDarrick J. Wong NEW = PREV; 1200fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1201fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1202fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1203fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1204fb7d9267SDarrick J. Wong if (error) 1205fb7d9267SDarrick J. Wong goto done; 1206fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1207fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1208fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1209fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1210fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1211fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1212fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, 1213fb7d9267SDarrick J. Wong len, owner, offset, newext); 1214fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1215fb7d9267SDarrick J. Wong if (error) 1216fb7d9267SDarrick J. Wong goto done; 1217fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1218fb7d9267SDarrick J. Wong break; 1219fb7d9267SDarrick J. Wong 1220fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1221fb7d9267SDarrick J. Wong /* 1222fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1223fb7d9267SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 1224fb7d9267SDarrick J. Wong */ 1225fb7d9267SDarrick J. Wong NEW = PREV; 1226fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1227fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1228fb7d9267SDarrick J. Wong if (error) 1229fb7d9267SDarrick J. Wong goto done; 1230fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1231fb7d9267SDarrick J. Wong if (error) 1232fb7d9267SDarrick J. Wong goto done; 1233fb7d9267SDarrick J. Wong NEW = RIGHT; 1234fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1235fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1236fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1237fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1238fb7d9267SDarrick J. Wong if (error) 1239fb7d9267SDarrick J. Wong goto done; 1240fb7d9267SDarrick J. Wong break; 1241fb7d9267SDarrick J. Wong 1242fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING: 1243fb7d9267SDarrick J. Wong /* 1244fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1245fb7d9267SDarrick J. Wong * The right neighbor is not contiguous. 1246fb7d9267SDarrick J. Wong */ 1247fb7d9267SDarrick J. Wong NEW = PREV; 1248fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1249fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1250fb7d9267SDarrick J. Wong if (error) 1251fb7d9267SDarrick J. Wong goto done; 1252fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1253fb7d9267SDarrick J. Wong oldext, &i); 1254fb7d9267SDarrick J. Wong if (error) 1255fb7d9267SDarrick J. Wong goto done; 1256fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); 1257fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1258fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1259fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1260fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1261fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1262fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1263fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, 1264fb7d9267SDarrick J. Wong len, owner, offset, newext); 1265fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1266fb7d9267SDarrick J. Wong if (error) 1267fb7d9267SDarrick J. Wong goto done; 1268fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1269fb7d9267SDarrick J. Wong break; 1270fb7d9267SDarrick J. Wong 1271fb7d9267SDarrick J. Wong case 0: 1272fb7d9267SDarrick J. Wong /* 1273fb7d9267SDarrick J. Wong * Setting the middle part of a previous oldext extent to 1274fb7d9267SDarrick J. Wong * newext. Contiguity is impossible here. 1275fb7d9267SDarrick J. Wong * One extent becomes three extents. 1276fb7d9267SDarrick J. Wong */ 1277fb7d9267SDarrick J. Wong /* new right extent - oldext */ 1278fb7d9267SDarrick J. Wong NEW.rm_startblock = bno + len; 1279fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1280fb7d9267SDarrick J. Wong NEW.rm_offset = new_endoff; 1281fb7d9267SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 1282fb7d9267SDarrick J. Wong new_endoff; 1283fb7d9267SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 1284fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1285fb7d9267SDarrick J. Wong if (error) 1286fb7d9267SDarrick J. Wong goto done; 1287fb7d9267SDarrick J. Wong /* new left extent - oldext */ 1288fb7d9267SDarrick J. Wong NEW = PREV; 1289fb7d9267SDarrick J. Wong NEW.rm_blockcount = offset - PREV.rm_offset; 1290fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1291fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, 1292fb7d9267SDarrick J. Wong NEW.rm_startblock, NEW.rm_blockcount, 1293fb7d9267SDarrick J. Wong NEW.rm_owner, NEW.rm_offset, 1294fb7d9267SDarrick J. Wong NEW.rm_flags); 1295fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1296fb7d9267SDarrick J. Wong if (error) 1297fb7d9267SDarrick J. Wong goto done; 1298fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1299fb7d9267SDarrick J. Wong /* 1300fb7d9267SDarrick J. Wong * Reset the cursor to the position of the new extent 1301fb7d9267SDarrick J. Wong * we are about to insert as we can't trust it after 1302fb7d9267SDarrick J. Wong * the previous insert. 1303fb7d9267SDarrick J. Wong */ 1304fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1305fb7d9267SDarrick J. Wong oldext, &i); 1306fb7d9267SDarrick J. Wong if (error) 1307fb7d9267SDarrick J. Wong goto done; 1308fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); 1309fb7d9267SDarrick J. Wong /* new middle extent - newext */ 1310fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; 1311fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags |= newext; 1312fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, 1313fb7d9267SDarrick J. Wong owner, offset, newext); 1314fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1315fb7d9267SDarrick J. Wong if (error) 1316fb7d9267SDarrick J. Wong goto done; 1317fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1318fb7d9267SDarrick J. Wong break; 1319fb7d9267SDarrick J. Wong 1320fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1321fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1322fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 1323fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1324fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1325fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG: 1326fb7d9267SDarrick J. Wong case RMAP_RIGHT_CONTIG: 1327fb7d9267SDarrick J. Wong /* 1328fb7d9267SDarrick J. Wong * These cases are all impossible. 1329fb7d9267SDarrick J. Wong */ 1330fb7d9267SDarrick J. Wong ASSERT(0); 1331fb7d9267SDarrick J. Wong } 1332fb7d9267SDarrick J. Wong 1333fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, 1334fb7d9267SDarrick J. Wong unwritten, oinfo); 1335fb7d9267SDarrick J. Wong done: 1336fb7d9267SDarrick J. Wong if (error) 1337fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 1338fb7d9267SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 1339fb7d9267SDarrick J. Wong return error; 1340fb7d9267SDarrick J. Wong } 1341fb7d9267SDarrick J. Wong 13423f165b33SDarrick J. Wong /* 13433f165b33SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. If there is no 13443f165b33SDarrick J. Wong * possibility of overlapping extents, delegate to the simpler convert 13453f165b33SDarrick J. Wong * function. 13463f165b33SDarrick J. Wong */ 13473f165b33SDarrick J. Wong STATIC int 13483f165b33SDarrick J. Wong xfs_rmap_convert_shared( 13493f165b33SDarrick J. Wong struct xfs_btree_cur *cur, 13503f165b33SDarrick J. Wong xfs_agblock_t bno, 13513f165b33SDarrick J. Wong xfs_extlen_t len, 13523f165b33SDarrick J. Wong bool unwritten, 135366e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 13543f165b33SDarrick J. Wong { 13553f165b33SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 13563f165b33SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 135766e3237eSDarrick J. Wong /* left is 0, right is 1, */ 135866e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 13593f165b33SDarrick J. Wong uint64_t owner; 13603f165b33SDarrick J. Wong uint64_t offset; 13613f165b33SDarrick J. Wong uint64_t new_endoff; 13623f165b33SDarrick J. Wong unsigned int oldext; 13633f165b33SDarrick J. Wong unsigned int newext; 13643f165b33SDarrick J. Wong unsigned int flags = 0; 13653f165b33SDarrick J. Wong int i; 13663f165b33SDarrick J. Wong int state = 0; 13673f165b33SDarrick J. Wong int error; 13683f165b33SDarrick J. Wong 13693f165b33SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 13703f165b33SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 13713f165b33SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 13723f165b33SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 13733f165b33SDarrick J. Wong new_endoff = offset + len; 13743f165b33SDarrick J. Wong trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, 13753f165b33SDarrick J. Wong unwritten, oinfo); 13763f165b33SDarrick J. Wong 13773f165b33SDarrick J. Wong /* 13783f165b33SDarrick J. Wong * For the initial lookup, look for and exact match or the left-adjacent 13793f165b33SDarrick J. Wong * record for our insertion point. This will also give us the record for 13803f165b33SDarrick J. Wong * start block contiguity tests. 13813f165b33SDarrick J. Wong */ 13823f165b33SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 13833f165b33SDarrick J. Wong &PREV, &i); 138452101dfeSDarrick J. Wong if (error) 138552101dfeSDarrick J. Wong goto done; 13863f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 13873f165b33SDarrick J. Wong 13883f165b33SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 13893f165b33SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 13903f165b33SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 13913f165b33SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 13923f165b33SDarrick J. Wong 13933f165b33SDarrick J. Wong /* 13943f165b33SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 13953f165b33SDarrick J. Wong * extent is being replaced by a newext allocation. 13963f165b33SDarrick J. Wong */ 13973f165b33SDarrick J. Wong if (PREV.rm_offset == offset) 13983f165b33SDarrick J. Wong state |= RMAP_LEFT_FILLING; 13993f165b33SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 14003f165b33SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 14013f165b33SDarrick J. Wong 14023f165b33SDarrick J. Wong /* Is there a left record that abuts our range? */ 14033f165b33SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, 14043f165b33SDarrick J. Wong &LEFT, &i); 14053f165b33SDarrick J. Wong if (error) 14063f165b33SDarrick J. Wong goto done; 14073f165b33SDarrick J. Wong if (i) { 14083f165b33SDarrick J. Wong state |= RMAP_LEFT_VALID; 14093f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 14103f165b33SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount <= bno, 14113f165b33SDarrick J. Wong done); 14123f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) 14133f165b33SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 14143f165b33SDarrick J. Wong } 14153f165b33SDarrick J. Wong 14163f165b33SDarrick J. Wong /* Is there a right record that abuts our range? */ 14173f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 14183f165b33SDarrick J. Wong newext, &i); 14193f165b33SDarrick J. Wong if (error) 14203f165b33SDarrick J. Wong goto done; 14213f165b33SDarrick J. Wong if (i) { 14223f165b33SDarrick J. Wong state |= RMAP_RIGHT_VALID; 14233f165b33SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 14243f165b33SDarrick J. Wong if (error) 14253f165b33SDarrick J. Wong goto done; 14263f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 14273f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, 14283f165b33SDarrick J. Wong done); 14293f165b33SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 14303f165b33SDarrick J. Wong cur->bc_private.a.agno, RIGHT.rm_startblock, 14313f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 14323f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 14333f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 14343f165b33SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 14353f165b33SDarrick J. Wong } 14363f165b33SDarrick J. Wong 14373f165b33SDarrick J. Wong /* check that left + prev + right is not too long */ 14383f165b33SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14393f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 14403f165b33SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14413f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 14423f165b33SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 14433f165b33SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 14443f165b33SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 14453f165b33SDarrick J. Wong 14463f165b33SDarrick J. Wong trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 14473f165b33SDarrick J. Wong _RET_IP_); 14483f165b33SDarrick J. Wong /* 14493f165b33SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 14503f165b33SDarrick J. Wong */ 14513f165b33SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14523f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 14533f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14543f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 14553f165b33SDarrick J. Wong /* 14563f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 14573f165b33SDarrick J. Wong * The left and right neighbors are both contiguous with new. 14583f165b33SDarrick J. Wong */ 14593f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 14603f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 14613f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 14623f165b33SDarrick J. Wong if (error) 14633f165b33SDarrick J. Wong goto done; 14643f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 14653f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 14663f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 14673f165b33SDarrick J. Wong if (error) 14683f165b33SDarrick J. Wong goto done; 14693f165b33SDarrick J. Wong NEW = LEFT; 14703f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 14713f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 14723f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 14733f165b33SDarrick J. Wong if (error) 14743f165b33SDarrick J. Wong goto done; 14753f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 14763f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 14773f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 14783f165b33SDarrick J. Wong if (error) 14793f165b33SDarrick J. Wong goto done; 14803f165b33SDarrick J. Wong break; 14813f165b33SDarrick J. Wong 14823f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 14833f165b33SDarrick J. Wong /* 14843f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 14853f165b33SDarrick J. Wong * The left neighbor is contiguous, the right is not. 14863f165b33SDarrick J. Wong */ 14873f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 14883f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 14893f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 14903f165b33SDarrick J. Wong if (error) 14913f165b33SDarrick J. Wong goto done; 14923f165b33SDarrick J. Wong NEW = LEFT; 14933f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 14943f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 14953f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 14963f165b33SDarrick J. Wong if (error) 14973f165b33SDarrick J. Wong goto done; 14983f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 14993f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 15003f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15013f165b33SDarrick J. Wong if (error) 15023f165b33SDarrick J. Wong goto done; 15033f165b33SDarrick J. Wong break; 15043f165b33SDarrick J. Wong 15053f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 15063f165b33SDarrick J. Wong /* 15073f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 15083f165b33SDarrick J. Wong * The right neighbor is contiguous, the left is not. 15093f165b33SDarrick J. Wong */ 15103f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 15113f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 15123f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 15133f165b33SDarrick J. Wong if (error) 15143f165b33SDarrick J. Wong goto done; 15153f165b33SDarrick J. Wong NEW = PREV; 15163f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 15173f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15183f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 15193f165b33SDarrick J. Wong if (error) 15203f165b33SDarrick J. Wong goto done; 15213f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 15223f165b33SDarrick J. Wong NEW.rm_blockcount += RIGHT.rm_blockcount; 15233f165b33SDarrick J. Wong NEW.rm_flags = RIGHT.rm_flags; 15243f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15253f165b33SDarrick J. Wong if (error) 15263f165b33SDarrick J. Wong goto done; 15273f165b33SDarrick J. Wong break; 15283f165b33SDarrick J. Wong 15293f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 15303f165b33SDarrick J. Wong /* 15313f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 15323f165b33SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 15333f165b33SDarrick J. Wong * the new one. 15343f165b33SDarrick J. Wong */ 15353f165b33SDarrick J. Wong NEW = PREV; 15363f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 15373f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15383f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 15393f165b33SDarrick J. Wong if (error) 15403f165b33SDarrick J. Wong goto done; 15413f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 15423f165b33SDarrick J. Wong NEW.rm_flags = newext; 15433f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15443f165b33SDarrick J. Wong if (error) 15453f165b33SDarrick J. Wong goto done; 15463f165b33SDarrick J. Wong break; 15473f165b33SDarrick J. Wong 15483f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 15493f165b33SDarrick J. Wong /* 15503f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 15513f165b33SDarrick J. Wong * The left neighbor is contiguous. 15523f165b33SDarrick J. Wong */ 15533f165b33SDarrick J. Wong NEW = PREV; 15543f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 15553f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15563f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15573f165b33SDarrick J. Wong if (error) 15583f165b33SDarrick J. Wong goto done; 15593f165b33SDarrick J. Wong NEW.rm_offset += len; 15603f165b33SDarrick J. Wong NEW.rm_startblock += len; 15613f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 15623f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 15633f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15643f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15653f165b33SDarrick J. Wong if (error) 15663f165b33SDarrick J. Wong goto done; 15673f165b33SDarrick J. Wong NEW = LEFT; 15683f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 15693f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15703f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 15713f165b33SDarrick J. Wong if (error) 15723f165b33SDarrick J. Wong goto done; 15733f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 15743f165b33SDarrick J. Wong NEW.rm_blockcount += len; 15753f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15763f165b33SDarrick J. Wong if (error) 15773f165b33SDarrick J. Wong goto done; 15783f165b33SDarrick J. Wong break; 15793f165b33SDarrick J. Wong 15803f165b33SDarrick J. Wong case RMAP_LEFT_FILLING: 15813f165b33SDarrick J. Wong /* 15823f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 15833f165b33SDarrick J. Wong * The left neighbor is not contiguous. 15843f165b33SDarrick J. Wong */ 15853f165b33SDarrick J. Wong NEW = PREV; 15863f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 15873f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15883f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15893f165b33SDarrick J. Wong if (error) 15903f165b33SDarrick J. Wong goto done; 15913f165b33SDarrick J. Wong NEW.rm_offset += len; 15923f165b33SDarrick J. Wong NEW.rm_startblock += len; 15933f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 15943f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 15953f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15963f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15973f165b33SDarrick J. Wong if (error) 15983f165b33SDarrick J. Wong goto done; 15993f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 16003f165b33SDarrick J. Wong if (error) 16013f165b33SDarrick J. Wong goto done; 16023f165b33SDarrick J. Wong break; 16033f165b33SDarrick J. Wong 16043f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 16053f165b33SDarrick J. Wong /* 16063f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 16073f165b33SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 16083f165b33SDarrick J. Wong */ 16093f165b33SDarrick J. Wong NEW = PREV; 16103f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16113f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16123f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16133f165b33SDarrick J. Wong if (error) 16143f165b33SDarrick J. Wong goto done; 16153f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 16163f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 16173f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16183f165b33SDarrick J. Wong if (error) 16193f165b33SDarrick J. Wong goto done; 16203f165b33SDarrick J. Wong NEW = RIGHT; 16213f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 16223f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16233f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 16243f165b33SDarrick J. Wong if (error) 16253f165b33SDarrick J. Wong goto done; 16263f165b33SDarrick J. Wong NEW.rm_offset = offset; 16273f165b33SDarrick J. Wong NEW.rm_startblock = bno; 16283f165b33SDarrick J. Wong NEW.rm_blockcount += len; 16293f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 16303f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16313f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 16323f165b33SDarrick J. Wong if (error) 16333f165b33SDarrick J. Wong goto done; 16343f165b33SDarrick J. Wong break; 16353f165b33SDarrick J. Wong 16363f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING: 16373f165b33SDarrick J. Wong /* 16383f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 16393f165b33SDarrick J. Wong * The right neighbor is not contiguous. 16403f165b33SDarrick J. Wong */ 16413f165b33SDarrick J. Wong NEW = PREV; 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; 16473f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 16483f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 16493f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16503f165b33SDarrick J. Wong if (error) 16513f165b33SDarrick J. Wong goto done; 16523f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 16533f165b33SDarrick J. Wong if (error) 16543f165b33SDarrick J. Wong goto done; 16553f165b33SDarrick J. Wong break; 16563f165b33SDarrick J. Wong 16573f165b33SDarrick J. Wong case 0: 16583f165b33SDarrick J. Wong /* 16593f165b33SDarrick J. Wong * Setting the middle part of a previous oldext extent to 16603f165b33SDarrick J. Wong * newext. Contiguity is impossible here. 16613f165b33SDarrick J. Wong * One extent becomes three extents. 16623f165b33SDarrick J. Wong */ 16633f165b33SDarrick J. Wong /* new right extent - oldext */ 16643f165b33SDarrick J. Wong NEW.rm_startblock = bno + len; 16653f165b33SDarrick J. Wong NEW.rm_owner = owner; 16663f165b33SDarrick J. Wong NEW.rm_offset = new_endoff; 16673f165b33SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 16683f165b33SDarrick J. Wong new_endoff; 16693f165b33SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 16703f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 16713f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 16723f165b33SDarrick J. Wong NEW.rm_flags); 16733f165b33SDarrick J. Wong if (error) 16743f165b33SDarrick J. Wong goto done; 16753f165b33SDarrick J. Wong /* new left extent - oldext */ 16763f165b33SDarrick J. Wong NEW = PREV; 16773f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16783f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16793f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16803f165b33SDarrick J. Wong if (error) 16813f165b33SDarrick J. Wong goto done; 16823f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 16833f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 16843f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16853f165b33SDarrick J. Wong if (error) 16863f165b33SDarrick J. Wong goto done; 16873f165b33SDarrick J. Wong /* new middle extent - newext */ 16883f165b33SDarrick J. Wong NEW.rm_startblock = bno; 16893f165b33SDarrick J. Wong NEW.rm_blockcount = len; 16903f165b33SDarrick J. Wong NEW.rm_owner = owner; 16913f165b33SDarrick J. Wong NEW.rm_offset = offset; 16923f165b33SDarrick J. Wong NEW.rm_flags = newext; 16933f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 16943f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 16953f165b33SDarrick J. Wong NEW.rm_flags); 16963f165b33SDarrick J. Wong if (error) 16973f165b33SDarrick J. Wong goto done; 16983f165b33SDarrick J. Wong break; 16993f165b33SDarrick J. Wong 17003f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 17013f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 17023f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 17033f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 17043f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 17053f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG: 17063f165b33SDarrick J. Wong case RMAP_RIGHT_CONTIG: 17073f165b33SDarrick J. Wong /* 17083f165b33SDarrick J. Wong * These cases are all impossible. 17093f165b33SDarrick J. Wong */ 17103f165b33SDarrick J. Wong ASSERT(0); 17113f165b33SDarrick J. Wong } 17123f165b33SDarrick J. Wong 17133f165b33SDarrick J. Wong trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, 17143f165b33SDarrick J. Wong unwritten, oinfo); 17153f165b33SDarrick J. Wong done: 17163f165b33SDarrick J. Wong if (error) 17173f165b33SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 17183f165b33SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 17193f165b33SDarrick J. Wong return error; 17203f165b33SDarrick J. Wong } 17213f165b33SDarrick J. Wong 1722fb7d9267SDarrick J. Wong #undef NEW 1723fb7d9267SDarrick J. Wong #undef LEFT 1724fb7d9267SDarrick J. Wong #undef RIGHT 1725fb7d9267SDarrick J. Wong #undef PREV 1726fb7d9267SDarrick J. Wong 1727ceeb9c83SDarrick J. Wong /* 1728ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and unmap it. For rmap extent types that 1729ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1730ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1731ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1732ceeb9c83SDarrick J. Wong * 1733ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1734ceeb9c83SDarrick J. Wong * so we can call the regular _free function. 1735ceeb9c83SDarrick J. Wong */ 1736ceeb9c83SDarrick J. Wong STATIC int 1737ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared( 1738ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1739ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1740ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1741ceeb9c83SDarrick J. Wong bool unwritten, 174266e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1743ceeb9c83SDarrick J. Wong { 1744ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1745ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 1746ceeb9c83SDarrick J. Wong uint64_t ltoff; 1747ceeb9c83SDarrick J. Wong int error = 0; 1748ceeb9c83SDarrick J. Wong int i; 1749ceeb9c83SDarrick J. Wong uint64_t owner; 1750ceeb9c83SDarrick J. Wong uint64_t offset; 1751ceeb9c83SDarrick J. Wong unsigned int flags; 1752ceeb9c83SDarrick J. Wong 1753ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1754ceeb9c83SDarrick J. Wong if (unwritten) 1755ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 1756ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, 1757ceeb9c83SDarrick J. Wong unwritten, oinfo); 1758ceeb9c83SDarrick J. Wong 1759ceeb9c83SDarrick J. Wong /* 1760ceeb9c83SDarrick J. Wong * We should always have a left record because there's a static record 1761ceeb9c83SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 1762ceeb9c83SDarrick J. Wong * will not ever be removed from the tree. 1763ceeb9c83SDarrick J. Wong */ 1764ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 1765ceeb9c83SDarrick J. Wong <rec, &i); 1766ceeb9c83SDarrick J. Wong if (error) 1767ceeb9c83SDarrick J. Wong goto out_error; 1768ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1769ceeb9c83SDarrick J. Wong ltoff = ltrec.rm_offset; 1770ceeb9c83SDarrick J. Wong 1771ceeb9c83SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 1772ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && 1773ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount >= 1774ceeb9c83SDarrick J. Wong bno + len, out_error); 1775ceeb9c83SDarrick J. Wong 1776ceeb9c83SDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 1777ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error); 1778ceeb9c83SDarrick J. Wong 1779ceeb9c83SDarrick J. Wong /* Make sure the unwritten flag matches. */ 1780ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == 1781ceeb9c83SDarrick J. Wong (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); 1782ceeb9c83SDarrick J. Wong 1783ceeb9c83SDarrick J. Wong /* Check the offset. */ 1784ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); 1785ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount, 1786ceeb9c83SDarrick J. Wong out_error); 1787ceeb9c83SDarrick J. Wong 1788ceeb9c83SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 1789ceeb9c83SDarrick J. Wong /* Exact match, simply remove the record from rmap tree. */ 1790ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 1791ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1792ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1793ceeb9c83SDarrick J. Wong if (error) 1794ceeb9c83SDarrick J. Wong goto out_error; 1795ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 1796ceeb9c83SDarrick J. Wong /* 1797ceeb9c83SDarrick J. Wong * Overlap left hand side of extent: move the start, trim the 1798ceeb9c83SDarrick J. Wong * length and update the current record. 1799ceeb9c83SDarrick J. Wong * 1800ceeb9c83SDarrick J. Wong * ltbno ltlen 1801ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1802ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1803ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 1804ceeb9c83SDarrick J. Wong * bno len 1805ceeb9c83SDarrick J. Wong */ 1806ceeb9c83SDarrick J. Wong 1807ceeb9c83SDarrick J. Wong /* Delete prev rmap. */ 1808ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 1809ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1810ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1811ceeb9c83SDarrick J. Wong if (error) 1812ceeb9c83SDarrick J. Wong goto out_error; 1813ceeb9c83SDarrick J. Wong 1814ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset. */ 1815ceeb9c83SDarrick J. Wong ltrec.rm_startblock += len; 1816ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 1817ceeb9c83SDarrick J. Wong ltrec.rm_offset += len; 1818ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, ltrec.rm_startblock, 1819ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1820ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1821ceeb9c83SDarrick J. Wong if (error) 1822ceeb9c83SDarrick J. Wong goto out_error; 1823ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 1824ceeb9c83SDarrick J. Wong /* 1825ceeb9c83SDarrick J. Wong * Overlap right hand side of extent: trim the length and 1826ceeb9c83SDarrick J. Wong * update the current record. 1827ceeb9c83SDarrick J. Wong * 1828ceeb9c83SDarrick J. Wong * ltbno ltlen 1829ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1830ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1831ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 1832ceeb9c83SDarrick J. Wong * bno len 1833ceeb9c83SDarrick J. Wong */ 1834ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 1835ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1836ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 1837ceeb9c83SDarrick J. Wong if (error) 1838ceeb9c83SDarrick J. Wong goto out_error; 1839ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1840ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 1841ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 1842ceeb9c83SDarrick J. Wong if (error) 1843ceeb9c83SDarrick J. Wong goto out_error; 1844ceeb9c83SDarrick J. Wong } else { 1845ceeb9c83SDarrick J. Wong /* 1846ceeb9c83SDarrick J. Wong * Overlap middle of extent: trim the length of the existing 1847ceeb9c83SDarrick J. Wong * record to the length of the new left-extent size, increment 1848ceeb9c83SDarrick J. Wong * the insertion position so we can insert a new record 1849ceeb9c83SDarrick J. Wong * containing the remaining right-extent space. 1850ceeb9c83SDarrick J. Wong * 1851ceeb9c83SDarrick J. Wong * ltbno ltlen 1852ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1853ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1854ceeb9c83SDarrick J. Wong * Result: |rrrrr| |rrrr| 1855ceeb9c83SDarrick J. Wong * bno len 1856ceeb9c83SDarrick J. Wong */ 1857ceeb9c83SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 1858ceeb9c83SDarrick J. Wong 1859ceeb9c83SDarrick J. Wong /* Shrink the left side of the rmap */ 1860ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 1861ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1862ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 1863ceeb9c83SDarrick J. Wong if (error) 1864ceeb9c83SDarrick J. Wong goto out_error; 1865ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1866ceeb9c83SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 1867ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 1868ceeb9c83SDarrick J. Wong if (error) 1869ceeb9c83SDarrick J. Wong goto out_error; 1870ceeb9c83SDarrick J. Wong 1871ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset */ 1872ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno + len, 1873ceeb9c83SDarrick J. Wong orig_len - len - ltrec.rm_blockcount, 1874ceeb9c83SDarrick J. Wong ltrec.rm_owner, offset + len, 1875ceeb9c83SDarrick J. Wong ltrec.rm_flags); 1876ceeb9c83SDarrick J. Wong if (error) 1877ceeb9c83SDarrick J. Wong goto out_error; 1878ceeb9c83SDarrick J. Wong } 1879ceeb9c83SDarrick J. Wong 1880ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, 1881ceeb9c83SDarrick J. Wong unwritten, oinfo); 1882ceeb9c83SDarrick J. Wong out_error: 1883ceeb9c83SDarrick J. Wong if (error) 1884ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_error(cur->bc_mp, 1885ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 1886ceeb9c83SDarrick J. Wong return error; 1887ceeb9c83SDarrick J. Wong } 1888ceeb9c83SDarrick J. Wong 1889ceeb9c83SDarrick J. Wong /* 1890ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and map it. For rmap extent types that 1891ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1892ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1893ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1894ceeb9c83SDarrick J. Wong * 1895ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1896ceeb9c83SDarrick J. Wong * so we can call the regular _alloc function. 1897ceeb9c83SDarrick J. Wong */ 1898ceeb9c83SDarrick J. Wong STATIC int 1899ceeb9c83SDarrick J. Wong xfs_rmap_map_shared( 1900ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1901ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1902ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1903ceeb9c83SDarrick J. Wong bool unwritten, 190466e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1905ceeb9c83SDarrick J. Wong { 1906ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1907ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 1908ceeb9c83SDarrick J. Wong struct xfs_rmap_irec gtrec; 1909ceeb9c83SDarrick J. Wong int have_gt; 1910ceeb9c83SDarrick J. Wong int have_lt; 1911ceeb9c83SDarrick J. Wong int error = 0; 1912ceeb9c83SDarrick J. Wong int i; 1913ceeb9c83SDarrick J. Wong uint64_t owner; 1914ceeb9c83SDarrick J. Wong uint64_t offset; 1915ceeb9c83SDarrick J. Wong unsigned int flags = 0; 1916ceeb9c83SDarrick J. Wong 1917ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1918ceeb9c83SDarrick J. Wong if (unwritten) 1919ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 1920ceeb9c83SDarrick J. Wong trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 1921ceeb9c83SDarrick J. Wong unwritten, oinfo); 1922ceeb9c83SDarrick J. Wong 1923ceeb9c83SDarrick J. Wong /* Is there a left record that abuts our range? */ 1924ceeb9c83SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, 1925ceeb9c83SDarrick J. Wong <rec, &have_lt); 1926ceeb9c83SDarrick J. Wong if (error) 1927ceeb9c83SDarrick J. Wong goto out_error; 1928ceeb9c83SDarrick J. Wong if (have_lt && 1929ceeb9c83SDarrick J. Wong !xfs_rmap_is_mergeable(<rec, owner, flags)) 1930ceeb9c83SDarrick J. Wong have_lt = 0; 1931ceeb9c83SDarrick J. Wong 1932ceeb9c83SDarrick J. Wong /* Is there a right record that abuts our range? */ 1933ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 1934ceeb9c83SDarrick J. Wong flags, &have_gt); 1935ceeb9c83SDarrick J. Wong if (error) 1936ceeb9c83SDarrick J. Wong goto out_error; 1937ceeb9c83SDarrick J. Wong if (have_gt) { 1938ceeb9c83SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 1939ceeb9c83SDarrick J. Wong if (error) 1940ceeb9c83SDarrick J. Wong goto out_error; 1941ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); 1942ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 1943ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, gtrec.rm_startblock, 1944ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 1945ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 1946ceeb9c83SDarrick J. Wong 1947ceeb9c83SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 1948ceeb9c83SDarrick J. Wong have_gt = 0; 1949ceeb9c83SDarrick J. Wong } 1950ceeb9c83SDarrick J. Wong 1951ceeb9c83SDarrick J. Wong if (have_lt && 1952ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 1953ceeb9c83SDarrick J. Wong ltrec.rm_offset + ltrec.rm_blockcount == offset) { 1954ceeb9c83SDarrick J. Wong /* 1955ceeb9c83SDarrick J. Wong * Left edge contiguous, merge into left record. 1956ceeb9c83SDarrick J. Wong * 1957ceeb9c83SDarrick J. Wong * ltbno ltlen 1958ceeb9c83SDarrick J. Wong * orig: |ooooooooo| 1959ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 1960ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 1961ceeb9c83SDarrick J. Wong * bno len 1962ceeb9c83SDarrick J. Wong */ 1963ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += len; 1964ceeb9c83SDarrick J. Wong if (have_gt && 1965ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 1966ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 1967ceeb9c83SDarrick J. Wong /* 1968ceeb9c83SDarrick J. Wong * Right edge also contiguous, delete right record 1969ceeb9c83SDarrick J. Wong * and merge into left record. 1970ceeb9c83SDarrick J. Wong * 1971ceeb9c83SDarrick J. Wong * ltbno ltlen gtbno gtlen 1972ceeb9c83SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 1973ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 1974ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 1975ceeb9c83SDarrick J. Wong */ 1976ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 1977ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 1978ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 1979ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 1980ceeb9c83SDarrick J. Wong if (error) 1981ceeb9c83SDarrick J. Wong goto out_error; 1982ceeb9c83SDarrick J. Wong } 1983ceeb9c83SDarrick J. Wong 1984ceeb9c83SDarrick J. Wong /* Point the cursor back to the left record and update. */ 1985ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 1986ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1987ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 1988ceeb9c83SDarrick J. Wong if (error) 1989ceeb9c83SDarrick J. Wong goto out_error; 1990ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1991ceeb9c83SDarrick J. Wong 1992ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 1993ceeb9c83SDarrick J. Wong if (error) 1994ceeb9c83SDarrick J. Wong goto out_error; 1995ceeb9c83SDarrick J. Wong } else if (have_gt && 1996ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 1997ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 1998ceeb9c83SDarrick J. Wong /* 1999ceeb9c83SDarrick J. Wong * Right edge contiguous, merge into right record. 2000ceeb9c83SDarrick J. Wong * 2001ceeb9c83SDarrick J. Wong * gtbno gtlen 2002ceeb9c83SDarrick J. Wong * Orig: |ooooooooo| 2003ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2004ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 2005ceeb9c83SDarrick J. Wong * bno len 2006ceeb9c83SDarrick J. Wong */ 2007ceeb9c83SDarrick J. Wong /* Delete the old record. */ 2008ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2009ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2010ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2011ceeb9c83SDarrick J. Wong if (error) 2012ceeb9c83SDarrick J. Wong goto out_error; 2013ceeb9c83SDarrick J. Wong 2014ceeb9c83SDarrick J. Wong /* Move the start and re-add it. */ 2015ceeb9c83SDarrick J. Wong gtrec.rm_startblock = bno; 2016ceeb9c83SDarrick J. Wong gtrec.rm_blockcount += len; 2017ceeb9c83SDarrick J. Wong gtrec.rm_offset = offset; 2018ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, gtrec.rm_startblock, 2019ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2020ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2021ceeb9c83SDarrick J. Wong if (error) 2022ceeb9c83SDarrick J. Wong goto out_error; 2023ceeb9c83SDarrick J. Wong } else { 2024ceeb9c83SDarrick J. Wong /* 2025ceeb9c83SDarrick J. Wong * No contiguous edge with identical owner, insert 2026ceeb9c83SDarrick J. Wong * new record at current cursor position. 2027ceeb9c83SDarrick J. Wong */ 2028ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); 2029ceeb9c83SDarrick J. Wong if (error) 2030ceeb9c83SDarrick J. Wong goto out_error; 2031ceeb9c83SDarrick J. Wong } 2032ceeb9c83SDarrick J. Wong 2033ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, 2034ceeb9c83SDarrick J. Wong unwritten, oinfo); 2035ceeb9c83SDarrick J. Wong out_error: 2036ceeb9c83SDarrick J. Wong if (error) 2037ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_error(cur->bc_mp, 2038ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 2039ceeb9c83SDarrick J. Wong return error; 2040ceeb9c83SDarrick J. Wong } 2041ceeb9c83SDarrick J. Wong 20424d4f86b4SDarrick J. Wong /* Insert a raw rmap into the rmapbt. */ 20434d4f86b4SDarrick J. Wong int 20444d4f86b4SDarrick J. Wong xfs_rmap_map_raw( 20454d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 20464d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rmap) 20474d4f86b4SDarrick J. Wong { 20484d4f86b4SDarrick J. Wong struct xfs_owner_info oinfo; 20494d4f86b4SDarrick J. Wong 20504d4f86b4SDarrick J. Wong oinfo.oi_owner = rmap->rm_owner; 20514d4f86b4SDarrick J. Wong oinfo.oi_offset = rmap->rm_offset; 20524d4f86b4SDarrick J. Wong oinfo.oi_flags = 0; 20534d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_ATTR_FORK) 20544d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK; 20554d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK) 20564d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; 20574d4f86b4SDarrick J. Wong 20584d4f86b4SDarrick J. Wong if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner)) 20594d4f86b4SDarrick J. Wong return xfs_rmap_map(cur, rmap->rm_startblock, 20604d4f86b4SDarrick J. Wong rmap->rm_blockcount, 20614d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 20624d4f86b4SDarrick J. Wong &oinfo); 20634d4f86b4SDarrick J. Wong 20644d4f86b4SDarrick J. Wong return xfs_rmap_map_shared(cur, rmap->rm_startblock, 20654d4f86b4SDarrick J. Wong rmap->rm_blockcount, 20664d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 20674d4f86b4SDarrick J. Wong &oinfo); 20684d4f86b4SDarrick J. Wong } 20694d4f86b4SDarrick J. Wong 2070c543838aSDarrick J. Wong struct xfs_rmap_query_range_info { 2071c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn; 2072c543838aSDarrick J. Wong void *priv; 2073c543838aSDarrick J. Wong }; 2074c543838aSDarrick J. Wong 2075c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */ 2076c543838aSDarrick J. Wong STATIC int 2077c543838aSDarrick J. Wong xfs_rmap_query_range_helper( 2078c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2079c543838aSDarrick J. Wong union xfs_btree_rec *rec, 2080c543838aSDarrick J. Wong void *priv) 2081c543838aSDarrick J. Wong { 2082c543838aSDarrick J. Wong struct xfs_rmap_query_range_info *query = priv; 2083c543838aSDarrick J. Wong struct xfs_rmap_irec irec; 2084c543838aSDarrick J. Wong int error; 2085c543838aSDarrick J. Wong 2086c543838aSDarrick J. Wong error = xfs_rmap_btrec_to_irec(rec, &irec); 2087c543838aSDarrick J. Wong if (error) 2088c543838aSDarrick J. Wong return error; 2089c543838aSDarrick J. Wong return query->fn(cur, &irec, query->priv); 2090c543838aSDarrick J. Wong } 2091c543838aSDarrick J. Wong 2092c543838aSDarrick J. Wong /* Find all rmaps between two keys. */ 2093c543838aSDarrick J. Wong int 2094c543838aSDarrick J. Wong xfs_rmap_query_range( 2095c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2096c543838aSDarrick J. Wong struct xfs_rmap_irec *low_rec, 2097c543838aSDarrick J. Wong struct xfs_rmap_irec *high_rec, 2098c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2099c543838aSDarrick J. Wong void *priv) 2100c543838aSDarrick J. Wong { 2101c543838aSDarrick J. Wong union xfs_btree_irec low_brec; 2102c543838aSDarrick J. Wong union xfs_btree_irec high_brec; 2103c543838aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2104c543838aSDarrick J. Wong 2105c543838aSDarrick J. Wong low_brec.r = *low_rec; 2106c543838aSDarrick J. Wong high_brec.r = *high_rec; 2107c543838aSDarrick J. Wong query.priv = priv; 2108c543838aSDarrick J. Wong query.fn = fn; 2109c543838aSDarrick J. Wong return xfs_btree_query_range(cur, &low_brec, &high_brec, 2110c543838aSDarrick J. Wong xfs_rmap_query_range_helper, &query); 2111e9a2599aSDarrick J. Wong } 2112e9a2599aSDarrick J. Wong 2113e9a2599aSDarrick J. Wong /* Find all rmaps. */ 2114e9a2599aSDarrick J. Wong int 2115e9a2599aSDarrick J. Wong xfs_rmap_query_all( 2116e9a2599aSDarrick J. Wong struct xfs_btree_cur *cur, 2117e9a2599aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2118e9a2599aSDarrick J. Wong void *priv) 2119e9a2599aSDarrick J. Wong { 2120e9a2599aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2121e9a2599aSDarrick J. Wong 2122e9a2599aSDarrick J. Wong query.priv = priv; 2123e9a2599aSDarrick J. Wong query.fn = fn; 2124e9a2599aSDarrick J. Wong return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query); 2125c543838aSDarrick J. Wong } 21269c194644SDarrick J. Wong 21279c194644SDarrick J. Wong /* Clean up after calling xfs_rmap_finish_one. */ 21289c194644SDarrick J. Wong void 21299c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup( 21309c194644SDarrick J. Wong struct xfs_trans *tp, 21319c194644SDarrick J. Wong struct xfs_btree_cur *rcur, 21329c194644SDarrick J. Wong int error) 21339c194644SDarrick J. Wong { 21349c194644SDarrick J. Wong struct xfs_buf *agbp; 21359c194644SDarrick J. Wong 21369c194644SDarrick J. Wong if (rcur == NULL) 21379c194644SDarrick J. Wong return; 21389c194644SDarrick J. Wong agbp = rcur->bc_private.a.agbp; 21390b04b6b8SDarrick J. Wong xfs_btree_del_cursor(rcur, error); 21409c194644SDarrick J. Wong if (error) 21419c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 21429c194644SDarrick J. Wong } 21439c194644SDarrick J. Wong 21449c194644SDarrick J. Wong /* 21459c194644SDarrick J. Wong * Process one of the deferred rmap operations. We pass back the 21469c194644SDarrick J. Wong * btree cursor to maintain our lock on the rmapbt between calls. 21479c194644SDarrick J. Wong * This saves time and eliminates a buffer deadlock between the 21489c194644SDarrick J. Wong * superblock and the AGF because we'll always grab them in the same 21499c194644SDarrick J. Wong * order. 21509c194644SDarrick J. Wong */ 21519c194644SDarrick J. Wong int 21529c194644SDarrick J. Wong xfs_rmap_finish_one( 21539c194644SDarrick J. Wong struct xfs_trans *tp, 21549c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2155c8ce540dSDarrick J. Wong uint64_t owner, 21569c194644SDarrick J. Wong int whichfork, 21579c194644SDarrick J. Wong xfs_fileoff_t startoff, 21589c194644SDarrick J. Wong xfs_fsblock_t startblock, 21599c194644SDarrick J. Wong xfs_filblks_t blockcount, 21609c194644SDarrick J. Wong xfs_exntst_t state, 21619c194644SDarrick J. Wong struct xfs_btree_cur **pcur) 21629c194644SDarrick J. Wong { 21639c194644SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 21649c194644SDarrick J. Wong struct xfs_btree_cur *rcur; 21659c194644SDarrick J. Wong struct xfs_buf *agbp = NULL; 21669c194644SDarrick J. Wong int error = 0; 21679c194644SDarrick J. Wong xfs_agnumber_t agno; 21689c194644SDarrick J. Wong struct xfs_owner_info oinfo; 21699c194644SDarrick J. Wong xfs_agblock_t bno; 21709c194644SDarrick J. Wong bool unwritten; 21719c194644SDarrick J. Wong 21729c194644SDarrick J. Wong agno = XFS_FSB_TO_AGNO(mp, startblock); 21739c194644SDarrick J. Wong ASSERT(agno != NULLAGNUMBER); 21749c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(mp, startblock); 21759c194644SDarrick J. Wong 21769c194644SDarrick J. Wong trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, 21779c194644SDarrick J. Wong startoff, blockcount, state); 21789c194644SDarrick J. Wong 21799c194644SDarrick J. Wong if (XFS_TEST_ERROR(false, mp, 21809e24cfd0SDarrick J. Wong XFS_ERRTAG_RMAP_FINISH_ONE)) 21819c194644SDarrick J. Wong return -EIO; 21829c194644SDarrick J. Wong 21839c194644SDarrick J. Wong /* 21849c194644SDarrick J. Wong * If we haven't gotten a cursor or the cursor AG doesn't match 21859c194644SDarrick J. Wong * the startblock, get one now. 21869c194644SDarrick J. Wong */ 21879c194644SDarrick J. Wong rcur = *pcur; 21889c194644SDarrick J. Wong if (rcur != NULL && rcur->bc_private.a.agno != agno) { 21899c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup(tp, rcur, 0); 21909c194644SDarrick J. Wong rcur = NULL; 21919c194644SDarrick J. Wong *pcur = NULL; 21929c194644SDarrick J. Wong } 21939c194644SDarrick J. Wong if (rcur == NULL) { 21949c194644SDarrick J. Wong /* 21959c194644SDarrick J. Wong * Refresh the freelist before we start changing the 21969c194644SDarrick J. Wong * rmapbt, because a shape change could cause us to 21979c194644SDarrick J. Wong * allocate blocks. 21989c194644SDarrick J. Wong */ 21999c194644SDarrick J. Wong error = xfs_free_extent_fix_freelist(tp, agno, &agbp); 22009c194644SDarrick J. Wong if (error) 22019c194644SDarrick J. Wong return error; 22029c194644SDarrick J. Wong if (!agbp) 22039c194644SDarrick J. Wong return -EFSCORRUPTED; 22049c194644SDarrick J. Wong 22059c194644SDarrick J. Wong rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 22069c194644SDarrick J. Wong if (!rcur) { 22079c194644SDarrick J. Wong error = -ENOMEM; 22089c194644SDarrick J. Wong goto out_cur; 22099c194644SDarrick J. Wong } 22109c194644SDarrick J. Wong } 22119c194644SDarrick J. Wong *pcur = rcur; 22129c194644SDarrick J. Wong 22139c194644SDarrick J. Wong xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff); 22149c194644SDarrick J. Wong unwritten = state == XFS_EXT_UNWRITTEN; 22159c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock); 22169c194644SDarrick J. Wong 22179c194644SDarrick J. Wong switch (type) { 22189c194644SDarrick J. Wong case XFS_RMAP_ALLOC: 22199c194644SDarrick J. Wong case XFS_RMAP_MAP: 22209c194644SDarrick J. Wong error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); 22219c194644SDarrick J. Wong break; 2222ceeb9c83SDarrick J. Wong case XFS_RMAP_MAP_SHARED: 2223ceeb9c83SDarrick J. Wong error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten, 2224ceeb9c83SDarrick J. Wong &oinfo); 2225ceeb9c83SDarrick J. Wong break; 22269c194644SDarrick J. Wong case XFS_RMAP_FREE: 22279c194644SDarrick J. Wong case XFS_RMAP_UNMAP: 22289c194644SDarrick J. Wong error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, 22299c194644SDarrick J. Wong &oinfo); 22309c194644SDarrick J. Wong break; 2231ceeb9c83SDarrick J. Wong case XFS_RMAP_UNMAP_SHARED: 2232ceeb9c83SDarrick J. Wong error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten, 2233ceeb9c83SDarrick J. Wong &oinfo); 2234ceeb9c83SDarrick J. Wong break; 22359c194644SDarrick J. Wong case XFS_RMAP_CONVERT: 22369c194644SDarrick J. Wong error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, 22379c194644SDarrick J. Wong &oinfo); 22389c194644SDarrick J. Wong break; 22393f165b33SDarrick J. Wong case XFS_RMAP_CONVERT_SHARED: 22403f165b33SDarrick J. Wong error = xfs_rmap_convert_shared(rcur, bno, blockcount, 22413f165b33SDarrick J. Wong !unwritten, &oinfo); 22423f165b33SDarrick J. Wong break; 22439c194644SDarrick J. Wong default: 22449c194644SDarrick J. Wong ASSERT(0); 22459c194644SDarrick J. Wong error = -EFSCORRUPTED; 22469c194644SDarrick J. Wong } 22479c194644SDarrick J. Wong return error; 22489c194644SDarrick J. Wong 22499c194644SDarrick J. Wong out_cur: 22509c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 22519c194644SDarrick J. Wong 22529c194644SDarrick J. Wong return error; 22539c194644SDarrick J. Wong } 22549c194644SDarrick J. Wong 22559c194644SDarrick J. Wong /* 22569c194644SDarrick J. Wong * Don't defer an rmap if we aren't an rmap filesystem. 22579c194644SDarrick J. Wong */ 22589c194644SDarrick J. Wong static bool 22599c194644SDarrick J. Wong xfs_rmap_update_is_needed( 22603993baebSDarrick J. Wong struct xfs_mount *mp, 22613993baebSDarrick J. Wong int whichfork) 22629c194644SDarrick J. Wong { 22633993baebSDarrick J. Wong return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK; 22649c194644SDarrick J. Wong } 22659c194644SDarrick J. Wong 22669c194644SDarrick J. Wong /* 22679c194644SDarrick J. Wong * Record a rmap intent; the list is kept sorted first by AG and then by 22689c194644SDarrick J. Wong * increasing age. 22699c194644SDarrick J. Wong */ 2270bc46ac64SDarrick J. Wong static void 22719c194644SDarrick J. Wong __xfs_rmap_add( 22720f37d178SBrian Foster struct xfs_trans *tp, 22739c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2274c8ce540dSDarrick J. Wong uint64_t owner, 22759c194644SDarrick J. Wong int whichfork, 22769c194644SDarrick J. Wong struct xfs_bmbt_irec *bmap) 22779c194644SDarrick J. Wong { 22789c194644SDarrick J. Wong struct xfs_rmap_intent *ri; 22799c194644SDarrick J. Wong 22800f37d178SBrian Foster trace_xfs_rmap_defer(tp->t_mountp, 22810f37d178SBrian Foster XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock), 22829c194644SDarrick J. Wong type, 22830f37d178SBrian Foster XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock), 22849c194644SDarrick J. Wong owner, whichfork, 22859c194644SDarrick J. Wong bmap->br_startoff, 22869c194644SDarrick J. Wong bmap->br_blockcount, 22879c194644SDarrick J. Wong bmap->br_state); 22889c194644SDarrick J. Wong 2289707e0ddaSTetsuo Handa ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS); 22909c194644SDarrick J. Wong INIT_LIST_HEAD(&ri->ri_list); 22919c194644SDarrick J. Wong ri->ri_type = type; 22929c194644SDarrick J. Wong ri->ri_owner = owner; 22939c194644SDarrick J. Wong ri->ri_whichfork = whichfork; 22949c194644SDarrick J. Wong ri->ri_bmap = *bmap; 22959c194644SDarrick J. Wong 22960f37d178SBrian Foster xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); 22979c194644SDarrick J. Wong } 22989c194644SDarrick J. Wong 22999c194644SDarrick J. Wong /* Map an extent into a file. */ 2300bc46ac64SDarrick J. Wong void 23019c194644SDarrick J. Wong xfs_rmap_map_extent( 23020f37d178SBrian Foster struct xfs_trans *tp, 23039c194644SDarrick J. Wong struct xfs_inode *ip, 23049c194644SDarrick J. Wong int whichfork, 23059c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 23069c194644SDarrick J. Wong { 23070f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2308bc46ac64SDarrick J. Wong return; 23099c194644SDarrick J. Wong 2310bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? 2311ceeb9c83SDarrick J. Wong XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino, 23129c194644SDarrick J. Wong whichfork, PREV); 23139c194644SDarrick J. Wong } 23149c194644SDarrick J. Wong 23159c194644SDarrick J. Wong /* Unmap an extent out of a file. */ 2316bc46ac64SDarrick J. Wong void 23179c194644SDarrick J. Wong xfs_rmap_unmap_extent( 23180f37d178SBrian Foster struct xfs_trans *tp, 23199c194644SDarrick J. Wong struct xfs_inode *ip, 23209c194644SDarrick J. Wong int whichfork, 23219c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 23229c194644SDarrick J. Wong { 23230f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2324bc46ac64SDarrick J. Wong return; 23259c194644SDarrick J. Wong 2326bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? 2327ceeb9c83SDarrick J. Wong XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino, 23289c194644SDarrick J. Wong whichfork, PREV); 23299c194644SDarrick J. Wong } 23309c194644SDarrick J. Wong 23310f37d178SBrian Foster /* 23320f37d178SBrian Foster * Convert a data fork extent from unwritten to real or vice versa. 23330f37d178SBrian Foster * 23340f37d178SBrian Foster * Note that tp can be NULL here as no transaction is used for COW fork 23350f37d178SBrian Foster * unwritten conversion. 23360f37d178SBrian Foster */ 2337bc46ac64SDarrick J. Wong void 23389c194644SDarrick J. Wong xfs_rmap_convert_extent( 23399c194644SDarrick J. Wong struct xfs_mount *mp, 23400f37d178SBrian Foster struct xfs_trans *tp, 23419c194644SDarrick J. Wong struct xfs_inode *ip, 23429c194644SDarrick J. Wong int whichfork, 23439c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 23449c194644SDarrick J. Wong { 23453993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 2346bc46ac64SDarrick J. Wong return; 23479c194644SDarrick J. Wong 2348bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? 23493f165b33SDarrick J. Wong XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino, 23509c194644SDarrick J. Wong whichfork, PREV); 23519c194644SDarrick J. Wong } 23529c194644SDarrick J. Wong 23539c194644SDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */ 2354bc46ac64SDarrick J. Wong void 23559c194644SDarrick J. Wong xfs_rmap_alloc_extent( 23560f37d178SBrian Foster struct xfs_trans *tp, 23579c194644SDarrick J. Wong xfs_agnumber_t agno, 23589c194644SDarrick J. Wong xfs_agblock_t bno, 23599c194644SDarrick J. Wong xfs_extlen_t len, 2360c8ce540dSDarrick J. Wong uint64_t owner) 23619c194644SDarrick J. Wong { 23629c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 23639c194644SDarrick J. Wong 23640f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2365bc46ac64SDarrick J. Wong return; 23669c194644SDarrick J. Wong 23670f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 23689c194644SDarrick J. Wong bmap.br_blockcount = len; 23699c194644SDarrick J. Wong bmap.br_startoff = 0; 23709c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 23719c194644SDarrick J. Wong 2372bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap); 23739c194644SDarrick J. Wong } 23749c194644SDarrick J. Wong 23759c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */ 2376bc46ac64SDarrick J. Wong void 23779c194644SDarrick J. Wong xfs_rmap_free_extent( 23780f37d178SBrian Foster struct xfs_trans *tp, 23799c194644SDarrick J. Wong xfs_agnumber_t agno, 23809c194644SDarrick J. Wong xfs_agblock_t bno, 23819c194644SDarrick J. Wong xfs_extlen_t len, 2382c8ce540dSDarrick J. Wong uint64_t owner) 23839c194644SDarrick J. Wong { 23849c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 23859c194644SDarrick J. Wong 23860f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2387bc46ac64SDarrick J. Wong return; 23889c194644SDarrick J. Wong 23890f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 23909c194644SDarrick J. Wong bmap.br_blockcount = len; 23919c194644SDarrick J. Wong bmap.br_startoff = 0; 23929c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 23939c194644SDarrick J. Wong 2394bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap); 23959c194644SDarrick J. Wong } 2396e89c0413SDarrick J. Wong 2397e89c0413SDarrick J. Wong /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ 2398e89c0413SDarrick J. Wong int 2399e89c0413SDarrick J. Wong xfs_rmap_compare( 2400e89c0413SDarrick J. Wong const struct xfs_rmap_irec *a, 2401e89c0413SDarrick J. Wong const struct xfs_rmap_irec *b) 2402e89c0413SDarrick J. Wong { 2403e89c0413SDarrick J. Wong __u64 oa; 2404e89c0413SDarrick J. Wong __u64 ob; 2405e89c0413SDarrick J. Wong 2406e89c0413SDarrick J. Wong oa = xfs_rmap_irec_offset_pack(a); 2407e89c0413SDarrick J. Wong ob = xfs_rmap_irec_offset_pack(b); 2408e89c0413SDarrick J. Wong 2409e89c0413SDarrick J. Wong if (a->rm_startblock < b->rm_startblock) 2410e89c0413SDarrick J. Wong return -1; 2411e89c0413SDarrick J. Wong else if (a->rm_startblock > b->rm_startblock) 2412e89c0413SDarrick J. Wong return 1; 2413e89c0413SDarrick J. Wong else if (a->rm_owner < b->rm_owner) 2414e89c0413SDarrick J. Wong return -1; 2415e89c0413SDarrick J. Wong else if (a->rm_owner > b->rm_owner) 2416e89c0413SDarrick J. Wong return 1; 2417e89c0413SDarrick J. Wong else if (oa < ob) 2418e89c0413SDarrick J. Wong return -1; 2419e89c0413SDarrick J. Wong else if (oa > ob) 2420e89c0413SDarrick J. Wong return 1; 2421e89c0413SDarrick J. Wong else 2422e89c0413SDarrick J. Wong return 0; 2423e89c0413SDarrick J. Wong } 2424ed7c52d4SDarrick J. Wong 2425ed7c52d4SDarrick J. Wong /* Is there a record covering a given extent? */ 2426ed7c52d4SDarrick J. Wong int 2427ed7c52d4SDarrick J. Wong xfs_rmap_has_record( 2428ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2429ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2430ed7c52d4SDarrick J. Wong xfs_extlen_t len, 2431ed7c52d4SDarrick J. Wong bool *exists) 2432ed7c52d4SDarrick J. Wong { 2433ed7c52d4SDarrick J. Wong union xfs_btree_irec low; 2434ed7c52d4SDarrick J. Wong union xfs_btree_irec high; 2435ed7c52d4SDarrick J. Wong 2436ed7c52d4SDarrick J. Wong memset(&low, 0, sizeof(low)); 2437ed7c52d4SDarrick J. Wong low.r.rm_startblock = bno; 2438ed7c52d4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 2439ed7c52d4SDarrick J. Wong high.r.rm_startblock = bno + len - 1; 2440ed7c52d4SDarrick J. Wong 2441ed7c52d4SDarrick J. Wong return xfs_btree_has_record(cur, &low, &high, exists); 2442ed7c52d4SDarrick J. Wong } 2443ed7c52d4SDarrick J. Wong 2444ed7c52d4SDarrick J. Wong /* 2445ed7c52d4SDarrick J. Wong * Is there a record for this owner completely covering a given physical 2446ed7c52d4SDarrick J. Wong * extent? If so, *has_rmap will be set to true. If there is no record 2447ed7c52d4SDarrick J. Wong * or the record only covers part of the range, we set *has_rmap to false. 2448ed7c52d4SDarrick J. Wong * This function doesn't perform range lookups or offset checks, so it is 2449ed7c52d4SDarrick J. Wong * not suitable for checking data fork blocks. 2450ed7c52d4SDarrick J. Wong */ 2451ed7c52d4SDarrick J. Wong int 2452ed7c52d4SDarrick J. Wong xfs_rmap_record_exists( 2453ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2454ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2455ed7c52d4SDarrick J. Wong xfs_extlen_t len, 245666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 2457ed7c52d4SDarrick J. Wong bool *has_rmap) 2458ed7c52d4SDarrick J. Wong { 2459ed7c52d4SDarrick J. Wong uint64_t owner; 2460ed7c52d4SDarrick J. Wong uint64_t offset; 2461ed7c52d4SDarrick J. Wong unsigned int flags; 2462ed7c52d4SDarrick J. Wong int has_record; 2463ed7c52d4SDarrick J. Wong struct xfs_rmap_irec irec; 2464ed7c52d4SDarrick J. Wong int error; 2465ed7c52d4SDarrick J. Wong 2466ed7c52d4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2467ed7c52d4SDarrick J. Wong ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || 2468ed7c52d4SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK)); 2469ed7c52d4SDarrick J. Wong 2470ed7c52d4SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, 2471ed7c52d4SDarrick J. Wong &has_record); 2472ed7c52d4SDarrick J. Wong if (error) 2473ed7c52d4SDarrick J. Wong return error; 2474ed7c52d4SDarrick J. Wong if (!has_record) { 2475ed7c52d4SDarrick J. Wong *has_rmap = false; 2476ed7c52d4SDarrick J. Wong return 0; 2477ed7c52d4SDarrick J. Wong } 2478ed7c52d4SDarrick J. Wong 2479ed7c52d4SDarrick J. Wong error = xfs_rmap_get_rec(cur, &irec, &has_record); 2480ed7c52d4SDarrick J. Wong if (error) 2481ed7c52d4SDarrick J. Wong return error; 2482ed7c52d4SDarrick J. Wong if (!has_record) { 2483ed7c52d4SDarrick J. Wong *has_rmap = false; 2484ed7c52d4SDarrick J. Wong return 0; 2485ed7c52d4SDarrick J. Wong } 2486ed7c52d4SDarrick J. Wong 2487ed7c52d4SDarrick J. Wong *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno && 2488ed7c52d4SDarrick J. Wong irec.rm_startblock + irec.rm_blockcount >= bno + len); 2489ed7c52d4SDarrick J. Wong return 0; 2490ed7c52d4SDarrick J. Wong } 24914d4f86b4SDarrick J. Wong 24924d4f86b4SDarrick J. Wong struct xfs_rmap_key_state { 24934d4f86b4SDarrick J. Wong uint64_t owner; 24944d4f86b4SDarrick J. Wong uint64_t offset; 24954d4f86b4SDarrick J. Wong unsigned int flags; 24964d4f86b4SDarrick J. Wong bool has_rmap; 24974d4f86b4SDarrick J. Wong }; 24984d4f86b4SDarrick J. Wong 24994d4f86b4SDarrick J. Wong /* For each rmap given, figure out if it doesn't match the key we want. */ 25004d4f86b4SDarrick J. Wong STATIC int 25014d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper( 25024d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 25034d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rec, 25044d4f86b4SDarrick J. Wong void *priv) 25054d4f86b4SDarrick J. Wong { 25064d4f86b4SDarrick J. Wong struct xfs_rmap_key_state *rks = priv; 25074d4f86b4SDarrick J. Wong 25084d4f86b4SDarrick J. Wong if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset && 25094d4f86b4SDarrick J. Wong ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags) 25104d4f86b4SDarrick J. Wong return 0; 25114d4f86b4SDarrick J. Wong rks->has_rmap = true; 2512e7ee96dfSDarrick J. Wong return -ECANCELED; 25134d4f86b4SDarrick J. Wong } 25144d4f86b4SDarrick J. Wong 25154d4f86b4SDarrick J. Wong /* 25164d4f86b4SDarrick J. Wong * Given an extent and some owner info, can we find records overlapping 25174d4f86b4SDarrick J. Wong * the extent whose owner info does not match the given owner? 25184d4f86b4SDarrick J. Wong */ 25194d4f86b4SDarrick J. Wong int 25204d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys( 25214d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 25224d4f86b4SDarrick J. Wong xfs_agblock_t bno, 25234d4f86b4SDarrick J. Wong xfs_extlen_t len, 252466e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 25254d4f86b4SDarrick J. Wong bool *has_rmap) 25264d4f86b4SDarrick J. Wong { 25274d4f86b4SDarrick J. Wong struct xfs_rmap_irec low = {0}; 25284d4f86b4SDarrick J. Wong struct xfs_rmap_irec high; 25294d4f86b4SDarrick J. Wong struct xfs_rmap_key_state rks; 25304d4f86b4SDarrick J. Wong int error; 25314d4f86b4SDarrick J. Wong 25324d4f86b4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags); 25334d4f86b4SDarrick J. Wong rks.has_rmap = false; 25344d4f86b4SDarrick J. Wong 25354d4f86b4SDarrick J. Wong low.rm_startblock = bno; 25364d4f86b4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 25374d4f86b4SDarrick J. Wong high.rm_startblock = bno + len - 1; 25384d4f86b4SDarrick J. Wong 25394d4f86b4SDarrick J. Wong error = xfs_rmap_query_range(cur, &low, &high, 25404d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper, &rks); 25417380e8feSDarrick J. Wong if (error < 0) 25424d4f86b4SDarrick J. Wong return error; 25437380e8feSDarrick J. Wong 25447380e8feSDarrick J. Wong *has_rmap = rks.has_rmap; 25457380e8feSDarrick J. Wong return 0; 25464d4f86b4SDarrick J. Wong } 25477280fedaSDarrick J. Wong 25487280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = { 25497280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_NULL, 25507280fedaSDarrick J. Wong }; 25517280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = { 25527280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_UNKNOWN, 25537280fedaSDarrick J. Wong }; 25547280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_FS = { 25557280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_FS, 25567280fedaSDarrick J. Wong }; 25577280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_LOG = { 25587280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_LOG, 25597280fedaSDarrick J. Wong }; 25607280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_AG = { 25617280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_AG, 25627280fedaSDarrick J. Wong }; 25637280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = { 25647280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INOBT, 25657280fedaSDarrick J. Wong }; 25667280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INODES = { 25677280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INODES, 25687280fedaSDarrick J. Wong }; 25697280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_REFC = { 25707280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_REFC, 25717280fedaSDarrick J. Wong }; 25727280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_COW = { 25737280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_COW, 25747280fedaSDarrick J. Wong }; 2575