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" 1445d06621SDave Chinner #include "xfs_sb.h" 15673930c3SDarrick J. Wong #include "xfs_defer.h" 16673930c3SDarrick J. Wong #include "xfs_btree.h" 17673930c3SDarrick J. Wong #include "xfs_trans.h" 18673930c3SDarrick J. Wong #include "xfs_alloc.h" 19673930c3SDarrick J. Wong #include "xfs_rmap.h" 200a1b0b38SDarrick J. Wong #include "xfs_rmap_btree.h" 21673930c3SDarrick J. Wong #include "xfs_trace.h" 22e9e899a2SDarrick J. Wong #include "xfs_errortag.h" 23673930c3SDarrick J. Wong #include "xfs_error.h" 249c194644SDarrick J. Wong #include "xfs_inode.h" 259bbafc71SDave Chinner #include "xfs_ag.h" 26673930c3SDarrick J. Wong 27f3c799c2SDarrick J. Wong struct kmem_cache *xfs_rmap_intent_cache; 28f3c799c2SDarrick J. Wong 294b8ed677SDarrick J. Wong /* 304b8ed677SDarrick J. Wong * Lookup the first record less than or equal to [bno, len, owner, offset] 314b8ed677SDarrick J. Wong * in the btree given by cur. 324b8ed677SDarrick J. Wong */ 334b8ed677SDarrick J. Wong int 344b8ed677SDarrick J. Wong xfs_rmap_lookup_le( 354b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 364b8ed677SDarrick J. Wong xfs_agblock_t bno, 374b8ed677SDarrick J. Wong uint64_t owner, 384b8ed677SDarrick J. Wong uint64_t offset, 394b8ed677SDarrick J. Wong unsigned int flags, 405b7ca8b3SDarrick J. Wong struct xfs_rmap_irec *irec, 414b8ed677SDarrick J. Wong int *stat) 424b8ed677SDarrick J. Wong { 435b7ca8b3SDarrick J. Wong int get_stat = 0; 445b7ca8b3SDarrick J. Wong int error; 455b7ca8b3SDarrick J. Wong 464b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 475b7ca8b3SDarrick J. Wong cur->bc_rec.r.rm_blockcount = 0; 484b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 494b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 504b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 515b7ca8b3SDarrick J. Wong 525b7ca8b3SDarrick J. Wong error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); 535b7ca8b3SDarrick J. Wong if (error || !(*stat) || !irec) 545b7ca8b3SDarrick J. Wong return error; 555b7ca8b3SDarrick J. Wong 565b7ca8b3SDarrick J. Wong error = xfs_rmap_get_rec(cur, irec, &get_stat); 575b7ca8b3SDarrick J. Wong if (error) 585b7ca8b3SDarrick J. Wong return error; 595b7ca8b3SDarrick J. Wong if (!get_stat) 605b7ca8b3SDarrick J. Wong return -EFSCORRUPTED; 615b7ca8b3SDarrick J. Wong 625b7ca8b3SDarrick J. Wong return 0; 634b8ed677SDarrick J. Wong } 644b8ed677SDarrick J. Wong 654b8ed677SDarrick J. Wong /* 664b8ed677SDarrick J. Wong * Lookup the record exactly matching [bno, len, owner, offset] 674b8ed677SDarrick J. Wong * in the btree given by cur. 684b8ed677SDarrick J. Wong */ 694b8ed677SDarrick J. Wong int 704b8ed677SDarrick J. Wong xfs_rmap_lookup_eq( 714b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 724b8ed677SDarrick J. Wong xfs_agblock_t bno, 734b8ed677SDarrick J. Wong xfs_extlen_t len, 744b8ed677SDarrick J. Wong uint64_t owner, 754b8ed677SDarrick J. Wong uint64_t offset, 764b8ed677SDarrick J. Wong unsigned int flags, 774b8ed677SDarrick J. Wong int *stat) 784b8ed677SDarrick J. Wong { 794b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 804b8ed677SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 814b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 824b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 834b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 844b8ed677SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); 854b8ed677SDarrick J. Wong } 864b8ed677SDarrick J. Wong 874b8ed677SDarrick J. Wong /* 884b8ed677SDarrick J. Wong * Update the record referred to by cur to the value given 894b8ed677SDarrick J. Wong * by [bno, len, owner, offset]. 904b8ed677SDarrick J. Wong * This either works (return 0) or gets an EFSCORRUPTED error. 914b8ed677SDarrick J. Wong */ 924b8ed677SDarrick J. Wong STATIC int 934b8ed677SDarrick J. Wong xfs_rmap_update( 944b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 954b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec) 964b8ed677SDarrick J. Wong { 974b8ed677SDarrick J. Wong union xfs_btree_rec rec; 98abf09233SDarrick J. Wong int error; 99abf09233SDarrick J. Wong 10050f02fe3SDave Chinner trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno, 101abf09233SDarrick J. Wong irec->rm_startblock, irec->rm_blockcount, 102abf09233SDarrick J. Wong irec->rm_owner, irec->rm_offset, irec->rm_flags); 1034b8ed677SDarrick J. Wong 1044b8ed677SDarrick J. Wong rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); 1054b8ed677SDarrick J. Wong rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); 1064b8ed677SDarrick J. Wong rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); 1074b8ed677SDarrick J. Wong rec.rmap.rm_offset = cpu_to_be64( 1084b8ed677SDarrick J. Wong xfs_rmap_irec_offset_pack(irec)); 109abf09233SDarrick J. Wong error = xfs_btree_update(cur, &rec); 110abf09233SDarrick J. Wong if (error) 111abf09233SDarrick J. Wong trace_xfs_rmap_update_error(cur->bc_mp, 11250f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 113abf09233SDarrick J. Wong return error; 114abf09233SDarrick J. Wong } 115abf09233SDarrick J. Wong 116abf09233SDarrick J. Wong int 117abf09233SDarrick J. Wong xfs_rmap_insert( 118abf09233SDarrick J. Wong struct xfs_btree_cur *rcur, 119abf09233SDarrick J. Wong xfs_agblock_t agbno, 120abf09233SDarrick J. Wong xfs_extlen_t len, 121abf09233SDarrick J. Wong uint64_t owner, 122abf09233SDarrick J. Wong uint64_t offset, 123abf09233SDarrick J. Wong unsigned int flags) 124abf09233SDarrick J. Wong { 125abf09233SDarrick J. Wong int i; 126abf09233SDarrick J. Wong int error; 127abf09233SDarrick J. Wong 12850f02fe3SDave Chinner trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno, 129abf09233SDarrick J. Wong len, owner, offset, flags); 130abf09233SDarrick J. Wong 131abf09233SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); 132abf09233SDarrick J. Wong if (error) 133abf09233SDarrick J. Wong goto done; 134f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) { 135f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 136f9e03706SDarrick J. Wong goto done; 137f9e03706SDarrick J. Wong } 138abf09233SDarrick J. Wong 139abf09233SDarrick J. Wong rcur->bc_rec.r.rm_startblock = agbno; 140abf09233SDarrick J. Wong rcur->bc_rec.r.rm_blockcount = len; 141abf09233SDarrick J. Wong rcur->bc_rec.r.rm_owner = owner; 142abf09233SDarrick J. Wong rcur->bc_rec.r.rm_offset = offset; 143abf09233SDarrick J. Wong rcur->bc_rec.r.rm_flags = flags; 144abf09233SDarrick J. Wong error = xfs_btree_insert(rcur, &i); 145abf09233SDarrick J. Wong if (error) 146abf09233SDarrick J. Wong goto done; 147f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { 148f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 149f9e03706SDarrick J. Wong goto done; 150f9e03706SDarrick J. Wong } 151abf09233SDarrick J. Wong done: 152abf09233SDarrick J. Wong if (error) 153abf09233SDarrick J. Wong trace_xfs_rmap_insert_error(rcur->bc_mp, 15450f02fe3SDave Chinner rcur->bc_ag.pag->pag_agno, error, _RET_IP_); 155abf09233SDarrick J. Wong return error; 1564b8ed677SDarrick J. Wong } 1574b8ed677SDarrick J. Wong 158ceeb9c83SDarrick J. Wong STATIC int 159ceeb9c83SDarrick J. Wong xfs_rmap_delete( 160ceeb9c83SDarrick J. Wong struct xfs_btree_cur *rcur, 161ceeb9c83SDarrick J. Wong xfs_agblock_t agbno, 162ceeb9c83SDarrick J. Wong xfs_extlen_t len, 163ceeb9c83SDarrick J. Wong uint64_t owner, 164ceeb9c83SDarrick J. Wong uint64_t offset, 165ceeb9c83SDarrick J. Wong unsigned int flags) 166ceeb9c83SDarrick J. Wong { 167ceeb9c83SDarrick J. Wong int i; 168ceeb9c83SDarrick J. Wong int error; 169ceeb9c83SDarrick J. Wong 17050f02fe3SDave Chinner trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno, 171ceeb9c83SDarrick J. Wong len, owner, offset, flags); 172ceeb9c83SDarrick J. Wong 173ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); 174ceeb9c83SDarrick J. Wong if (error) 175ceeb9c83SDarrick J. Wong goto done; 176f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { 177f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 178f9e03706SDarrick J. Wong goto done; 179f9e03706SDarrick J. Wong } 180ceeb9c83SDarrick J. Wong 181ceeb9c83SDarrick J. Wong error = xfs_btree_delete(rcur, &i); 182ceeb9c83SDarrick J. Wong if (error) 183ceeb9c83SDarrick J. Wong goto done; 184f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { 185f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 186f9e03706SDarrick J. Wong goto done; 187f9e03706SDarrick J. Wong } 188ceeb9c83SDarrick J. Wong done: 189ceeb9c83SDarrick J. Wong if (error) 190ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete_error(rcur->bc_mp, 19150f02fe3SDave Chinner rcur->bc_ag.pag->pag_agno, error, _RET_IP_); 192ceeb9c83SDarrick J. Wong return error; 193ceeb9c83SDarrick J. Wong } 194ceeb9c83SDarrick J. Wong 19526788097SDarrick J. Wong /* Convert an internal btree record to an rmap record. */ 19626788097SDarrick J. Wong int 1974b8ed677SDarrick J. Wong xfs_rmap_btrec_to_irec( 198159eb69dSDarrick J. Wong const union xfs_btree_rec *rec, 1994b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec) 2004b8ed677SDarrick J. Wong { 2014b8ed677SDarrick J. Wong irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); 2024b8ed677SDarrick J. Wong irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); 2034b8ed677SDarrick J. Wong irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); 2044b8ed677SDarrick J. Wong return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), 2054b8ed677SDarrick J. Wong irec); 2064b8ed677SDarrick J. Wong } 2074b8ed677SDarrick J. Wong 2084b8ed677SDarrick J. Wong /* 2094b8ed677SDarrick J. Wong * Get the data from the pointed-to record. 2104b8ed677SDarrick J. Wong */ 2114b8ed677SDarrick J. Wong int 2124b8ed677SDarrick J. Wong xfs_rmap_get_rec( 2134b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 2144b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec, 2154b8ed677SDarrick J. Wong int *stat) 2164b8ed677SDarrick J. Wong { 2179e6c08d4SDave Chinner struct xfs_mount *mp = cur->bc_mp; 2180800169eSDave Chinner struct xfs_perag *pag = cur->bc_ag.pag; 2194b8ed677SDarrick J. Wong union xfs_btree_rec *rec; 2204b8ed677SDarrick J. Wong int error; 2214b8ed677SDarrick J. Wong 2224b8ed677SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat); 2234b8ed677SDarrick J. Wong if (error || !*stat) 2244b8ed677SDarrick J. Wong return error; 2254b8ed677SDarrick J. Wong 2269e6c08d4SDave Chinner if (xfs_rmap_btrec_to_irec(rec, irec)) 2279e6c08d4SDave Chinner goto out_bad_rec; 2289e6c08d4SDave Chinner 2299e6c08d4SDave Chinner if (irec->rm_blockcount == 0) 2309e6c08d4SDave Chinner goto out_bad_rec; 2319e6c08d4SDave Chinner if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) { 2329e6c08d4SDave Chinner if (irec->rm_owner != XFS_RMAP_OWN_FS) 2339e6c08d4SDave Chinner goto out_bad_rec; 2349e6c08d4SDave Chinner if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1) 2359e6c08d4SDave Chinner goto out_bad_rec; 2369e6c08d4SDave Chinner } else { 2379e6c08d4SDave Chinner /* check for valid extent range, including overflow */ 238b65e08f8SDarrick J. Wong if (!xfs_verify_agbext(pag, irec->rm_startblock, 239b65e08f8SDarrick J. Wong irec->rm_blockcount)) 2409e6c08d4SDave Chinner goto out_bad_rec; 2419e6c08d4SDave Chinner } 2429e6c08d4SDave Chinner 2439e6c08d4SDave Chinner if (!(xfs_verify_ino(mp, irec->rm_owner) || 2449e6c08d4SDave Chinner (irec->rm_owner <= XFS_RMAP_OWN_FS && 2459e6c08d4SDave Chinner irec->rm_owner >= XFS_RMAP_OWN_MIN))) 2469e6c08d4SDave Chinner goto out_bad_rec; 2479e6c08d4SDave Chinner 2489e6c08d4SDave Chinner return 0; 2499e6c08d4SDave Chinner out_bad_rec: 2509e6c08d4SDave Chinner xfs_warn(mp, 2519e6c08d4SDave Chinner "Reverse Mapping BTree record corruption in AG %d detected!", 2520800169eSDave Chinner pag->pag_agno); 2539e6c08d4SDave Chinner xfs_warn(mp, 2549e6c08d4SDave Chinner "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", 2559e6c08d4SDave Chinner irec->rm_owner, irec->rm_flags, irec->rm_startblock, 2569e6c08d4SDave Chinner irec->rm_blockcount); 2579e6c08d4SDave Chinner return -EFSCORRUPTED; 2584b8ed677SDarrick J. Wong } 2594b8ed677SDarrick J. Wong 260ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info { 261ceeb9c83SDarrick J. Wong struct xfs_rmap_irec high; 262ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec; 263ceeb9c83SDarrick J. Wong }; 264ceeb9c83SDarrick J. Wong 265ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 266ceeb9c83SDarrick J. Wong STATIC int 267ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper( 268ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 269159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec, 270ceeb9c83SDarrick J. Wong void *priv) 271ceeb9c83SDarrick J. Wong { 272ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 273ceeb9c83SDarrick J. Wong 274ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, 27550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, rec->rm_startblock, 276ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 277ceeb9c83SDarrick J. Wong rec->rm_flags); 278ceeb9c83SDarrick J. Wong 279ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 28039ee2239SDarrick J. Wong return 0; 281ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 282ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 283ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) 28439ee2239SDarrick J. Wong return 0; 285ceeb9c83SDarrick J. Wong 286ceeb9c83SDarrick J. Wong *info->irec = *rec; 287e7ee96dfSDarrick J. Wong return -ECANCELED; 288ceeb9c83SDarrick J. Wong } 289ceeb9c83SDarrick J. Wong 290ceeb9c83SDarrick J. Wong /* 291ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 292ceeb9c83SDarrick J. Wong * return a match with the same owner and adjacent physical and logical 293ceeb9c83SDarrick J. Wong * block ranges. 294ceeb9c83SDarrick J. Wong */ 2951edf8056SDarrick J. Wong STATIC int 296ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor( 297ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 298ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 299ceeb9c83SDarrick J. Wong uint64_t owner, 300ceeb9c83SDarrick J. Wong uint64_t offset, 301ceeb9c83SDarrick J. Wong unsigned int flags, 302ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 303ceeb9c83SDarrick J. Wong int *stat) 304ceeb9c83SDarrick J. Wong { 305ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 3061edf8056SDarrick J. Wong int found = 0; 307ceeb9c83SDarrick J. Wong int error; 308ceeb9c83SDarrick J. Wong 309ceeb9c83SDarrick J. Wong *stat = 0; 310ceeb9c83SDarrick J. Wong if (bno == 0) 311ceeb9c83SDarrick J. Wong return 0; 312ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno - 1; 313ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 314ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && 315ceeb9c83SDarrick J. Wong !(flags & XFS_RMAP_BMBT_BLOCK)) { 316ceeb9c83SDarrick J. Wong if (offset == 0) 317ceeb9c83SDarrick J. Wong return 0; 318ceeb9c83SDarrick J. Wong info.high.rm_offset = offset - 1; 319ceeb9c83SDarrick J. Wong } else 320ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 321ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 322ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 323ceeb9c83SDarrick J. Wong info.irec = irec; 324ceeb9c83SDarrick J. Wong 325ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, 32650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags); 327ceeb9c83SDarrick J. Wong 3281edf8056SDarrick J. Wong /* 3291edf8056SDarrick J. Wong * Historically, we always used the range query to walk every reverse 3301edf8056SDarrick J. Wong * mapping that could possibly overlap the key that the caller asked 3311edf8056SDarrick J. Wong * for, and filter out the ones that don't. That is very slow when 3321edf8056SDarrick J. Wong * there are a lot of records. 3331edf8056SDarrick J. Wong * 3341edf8056SDarrick J. Wong * However, there are two scenarios where the classic btree search can 3351edf8056SDarrick J. Wong * produce correct results -- if the index contains a record that is an 3361edf8056SDarrick J. Wong * exact match for the lookup key; and if there are no other records 3371edf8056SDarrick J. Wong * between the record we want and the key we supplied. 3381edf8056SDarrick J. Wong * 3391edf8056SDarrick J. Wong * As an optimization, try a non-overlapped lookup first. This makes 3401edf8056SDarrick J. Wong * extent conversion and remap operations run a bit faster if the 3411edf8056SDarrick J. Wong * physical extents aren't being shared. If we don't find what we 3421edf8056SDarrick J. Wong * want, we fall back to the overlapped query. 3431edf8056SDarrick J. Wong */ 3441edf8056SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec, 3451edf8056SDarrick J. Wong &found); 3461edf8056SDarrick J. Wong if (error) 3471edf8056SDarrick J. Wong return error; 3481edf8056SDarrick J. Wong if (found) 3491edf8056SDarrick J. Wong error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info); 3501edf8056SDarrick J. Wong if (!error) 351ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 352ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper, &info); 3531edf8056SDarrick J. Wong if (error != -ECANCELED) 3541edf8056SDarrick J. Wong return error; 3551edf8056SDarrick J. Wong 3561edf8056SDarrick J. Wong *stat = 1; 357ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 35850f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, irec->rm_startblock, 3591edf8056SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, irec->rm_offset, 3601edf8056SDarrick J. Wong irec->rm_flags); 3611edf8056SDarrick J. Wong return 0; 362ceeb9c83SDarrick J. Wong } 363ceeb9c83SDarrick J. Wong 364ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 365ceeb9c83SDarrick J. Wong STATIC int 366ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper( 367ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 368159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec, 369ceeb9c83SDarrick J. Wong void *priv) 370ceeb9c83SDarrick J. Wong { 371ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 372ceeb9c83SDarrick J. Wong 373ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, 37450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, rec->rm_startblock, 375ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 376ceeb9c83SDarrick J. Wong rec->rm_flags); 377ceeb9c83SDarrick J. Wong 378ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 37939ee2239SDarrick J. Wong return 0; 380ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 381ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 382ceeb9c83SDarrick J. Wong (rec->rm_offset > info->high.rm_offset || 383ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) 38439ee2239SDarrick J. Wong return 0; 385ceeb9c83SDarrick J. Wong 386ceeb9c83SDarrick J. Wong *info->irec = *rec; 387e7ee96dfSDarrick J. Wong return -ECANCELED; 388ceeb9c83SDarrick J. Wong } 389ceeb9c83SDarrick J. Wong 390ceeb9c83SDarrick J. Wong /* 391ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 392ceeb9c83SDarrick J. Wong * return a match with the same owner and overlapping physical and logical 393ceeb9c83SDarrick J. Wong * block ranges. This is the overlapping-interval version of 394ceeb9c83SDarrick J. Wong * xfs_rmap_lookup_le. 395ceeb9c83SDarrick J. Wong */ 396ceeb9c83SDarrick J. Wong int 397ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range( 398ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 399ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 400ceeb9c83SDarrick J. Wong uint64_t owner, 401ceeb9c83SDarrick J. Wong uint64_t offset, 402ceeb9c83SDarrick J. Wong unsigned int flags, 403ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 404ceeb9c83SDarrick J. Wong int *stat) 405ceeb9c83SDarrick J. Wong { 406ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 40775d893d1SDarrick J. Wong int found = 0; 408ceeb9c83SDarrick J. Wong int error; 409ceeb9c83SDarrick J. Wong 410ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno; 411ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 412ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) 413ceeb9c83SDarrick J. Wong info.high.rm_offset = offset; 414ceeb9c83SDarrick J. Wong else 415ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 416ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 417ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 418ceeb9c83SDarrick J. Wong *stat = 0; 419ceeb9c83SDarrick J. Wong info.irec = irec; 420ceeb9c83SDarrick J. Wong 42175d893d1SDarrick J. Wong trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno, 42275d893d1SDarrick J. Wong bno, 0, owner, offset, flags); 42375d893d1SDarrick J. Wong 42475d893d1SDarrick J. Wong /* 42575d893d1SDarrick J. Wong * Historically, we always used the range query to walk every reverse 42675d893d1SDarrick J. Wong * mapping that could possibly overlap the key that the caller asked 42775d893d1SDarrick J. Wong * for, and filter out the ones that don't. That is very slow when 42875d893d1SDarrick J. Wong * there are a lot of records. 42975d893d1SDarrick J. Wong * 43075d893d1SDarrick J. Wong * However, there are two scenarios where the classic btree search can 43175d893d1SDarrick J. Wong * produce correct results -- if the index contains a record that is an 43275d893d1SDarrick J. Wong * exact match for the lookup key; and if there are no other records 43375d893d1SDarrick J. Wong * between the record we want and the key we supplied. 43475d893d1SDarrick J. Wong * 43575d893d1SDarrick J. Wong * As an optimization, try a non-overlapped lookup first. This makes 43675d893d1SDarrick J. Wong * scrub run much faster on most filesystems because bmbt records are 43775d893d1SDarrick J. Wong * usually an exact match for rmap records. If we don't find what we 43875d893d1SDarrick J. Wong * want, we fall back to the overlapped query. 43975d893d1SDarrick J. Wong */ 44075d893d1SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec, 44175d893d1SDarrick J. Wong &found); 44275d893d1SDarrick J. Wong if (error) 44375d893d1SDarrick J. Wong return error; 44475d893d1SDarrick J. Wong if (found) 44575d893d1SDarrick J. Wong error = xfs_rmap_lookup_le_range_helper(cur, irec, &info); 44675d893d1SDarrick J. Wong if (!error) 447ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 448ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper, &info); 44975d893d1SDarrick J. Wong if (error != -ECANCELED) 45075d893d1SDarrick J. Wong return error; 45175d893d1SDarrick J. Wong 45275d893d1SDarrick J. Wong *stat = 1; 453ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 45450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, irec->rm_startblock, 45575d893d1SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, irec->rm_offset, 45675d893d1SDarrick J. Wong irec->rm_flags); 45775d893d1SDarrick J. Wong return 0; 458ceeb9c83SDarrick J. Wong } 459ceeb9c83SDarrick J. Wong 460f922cd90SDarrick J. Wong /* 46168c58e9bSDarrick J. Wong * Perform all the relevant owner checks for a removal op. If we're doing an 46268c58e9bSDarrick J. Wong * unknown-owner removal then we have no owner information to check. 46368c58e9bSDarrick J. Wong */ 46468c58e9bSDarrick J. Wong static int 46568c58e9bSDarrick J. Wong xfs_rmap_free_check_owner( 46668c58e9bSDarrick J. Wong struct xfs_mount *mp, 46768c58e9bSDarrick J. Wong uint64_t ltoff, 46868c58e9bSDarrick J. Wong struct xfs_rmap_irec *rec, 46968c58e9bSDarrick J. Wong xfs_filblks_t len, 47068c58e9bSDarrick J. Wong uint64_t owner, 47168c58e9bSDarrick J. Wong uint64_t offset, 47268c58e9bSDarrick J. Wong unsigned int flags) 47368c58e9bSDarrick J. Wong { 47468c58e9bSDarrick J. Wong int error = 0; 47568c58e9bSDarrick J. Wong 47668c58e9bSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN) 47768c58e9bSDarrick J. Wong return 0; 47868c58e9bSDarrick J. Wong 47968c58e9bSDarrick J. Wong /* Make sure the unwritten flag matches. */ 480f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 481f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) != 482f9e03706SDarrick J. Wong (rec->rm_flags & XFS_RMAP_UNWRITTEN))) { 483f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 484f9e03706SDarrick J. Wong goto out; 485f9e03706SDarrick J. Wong } 48668c58e9bSDarrick J. Wong 48768c58e9bSDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 488f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) { 489f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 490f9e03706SDarrick J. Wong goto out; 491f9e03706SDarrick J. Wong } 49268c58e9bSDarrick J. Wong 49368c58e9bSDarrick J. Wong /* Check the offset, if necessary. */ 49468c58e9bSDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(owner)) 49568c58e9bSDarrick J. Wong goto out; 49668c58e9bSDarrick J. Wong 49768c58e9bSDarrick J. Wong if (flags & XFS_RMAP_BMBT_BLOCK) { 498f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 499f9e03706SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) { 500f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 501f9e03706SDarrick J. Wong goto out; 502f9e03706SDarrick J. Wong } 50368c58e9bSDarrick J. Wong } else { 504f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) { 505f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 506f9e03706SDarrick J. Wong goto out; 507f9e03706SDarrick J. Wong } 508f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 509f9e03706SDarrick J. Wong offset + len > ltoff + rec->rm_blockcount)) { 510f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 511f9e03706SDarrick J. Wong goto out; 512f9e03706SDarrick J. Wong } 51368c58e9bSDarrick J. Wong } 51468c58e9bSDarrick J. Wong 51568c58e9bSDarrick J. Wong out: 51668c58e9bSDarrick J. Wong return error; 51768c58e9bSDarrick J. Wong } 51868c58e9bSDarrick J. Wong 51968c58e9bSDarrick J. Wong /* 520f922cd90SDarrick J. Wong * Find the extent in the rmap btree and remove it. 521f922cd90SDarrick J. Wong * 522f922cd90SDarrick J. Wong * The record we find should always be an exact match for the extent that we're 523f922cd90SDarrick J. Wong * looking for, since we insert them into the btree without modification. 524f922cd90SDarrick J. Wong * 525f922cd90SDarrick J. Wong * Special Case #1: when growing the filesystem, we "free" an extent when 526f922cd90SDarrick J. Wong * growing the last AG. This extent is new space and so it is not tracked as 527f922cd90SDarrick J. Wong * used space in the btree. The growfs code will pass in an owner of 528f922cd90SDarrick J. Wong * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this 529f922cd90SDarrick J. Wong * extent. We verify that - the extent lookup result in a record that does not 530f922cd90SDarrick J. Wong * overlap. 531f922cd90SDarrick J. Wong * 532f922cd90SDarrick J. Wong * Special Case #2: EFIs do not record the owner of the extent, so when 533f922cd90SDarrick J. Wong * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap 534f922cd90SDarrick J. Wong * btree to ignore the owner (i.e. wildcard match) so we don't trigger 535f922cd90SDarrick J. Wong * corruption checks during log recovery. 536f922cd90SDarrick J. Wong */ 537f922cd90SDarrick J. Wong STATIC int 538f922cd90SDarrick J. Wong xfs_rmap_unmap( 539f922cd90SDarrick J. Wong struct xfs_btree_cur *cur, 540f922cd90SDarrick J. Wong xfs_agblock_t bno, 541f922cd90SDarrick J. Wong xfs_extlen_t len, 542f922cd90SDarrick J. Wong bool unwritten, 54366e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 544f922cd90SDarrick J. Wong { 545f922cd90SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 546f922cd90SDarrick J. Wong struct xfs_rmap_irec ltrec; 547f922cd90SDarrick J. Wong uint64_t ltoff; 548f922cd90SDarrick J. Wong int error = 0; 549f922cd90SDarrick J. Wong int i; 550f922cd90SDarrick J. Wong uint64_t owner; 551f922cd90SDarrick J. Wong uint64_t offset; 552f922cd90SDarrick J. Wong unsigned int flags; 553f922cd90SDarrick J. Wong bool ignore_off; 554f922cd90SDarrick J. Wong 555f922cd90SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 556f922cd90SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 557f922cd90SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 558f922cd90SDarrick J. Wong if (unwritten) 559f922cd90SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 56050f02fe3SDave Chinner trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len, 561f922cd90SDarrick J. Wong unwritten, oinfo); 562f922cd90SDarrick J. Wong 563f922cd90SDarrick J. Wong /* 564f922cd90SDarrick J. Wong * We should always have a left record because there's a static record 565f922cd90SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 566f922cd90SDarrick J. Wong * will not ever be removed from the tree. 567f922cd90SDarrick J. Wong */ 5685b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i); 569f922cd90SDarrick J. Wong if (error) 570f922cd90SDarrick J. Wong goto out_error; 571f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 572f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 573f9e03706SDarrick J. Wong goto out_error; 574f9e03706SDarrick J. Wong } 575f922cd90SDarrick J. Wong 576f922cd90SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 57750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, ltrec.rm_startblock, 578f922cd90SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 579f922cd90SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 580f922cd90SDarrick J. Wong ltoff = ltrec.rm_offset; 581f922cd90SDarrick J. Wong 582f922cd90SDarrick J. Wong /* 583f922cd90SDarrick J. Wong * For growfs, the incoming extent must be beyond the left record we 584f922cd90SDarrick J. Wong * just found as it is new space and won't be used by anyone. This is 585f922cd90SDarrick J. Wong * just a corruption check as we don't actually do anything with this 586f922cd90SDarrick J. Wong * extent. Note that we need to use >= instead of > because it might 587f922cd90SDarrick J. Wong * be the case that the "left" extent goes all the way to EOFS. 588f922cd90SDarrick J. Wong */ 589f922cd90SDarrick J. Wong if (owner == XFS_RMAP_OWN_NULL) { 590f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 591f9e03706SDarrick J. Wong bno < 592f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount)) { 593f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 594f9e03706SDarrick J. Wong goto out_error; 595f9e03706SDarrick J. Wong } 596f922cd90SDarrick J. Wong goto out_done; 597f922cd90SDarrick J. Wong } 598f922cd90SDarrick J. Wong 59933df3a9cSDarrick J. Wong /* 60033df3a9cSDarrick J. Wong * If we're doing an unknown-owner removal for EFI recovery, we expect 60133df3a9cSDarrick J. Wong * to find the full range in the rmapbt or nothing at all. If we 60233df3a9cSDarrick J. Wong * don't find any rmaps overlapping either end of the range, we're 60333df3a9cSDarrick J. Wong * done. Hopefully this means that the EFI creator already queued 60433df3a9cSDarrick J. Wong * (and finished) a RUI to remove the rmap. 60533df3a9cSDarrick J. Wong */ 60633df3a9cSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN && 60733df3a9cSDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 60833df3a9cSDarrick J. Wong struct xfs_rmap_irec rtrec; 60933df3a9cSDarrick J. Wong 61033df3a9cSDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 61133df3a9cSDarrick J. Wong if (error) 61233df3a9cSDarrick J. Wong goto out_error; 61333df3a9cSDarrick J. Wong if (i == 0) 61433df3a9cSDarrick J. Wong goto out_done; 61533df3a9cSDarrick J. Wong error = xfs_rmap_get_rec(cur, &rtrec, &i); 61633df3a9cSDarrick J. Wong if (error) 61733df3a9cSDarrick J. Wong goto out_error; 618f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 619f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 620f9e03706SDarrick J. Wong goto out_error; 621f9e03706SDarrick J. Wong } 62233df3a9cSDarrick J. Wong if (rtrec.rm_startblock >= bno + len) 62333df3a9cSDarrick J. Wong goto out_done; 62433df3a9cSDarrick J. Wong } 62533df3a9cSDarrick J. Wong 626f922cd90SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 627f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 628f9e03706SDarrick J. Wong ltrec.rm_startblock > bno || 629f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount < 630f9e03706SDarrick J. Wong bno + len)) { 631f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 632f9e03706SDarrick J. Wong goto out_error; 633f9e03706SDarrick J. Wong } 634f922cd90SDarrick J. Wong 63568c58e9bSDarrick J. Wong /* Check owner information. */ 636a1f69417SEric Sandeen error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner, 63768c58e9bSDarrick J. Wong offset, flags); 63868c58e9bSDarrick J. Wong if (error) 63968c58e9bSDarrick J. Wong goto out_error; 640f922cd90SDarrick J. Wong 641f922cd90SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 642f922cd90SDarrick J. Wong /* exact match, simply remove the record from rmap tree */ 64350f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 644f922cd90SDarrick J. Wong ltrec.rm_startblock, ltrec.rm_blockcount, 645f922cd90SDarrick J. Wong ltrec.rm_owner, ltrec.rm_offset, 646f922cd90SDarrick J. Wong ltrec.rm_flags); 647f922cd90SDarrick J. Wong error = xfs_btree_delete(cur, &i); 648f922cd90SDarrick J. Wong if (error) 649f922cd90SDarrick J. Wong goto out_error; 650f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 651f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 652f9e03706SDarrick J. Wong goto out_error; 653f9e03706SDarrick J. Wong } 654f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 655f922cd90SDarrick J. Wong /* 656f922cd90SDarrick J. Wong * overlap left hand side of extent: move the start, trim the 657f922cd90SDarrick J. Wong * length and update the current record. 658f922cd90SDarrick J. Wong * 659f922cd90SDarrick J. Wong * ltbno ltlen 660f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 661f922cd90SDarrick J. Wong * Freeing: |fffffffff| 662f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 663f922cd90SDarrick J. Wong * bno len 664f922cd90SDarrick J. Wong */ 665f922cd90SDarrick J. Wong ltrec.rm_startblock += len; 666f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 667f922cd90SDarrick J. Wong if (!ignore_off) 668f922cd90SDarrick J. Wong ltrec.rm_offset += len; 669f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 670f922cd90SDarrick J. Wong if (error) 671f922cd90SDarrick J. Wong goto out_error; 672f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 673f922cd90SDarrick J. Wong /* 674f922cd90SDarrick J. Wong * overlap right hand side of extent: trim the length and update 675f922cd90SDarrick J. Wong * the current record. 676f922cd90SDarrick J. Wong * 677f922cd90SDarrick J. Wong * ltbno ltlen 678f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 679f922cd90SDarrick J. Wong * Freeing: |fffffffff| 680f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 681f922cd90SDarrick J. Wong * bno len 682f922cd90SDarrick J. Wong */ 683f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 684f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 685f922cd90SDarrick J. Wong if (error) 686f922cd90SDarrick J. Wong goto out_error; 687f922cd90SDarrick J. Wong } else { 688f922cd90SDarrick J. Wong 689f922cd90SDarrick J. Wong /* 690f922cd90SDarrick J. Wong * overlap middle of extent: trim the length of the existing 691f922cd90SDarrick J. Wong * record to the length of the new left-extent size, increment 692f922cd90SDarrick J. Wong * the insertion position so we can insert a new record 693f922cd90SDarrick J. Wong * containing the remaining right-extent space. 694f922cd90SDarrick J. Wong * 695f922cd90SDarrick J. Wong * ltbno ltlen 696f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 697f922cd90SDarrick J. Wong * Freeing: |fffffffff| 698f922cd90SDarrick J. Wong * Result: |rrrrr| |rrrr| 699f922cd90SDarrick J. Wong * bno len 700f922cd90SDarrick J. Wong */ 701f922cd90SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 702f922cd90SDarrick J. Wong 703f922cd90SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 704f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 705f922cd90SDarrick J. Wong if (error) 706f922cd90SDarrick J. Wong goto out_error; 707f922cd90SDarrick J. Wong 708f922cd90SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 709f922cd90SDarrick J. Wong if (error) 710f922cd90SDarrick J. Wong goto out_error; 711f922cd90SDarrick J. Wong 712f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno + len; 713f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount = orig_len - len - 714f922cd90SDarrick J. Wong ltrec.rm_blockcount; 715f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner = ltrec.rm_owner; 716f922cd90SDarrick J. Wong if (ignore_off) 717f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = 0; 718f922cd90SDarrick J. Wong else 719f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = offset + len; 720f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 72150f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, 722f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock, 723f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount, 724f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner, 725f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset, 726f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags); 727f922cd90SDarrick J. Wong error = xfs_btree_insert(cur, &i); 728f922cd90SDarrick J. Wong if (error) 729f922cd90SDarrick J. Wong goto out_error; 730f922cd90SDarrick J. Wong } 731f922cd90SDarrick J. Wong 732f922cd90SDarrick J. Wong out_done: 73350f02fe3SDave Chinner trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 734f922cd90SDarrick J. Wong unwritten, oinfo); 735f922cd90SDarrick J. Wong out_error: 736f922cd90SDarrick J. Wong if (error) 73750f02fe3SDave Chinner trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno, 738f922cd90SDarrick J. Wong error, _RET_IP_); 739f922cd90SDarrick J. Wong return error; 740f922cd90SDarrick J. Wong } 741f922cd90SDarrick J. Wong 742f922cd90SDarrick J. Wong /* 743f922cd90SDarrick J. Wong * Remove a reference to an extent in the rmap btree. 744f922cd90SDarrick J. Wong */ 745673930c3SDarrick J. Wong int 746673930c3SDarrick J. Wong xfs_rmap_free( 747673930c3SDarrick J. Wong struct xfs_trans *tp, 748673930c3SDarrick J. Wong struct xfs_buf *agbp, 749fa9c3c19SDave Chinner struct xfs_perag *pag, 750673930c3SDarrick J. Wong xfs_agblock_t bno, 751673930c3SDarrick J. Wong xfs_extlen_t len, 75266e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 753673930c3SDarrick J. Wong { 754673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 755f922cd90SDarrick J. Wong struct xfs_btree_cur *cur; 756f922cd90SDarrick J. Wong int error; 757673930c3SDarrick J. Wong 75838c26bfdSDave Chinner if (!xfs_has_rmapbt(mp)) 759673930c3SDarrick J. Wong return 0; 760673930c3SDarrick J. Wong 761fa9c3c19SDave Chinner cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); 762f922cd90SDarrick J. Wong 763f922cd90SDarrick J. Wong error = xfs_rmap_unmap(cur, bno, len, false, oinfo); 764f922cd90SDarrick J. Wong 7650b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 766673930c3SDarrick J. Wong return error; 767673930c3SDarrick J. Wong } 768673930c3SDarrick J. Wong 7690a1b0b38SDarrick J. Wong /* 7700a1b0b38SDarrick J. Wong * A mergeable rmap must have the same owner and the same values for 7710a1b0b38SDarrick J. Wong * the unwritten, attr_fork, and bmbt flags. The startblock and 7720a1b0b38SDarrick J. Wong * offset are checked separately. 7730a1b0b38SDarrick J. Wong */ 7740a1b0b38SDarrick J. Wong static bool 7750a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable( 7760a1b0b38SDarrick J. Wong struct xfs_rmap_irec *irec, 7770a1b0b38SDarrick J. Wong uint64_t owner, 7780a1b0b38SDarrick J. Wong unsigned int flags) 7790a1b0b38SDarrick J. Wong { 7800a1b0b38SDarrick J. Wong if (irec->rm_owner == XFS_RMAP_OWN_NULL) 7810a1b0b38SDarrick J. Wong return false; 7820a1b0b38SDarrick J. Wong if (irec->rm_owner != owner) 7830a1b0b38SDarrick J. Wong return false; 7840a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_UNWRITTEN) ^ 7850a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_UNWRITTEN)) 7860a1b0b38SDarrick J. Wong return false; 7870a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_ATTR_FORK) ^ 7880a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_ATTR_FORK)) 7890a1b0b38SDarrick J. Wong return false; 7900a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_BMBT_BLOCK) ^ 7910a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) 7920a1b0b38SDarrick J. Wong return false; 7930a1b0b38SDarrick J. Wong return true; 7940a1b0b38SDarrick J. Wong } 7950a1b0b38SDarrick J. Wong 7960a1b0b38SDarrick J. Wong /* 7970a1b0b38SDarrick J. Wong * When we allocate a new block, the first thing we do is add a reference to 7980a1b0b38SDarrick J. Wong * the extent in the rmap btree. This takes the form of a [agbno, length, 7990a1b0b38SDarrick J. Wong * owner, offset] record. Flags are encoded in the high bits of the offset 8000a1b0b38SDarrick J. Wong * field. 8010a1b0b38SDarrick J. Wong */ 8020a1b0b38SDarrick J. Wong STATIC int 8030a1b0b38SDarrick J. Wong xfs_rmap_map( 8040a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur, 8050a1b0b38SDarrick J. Wong xfs_agblock_t bno, 8060a1b0b38SDarrick J. Wong xfs_extlen_t len, 8070a1b0b38SDarrick J. Wong bool unwritten, 80866e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 8090a1b0b38SDarrick J. Wong { 8100a1b0b38SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 8110a1b0b38SDarrick J. Wong struct xfs_rmap_irec ltrec; 8120a1b0b38SDarrick J. Wong struct xfs_rmap_irec gtrec; 8130a1b0b38SDarrick J. Wong int have_gt; 8140a1b0b38SDarrick J. Wong int have_lt; 8150a1b0b38SDarrick J. Wong int error = 0; 8160a1b0b38SDarrick J. Wong int i; 8170a1b0b38SDarrick J. Wong uint64_t owner; 8180a1b0b38SDarrick J. Wong uint64_t offset; 8190a1b0b38SDarrick J. Wong unsigned int flags = 0; 8200a1b0b38SDarrick J. Wong bool ignore_off; 8210a1b0b38SDarrick J. Wong 8220a1b0b38SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 8230a1b0b38SDarrick J. Wong ASSERT(owner != 0); 8240a1b0b38SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 8250a1b0b38SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 8260a1b0b38SDarrick J. Wong if (unwritten) 8270a1b0b38SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 82850f02fe3SDave Chinner trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len, 8290a1b0b38SDarrick J. Wong unwritten, oinfo); 83033df3a9cSDarrick J. Wong ASSERT(!xfs_rmap_should_skip_owner_update(oinfo)); 8310a1b0b38SDarrick J. Wong 8320a1b0b38SDarrick J. Wong /* 8330a1b0b38SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 8340a1b0b38SDarrick J. Wong * record for our insertion point. This will also give us the record for 8350a1b0b38SDarrick J. Wong * start block contiguity tests. 8360a1b0b38SDarrick J. Wong */ 8375b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, 8380a1b0b38SDarrick J. Wong &have_lt); 8390a1b0b38SDarrick J. Wong if (error) 8400a1b0b38SDarrick J. Wong goto out_error; 841fa248de9SDarrick J. Wong if (have_lt) { 8420a1b0b38SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 84350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, ltrec.rm_startblock, 8440a1b0b38SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 8450a1b0b38SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 8460a1b0b38SDarrick J. Wong 8470a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(<rec, owner, flags)) 8480a1b0b38SDarrick J. Wong have_lt = 0; 849fa248de9SDarrick J. Wong } 8500a1b0b38SDarrick J. Wong 851f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 852f9e03706SDarrick J. Wong have_lt != 0 && 853f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount > bno)) { 854f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 855f9e03706SDarrick J. Wong goto out_error; 856f9e03706SDarrick J. Wong } 8570a1b0b38SDarrick J. Wong 8580a1b0b38SDarrick J. Wong /* 8590a1b0b38SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 8600a1b0b38SDarrick J. Wong * insertion point. This will give us the record for end block 8610a1b0b38SDarrick J. Wong * contiguity tests. 8620a1b0b38SDarrick J. Wong */ 8630a1b0b38SDarrick J. Wong error = xfs_btree_increment(cur, 0, &have_gt); 8640a1b0b38SDarrick J. Wong if (error) 8650a1b0b38SDarrick J. Wong goto out_error; 8660a1b0b38SDarrick J. Wong if (have_gt) { 8670a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 8680a1b0b38SDarrick J. Wong if (error) 8690a1b0b38SDarrick J. Wong goto out_error; 870f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) { 871f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 872f9e03706SDarrick J. Wong goto out_error; 873f9e03706SDarrick J. Wong } 874f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) { 875f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 876f9e03706SDarrick J. Wong goto out_error; 877f9e03706SDarrick J. Wong } 8780a1b0b38SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 87950f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, gtrec.rm_startblock, 8800a1b0b38SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 8810a1b0b38SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 8820a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 8830a1b0b38SDarrick J. Wong have_gt = 0; 8840a1b0b38SDarrick J. Wong } 8850a1b0b38SDarrick J. Wong 8860a1b0b38SDarrick J. Wong /* 8870a1b0b38SDarrick J. Wong * Note: cursor currently points one record to the right of ltrec, even 8880a1b0b38SDarrick J. Wong * if there is no record in the tree to the right. 8890a1b0b38SDarrick J. Wong */ 8900a1b0b38SDarrick J. Wong if (have_lt && 8910a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 8920a1b0b38SDarrick J. Wong (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { 8930a1b0b38SDarrick J. Wong /* 8940a1b0b38SDarrick J. Wong * left edge contiguous, merge into left record. 8950a1b0b38SDarrick J. Wong * 8960a1b0b38SDarrick J. Wong * ltbno ltlen 8970a1b0b38SDarrick J. Wong * orig: |ooooooooo| 8980a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8990a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 9000a1b0b38SDarrick J. Wong * bno len 9010a1b0b38SDarrick J. Wong */ 9020a1b0b38SDarrick J. Wong ltrec.rm_blockcount += len; 9030a1b0b38SDarrick J. Wong if (have_gt && 9040a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 9050a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset) && 9060a1b0b38SDarrick J. Wong (unsigned long)ltrec.rm_blockcount + len + 9070a1b0b38SDarrick J. Wong gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { 9080a1b0b38SDarrick J. Wong /* 9090a1b0b38SDarrick J. Wong * right edge also contiguous, delete right record 9100a1b0b38SDarrick J. Wong * and merge into left record. 9110a1b0b38SDarrick J. Wong * 9120a1b0b38SDarrick J. Wong * ltbno ltlen gtbno gtlen 9130a1b0b38SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 9140a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 9150a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 9160a1b0b38SDarrick J. Wong */ 9170a1b0b38SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 91850f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 9190a1b0b38SDarrick J. Wong gtrec.rm_startblock, 9200a1b0b38SDarrick J. Wong gtrec.rm_blockcount, 9210a1b0b38SDarrick J. Wong gtrec.rm_owner, 9220a1b0b38SDarrick J. Wong gtrec.rm_offset, 9230a1b0b38SDarrick J. Wong gtrec.rm_flags); 9240a1b0b38SDarrick J. Wong error = xfs_btree_delete(cur, &i); 9250a1b0b38SDarrick J. Wong if (error) 9260a1b0b38SDarrick J. Wong goto out_error; 927f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 928f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 929f9e03706SDarrick J. Wong goto out_error; 930f9e03706SDarrick J. Wong } 9310a1b0b38SDarrick J. Wong } 9320a1b0b38SDarrick J. Wong 9330a1b0b38SDarrick J. Wong /* point the cursor back to the left record and update */ 9340a1b0b38SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &have_gt); 9350a1b0b38SDarrick J. Wong if (error) 9360a1b0b38SDarrick J. Wong goto out_error; 9370a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 9380a1b0b38SDarrick J. Wong if (error) 9390a1b0b38SDarrick J. Wong goto out_error; 9400a1b0b38SDarrick J. Wong } else if (have_gt && 9410a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 9420a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset)) { 9430a1b0b38SDarrick J. Wong /* 9440a1b0b38SDarrick J. Wong * right edge contiguous, merge into right record. 9450a1b0b38SDarrick J. Wong * 9460a1b0b38SDarrick J. Wong * gtbno gtlen 9470a1b0b38SDarrick J. Wong * Orig: |ooooooooo| 9480a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 9490a1b0b38SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 9500a1b0b38SDarrick J. Wong * bno len 9510a1b0b38SDarrick J. Wong */ 9520a1b0b38SDarrick J. Wong gtrec.rm_startblock = bno; 9530a1b0b38SDarrick J. Wong gtrec.rm_blockcount += len; 9540a1b0b38SDarrick J. Wong if (!ignore_off) 9550a1b0b38SDarrick J. Wong gtrec.rm_offset = offset; 9560a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, >rec); 9570a1b0b38SDarrick J. Wong if (error) 9580a1b0b38SDarrick J. Wong goto out_error; 9590a1b0b38SDarrick J. Wong } else { 9600a1b0b38SDarrick J. Wong /* 9610a1b0b38SDarrick J. Wong * no contiguous edge with identical owner, insert 9620a1b0b38SDarrick J. Wong * new record at current cursor position. 9630a1b0b38SDarrick J. Wong */ 9640a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 9650a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 9660a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 9670a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 9680a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 96950f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len, 9700a1b0b38SDarrick J. Wong owner, offset, flags); 9710a1b0b38SDarrick J. Wong error = xfs_btree_insert(cur, &i); 9720a1b0b38SDarrick J. Wong if (error) 9730a1b0b38SDarrick J. Wong goto out_error; 974f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 975f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 976f9e03706SDarrick J. Wong goto out_error; 977f9e03706SDarrick J. Wong } 9780a1b0b38SDarrick J. Wong } 9790a1b0b38SDarrick J. Wong 98050f02fe3SDave Chinner trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 9810a1b0b38SDarrick J. Wong unwritten, oinfo); 9820a1b0b38SDarrick J. Wong out_error: 9830a1b0b38SDarrick J. Wong if (error) 98450f02fe3SDave Chinner trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno, 9850a1b0b38SDarrick J. Wong error, _RET_IP_); 9860a1b0b38SDarrick J. Wong return error; 9870a1b0b38SDarrick J. Wong } 9880a1b0b38SDarrick J. Wong 9890a1b0b38SDarrick J. Wong /* 9900a1b0b38SDarrick J. Wong * Add a reference to an extent in the rmap btree. 9910a1b0b38SDarrick J. Wong */ 992673930c3SDarrick J. Wong int 993673930c3SDarrick J. Wong xfs_rmap_alloc( 994673930c3SDarrick J. Wong struct xfs_trans *tp, 995673930c3SDarrick J. Wong struct xfs_buf *agbp, 996fa9c3c19SDave Chinner struct xfs_perag *pag, 997673930c3SDarrick J. Wong xfs_agblock_t bno, 998673930c3SDarrick J. Wong xfs_extlen_t len, 99966e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1000673930c3SDarrick J. Wong { 1001673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 10020a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur; 10030a1b0b38SDarrick J. Wong int error; 1004673930c3SDarrick J. Wong 100538c26bfdSDave Chinner if (!xfs_has_rmapbt(mp)) 1006673930c3SDarrick J. Wong return 0; 1007673930c3SDarrick J. Wong 1008fa9c3c19SDave Chinner cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); 10090a1b0b38SDarrick J. Wong error = xfs_rmap_map(cur, bno, len, false, oinfo); 10100a1b0b38SDarrick J. Wong 10110b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 1012673930c3SDarrick J. Wong return error; 1013673930c3SDarrick J. Wong } 1014c543838aSDarrick J. Wong 1015fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG (1 << 0) 1016fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG (1 << 1) 1017fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING (1 << 2) 1018fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING (1 << 3) 1019fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID (1 << 6) 1020fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID (1 << 7) 1021fb7d9267SDarrick J. Wong 1022fb7d9267SDarrick J. Wong #define LEFT r[0] 1023fb7d9267SDarrick J. Wong #define RIGHT r[1] 1024fb7d9267SDarrick J. Wong #define PREV r[2] 1025fb7d9267SDarrick J. Wong #define NEW r[3] 1026fb7d9267SDarrick J. Wong 1027fb7d9267SDarrick J. Wong /* 1028fb7d9267SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. 1029fb7d9267SDarrick J. Wong * Does not handle overlapping extents. 1030fb7d9267SDarrick J. Wong */ 1031fb7d9267SDarrick J. Wong STATIC int 1032fb7d9267SDarrick J. Wong xfs_rmap_convert( 1033fb7d9267SDarrick J. Wong struct xfs_btree_cur *cur, 1034fb7d9267SDarrick J. Wong xfs_agblock_t bno, 1035fb7d9267SDarrick J. Wong xfs_extlen_t len, 1036fb7d9267SDarrick J. Wong bool unwritten, 103766e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1038fb7d9267SDarrick J. Wong { 1039fb7d9267SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1040fb7d9267SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 104166e3237eSDarrick J. Wong /* left is 0, right is 1, */ 104266e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 1043fb7d9267SDarrick J. Wong uint64_t owner; 1044fb7d9267SDarrick J. Wong uint64_t offset; 1045fb7d9267SDarrick J. Wong uint64_t new_endoff; 1046fb7d9267SDarrick J. Wong unsigned int oldext; 1047fb7d9267SDarrick J. Wong unsigned int newext; 1048fb7d9267SDarrick J. Wong unsigned int flags = 0; 1049fb7d9267SDarrick J. Wong int i; 1050fb7d9267SDarrick J. Wong int state = 0; 1051fb7d9267SDarrick J. Wong int error; 1052fb7d9267SDarrick J. Wong 1053fb7d9267SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1054fb7d9267SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 1055fb7d9267SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 1056fb7d9267SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 1057fb7d9267SDarrick J. Wong new_endoff = offset + len; 105850f02fe3SDave Chinner trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len, 1059fb7d9267SDarrick J. Wong unwritten, oinfo); 1060fb7d9267SDarrick J. Wong 1061fb7d9267SDarrick J. Wong /* 1062fb7d9267SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 1063fb7d9267SDarrick J. Wong * record for our insertion point. This will also give us the record for 1064fb7d9267SDarrick J. Wong * start block contiguity tests. 1065fb7d9267SDarrick J. Wong */ 10665b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i); 1067fb7d9267SDarrick J. Wong if (error) 1068fb7d9267SDarrick J. Wong goto done; 1069f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1070f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1071f9e03706SDarrick J. Wong goto done; 1072f9e03706SDarrick J. Wong } 1073fb7d9267SDarrick J. Wong 1074fb7d9267SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 107550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, PREV.rm_startblock, 1076fb7d9267SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 1077fb7d9267SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 1078fb7d9267SDarrick J. Wong 1079fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 1080fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 1081fb7d9267SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 1082fb7d9267SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 1083fb7d9267SDarrick J. Wong 1084fb7d9267SDarrick J. Wong /* 1085fb7d9267SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 1086fb7d9267SDarrick J. Wong * extent is being replaced by a newext allocation. 1087fb7d9267SDarrick J. Wong */ 1088fb7d9267SDarrick J. Wong if (PREV.rm_offset == offset) 1089fb7d9267SDarrick J. Wong state |= RMAP_LEFT_FILLING; 1090fb7d9267SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 1091fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 1092fb7d9267SDarrick J. Wong 1093fb7d9267SDarrick J. Wong /* 1094fb7d9267SDarrick J. Wong * Decrement the cursor to see if we have a left-adjacent record to our 1095fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1096fb7d9267SDarrick J. Wong * contiguity tests. 1097fb7d9267SDarrick J. Wong */ 1098fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1099fb7d9267SDarrick J. Wong if (error) 1100fb7d9267SDarrick J. Wong goto done; 1101fb7d9267SDarrick J. Wong if (i) { 1102fb7d9267SDarrick J. Wong state |= RMAP_LEFT_VALID; 1103fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &LEFT, &i); 1104fb7d9267SDarrick J. Wong if (error) 1105fb7d9267SDarrick J. Wong goto done; 1106f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1107f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1108f9e03706SDarrick J. Wong goto done; 1109f9e03706SDarrick J. Wong } 1110f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1111f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount > 1112f9e03706SDarrick J. Wong bno)) { 1113f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1114f9e03706SDarrick J. Wong goto done; 1115f9e03706SDarrick J. Wong } 1116fb7d9267SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 111750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, LEFT.rm_startblock, 1118fb7d9267SDarrick J. Wong LEFT.rm_blockcount, LEFT.rm_owner, 1119fb7d9267SDarrick J. Wong LEFT.rm_offset, LEFT.rm_flags); 1120fb7d9267SDarrick J. Wong if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && 1121fb7d9267SDarrick J. Wong LEFT.rm_offset + LEFT.rm_blockcount == offset && 1122fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&LEFT, owner, newext)) 1123fb7d9267SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 1124fb7d9267SDarrick J. Wong } 1125fb7d9267SDarrick J. Wong 1126fb7d9267SDarrick J. Wong /* 1127fb7d9267SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 1128fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1129fb7d9267SDarrick J. Wong * contiguity tests. 1130fb7d9267SDarrick J. Wong */ 1131fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1132fb7d9267SDarrick J. Wong if (error) 1133fb7d9267SDarrick J. Wong goto done; 1134f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1135f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1136f9e03706SDarrick J. Wong goto done; 1137f9e03706SDarrick J. Wong } 1138fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1139fb7d9267SDarrick J. Wong if (error) 1140fb7d9267SDarrick J. Wong goto done; 1141fb7d9267SDarrick J. Wong if (i) { 1142fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_VALID; 1143fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 1144fb7d9267SDarrick J. Wong if (error) 1145fb7d9267SDarrick J. Wong goto done; 1146f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1147f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1148f9e03706SDarrick J. Wong goto done; 1149f9e03706SDarrick J. Wong } 1150f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { 1151f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1152f9e03706SDarrick J. Wong goto done; 1153f9e03706SDarrick J. Wong } 1154fb7d9267SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 115550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock, 1156fb7d9267SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 1157fb7d9267SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 1158fb7d9267SDarrick J. Wong if (bno + len == RIGHT.rm_startblock && 1159fb7d9267SDarrick J. Wong offset + len == RIGHT.rm_offset && 1160fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 1161fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 1162fb7d9267SDarrick J. Wong } 1163fb7d9267SDarrick J. Wong 1164fb7d9267SDarrick J. Wong /* check that left + prev + right is not too long */ 1165fb7d9267SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1166fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 1167fb7d9267SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1168fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 1169fb7d9267SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 1170fb7d9267SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 1171fb7d9267SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 1172fb7d9267SDarrick J. Wong 117350f02fe3SDave Chinner trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state, 1174fb7d9267SDarrick J. Wong _RET_IP_); 1175fb7d9267SDarrick J. Wong 1176fb7d9267SDarrick J. Wong /* reset the cursor back to PREV */ 11775b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i); 1178fb7d9267SDarrick J. Wong if (error) 1179fb7d9267SDarrick J. Wong goto done; 1180f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1181f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1182f9e03706SDarrick J. Wong goto done; 1183f9e03706SDarrick J. Wong } 1184fb7d9267SDarrick J. Wong 1185fb7d9267SDarrick J. Wong /* 1186fb7d9267SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 1187fb7d9267SDarrick J. Wong */ 1188fb7d9267SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1189fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 1190fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1191fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1192fb7d9267SDarrick J. Wong /* 1193fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1194fb7d9267SDarrick J. Wong * The left and right neighbors are both contiguous with new. 1195fb7d9267SDarrick J. Wong */ 1196fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1197fb7d9267SDarrick J. Wong if (error) 1198fb7d9267SDarrick J. Wong goto done; 1199f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1200f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1201f9e03706SDarrick J. Wong goto done; 1202f9e03706SDarrick J. Wong } 120350f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1204fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1205fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1206fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1207fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1208fb7d9267SDarrick J. Wong if (error) 1209fb7d9267SDarrick J. Wong goto done; 1210f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1211f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1212f9e03706SDarrick J. Wong goto done; 1213f9e03706SDarrick J. Wong } 1214fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1215fb7d9267SDarrick J. Wong if (error) 1216fb7d9267SDarrick J. Wong goto done; 1217f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1218f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1219f9e03706SDarrick J. Wong goto done; 1220f9e03706SDarrick J. Wong } 122150f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1222fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1223fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1224fb7d9267SDarrick J. Wong PREV.rm_flags); 1225fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1226fb7d9267SDarrick J. Wong if (error) 1227fb7d9267SDarrick J. Wong goto done; 1228f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1229f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1230f9e03706SDarrick J. Wong goto done; 1231f9e03706SDarrick J. Wong } 1232fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1233fb7d9267SDarrick J. Wong if (error) 1234fb7d9267SDarrick J. Wong goto done; 1235f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1236f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1237f9e03706SDarrick J. Wong goto done; 1238f9e03706SDarrick J. Wong } 1239fb7d9267SDarrick J. Wong NEW = LEFT; 1240fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 1241fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1242fb7d9267SDarrick J. Wong if (error) 1243fb7d9267SDarrick J. Wong goto done; 1244fb7d9267SDarrick J. Wong break; 1245fb7d9267SDarrick J. Wong 1246fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1247fb7d9267SDarrick J. Wong /* 1248fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1249fb7d9267SDarrick J. Wong * The left neighbor is contiguous, the right is not. 1250fb7d9267SDarrick J. Wong */ 125150f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1252fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1253fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1254fb7d9267SDarrick J. Wong PREV.rm_flags); 1255fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1256fb7d9267SDarrick J. Wong if (error) 1257fb7d9267SDarrick J. Wong goto done; 1258f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1259f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1260f9e03706SDarrick J. Wong goto done; 1261f9e03706SDarrick J. Wong } 1262fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1263fb7d9267SDarrick J. Wong if (error) 1264fb7d9267SDarrick J. Wong goto done; 1265f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1266f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1267f9e03706SDarrick J. Wong goto done; 1268f9e03706SDarrick J. Wong } 1269fb7d9267SDarrick J. Wong NEW = LEFT; 1270fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 1271fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1272fb7d9267SDarrick J. Wong if (error) 1273fb7d9267SDarrick J. Wong goto done; 1274fb7d9267SDarrick J. Wong break; 1275fb7d9267SDarrick J. Wong 1276fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1277fb7d9267SDarrick J. Wong /* 1278fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1279fb7d9267SDarrick J. Wong * The right neighbor is contiguous, the left is not. 1280fb7d9267SDarrick J. Wong */ 1281fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1282fb7d9267SDarrick J. Wong if (error) 1283fb7d9267SDarrick J. Wong goto done; 1284f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1285f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1286f9e03706SDarrick J. Wong goto done; 1287f9e03706SDarrick J. Wong } 128850f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1289fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1290fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1291fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1292fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1293fb7d9267SDarrick J. Wong if (error) 1294fb7d9267SDarrick J. Wong goto done; 1295f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1296f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1297f9e03706SDarrick J. Wong goto done; 1298f9e03706SDarrick J. Wong } 1299fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1300fb7d9267SDarrick J. Wong if (error) 1301fb7d9267SDarrick J. Wong goto done; 1302f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1303f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1304f9e03706SDarrick J. Wong goto done; 1305f9e03706SDarrick J. Wong } 1306fb7d9267SDarrick J. Wong NEW = PREV; 1307fb7d9267SDarrick J. Wong NEW.rm_blockcount = len + RIGHT.rm_blockcount; 1308fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1309fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1310fb7d9267SDarrick J. Wong if (error) 1311fb7d9267SDarrick J. Wong goto done; 1312fb7d9267SDarrick J. Wong break; 1313fb7d9267SDarrick J. Wong 1314fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1315fb7d9267SDarrick J. Wong /* 1316fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1317fb7d9267SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 1318fb7d9267SDarrick J. Wong * the new one. 1319fb7d9267SDarrick J. Wong */ 1320fb7d9267SDarrick J. Wong NEW = PREV; 1321fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1322fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1323fb7d9267SDarrick J. Wong if (error) 1324fb7d9267SDarrick J. Wong goto done; 1325fb7d9267SDarrick J. Wong break; 1326fb7d9267SDarrick J. Wong 1327fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1328fb7d9267SDarrick J. Wong /* 1329fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1330fb7d9267SDarrick J. Wong * The left neighbor is contiguous. 1331fb7d9267SDarrick J. Wong */ 1332fb7d9267SDarrick J. Wong NEW = PREV; 1333fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1334fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1335fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1336fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1337fb7d9267SDarrick J. Wong if (error) 1338fb7d9267SDarrick J. Wong goto done; 1339fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1340fb7d9267SDarrick J. Wong if (error) 1341fb7d9267SDarrick J. Wong goto done; 1342fb7d9267SDarrick J. Wong NEW = LEFT; 1343fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1344fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1345fb7d9267SDarrick J. Wong if (error) 1346fb7d9267SDarrick J. Wong goto done; 1347fb7d9267SDarrick J. Wong break; 1348fb7d9267SDarrick J. Wong 1349fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING: 1350fb7d9267SDarrick J. Wong /* 1351fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1352fb7d9267SDarrick J. Wong * The left neighbor is not contiguous. 1353fb7d9267SDarrick J. Wong */ 1354fb7d9267SDarrick J. Wong NEW = PREV; 1355fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1356fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1357fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1358fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1359fb7d9267SDarrick J. Wong if (error) 1360fb7d9267SDarrick J. Wong goto done; 1361fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1362fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1363fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1364fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1365fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1366fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 136750f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, 1368fb7d9267SDarrick J. Wong len, owner, offset, newext); 1369fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1370fb7d9267SDarrick J. Wong if (error) 1371fb7d9267SDarrick J. Wong goto done; 1372f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1373f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1374f9e03706SDarrick J. Wong goto done; 1375f9e03706SDarrick J. Wong } 1376fb7d9267SDarrick J. Wong break; 1377fb7d9267SDarrick J. Wong 1378fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1379fb7d9267SDarrick J. Wong /* 1380fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1381fb7d9267SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 1382fb7d9267SDarrick J. Wong */ 1383fb7d9267SDarrick J. Wong NEW = PREV; 1384fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1385fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1386fb7d9267SDarrick J. Wong if (error) 1387fb7d9267SDarrick J. Wong goto done; 1388fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1389fb7d9267SDarrick J. Wong if (error) 1390fb7d9267SDarrick J. Wong goto done; 1391fb7d9267SDarrick J. Wong NEW = RIGHT; 1392fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1393fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1394fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1395fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1396fb7d9267SDarrick J. Wong if (error) 1397fb7d9267SDarrick J. Wong goto done; 1398fb7d9267SDarrick J. Wong break; 1399fb7d9267SDarrick J. Wong 1400fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING: 1401fb7d9267SDarrick J. Wong /* 1402fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1403fb7d9267SDarrick J. Wong * The right neighbor is not contiguous. 1404fb7d9267SDarrick J. Wong */ 1405fb7d9267SDarrick J. Wong NEW = PREV; 1406fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1407fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1408fb7d9267SDarrick J. Wong if (error) 1409fb7d9267SDarrick J. Wong goto done; 1410fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1411fb7d9267SDarrick J. Wong oldext, &i); 1412fb7d9267SDarrick J. Wong if (error) 1413fb7d9267SDarrick J. Wong goto done; 1414f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) { 1415f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1416f9e03706SDarrick J. Wong goto done; 1417f9e03706SDarrick J. Wong } 1418fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1419fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1420fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1421fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1422fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1423fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 142450f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, 1425fb7d9267SDarrick J. Wong len, owner, offset, newext); 1426fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1427fb7d9267SDarrick J. Wong if (error) 1428fb7d9267SDarrick J. Wong goto done; 1429f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1430f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1431f9e03706SDarrick J. Wong goto done; 1432f9e03706SDarrick J. Wong } 1433fb7d9267SDarrick J. Wong break; 1434fb7d9267SDarrick J. Wong 1435fb7d9267SDarrick J. Wong case 0: 1436fb7d9267SDarrick J. Wong /* 1437fb7d9267SDarrick J. Wong * Setting the middle part of a previous oldext extent to 1438fb7d9267SDarrick J. Wong * newext. Contiguity is impossible here. 1439fb7d9267SDarrick J. Wong * One extent becomes three extents. 1440fb7d9267SDarrick J. Wong */ 1441fb7d9267SDarrick J. Wong /* new right extent - oldext */ 1442fb7d9267SDarrick J. Wong NEW.rm_startblock = bno + len; 1443fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1444fb7d9267SDarrick J. Wong NEW.rm_offset = new_endoff; 1445fb7d9267SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 1446fb7d9267SDarrick J. Wong new_endoff; 1447fb7d9267SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 1448fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1449fb7d9267SDarrick J. Wong if (error) 1450fb7d9267SDarrick J. Wong goto done; 1451fb7d9267SDarrick J. Wong /* new left extent - oldext */ 1452fb7d9267SDarrick J. Wong NEW = PREV; 1453fb7d9267SDarrick J. Wong NEW.rm_blockcount = offset - PREV.rm_offset; 1454fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 145550f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, 1456fb7d9267SDarrick J. Wong NEW.rm_startblock, NEW.rm_blockcount, 1457fb7d9267SDarrick J. Wong NEW.rm_owner, NEW.rm_offset, 1458fb7d9267SDarrick J. Wong NEW.rm_flags); 1459fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1460fb7d9267SDarrick J. Wong if (error) 1461fb7d9267SDarrick J. Wong goto done; 1462f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1463f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1464f9e03706SDarrick J. Wong goto done; 1465f9e03706SDarrick J. Wong } 1466fb7d9267SDarrick J. Wong /* 1467fb7d9267SDarrick J. Wong * Reset the cursor to the position of the new extent 1468fb7d9267SDarrick J. Wong * we are about to insert as we can't trust it after 1469fb7d9267SDarrick J. Wong * the previous insert. 1470fb7d9267SDarrick J. Wong */ 1471fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1472fb7d9267SDarrick J. Wong oldext, &i); 1473fb7d9267SDarrick J. Wong if (error) 1474fb7d9267SDarrick J. Wong goto done; 1475f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) { 1476f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1477f9e03706SDarrick J. Wong goto done; 1478f9e03706SDarrick J. Wong } 1479fb7d9267SDarrick J. Wong /* new middle extent - newext */ 1480fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; 1481fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags |= newext; 148250f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len, 1483fb7d9267SDarrick J. Wong owner, offset, newext); 1484fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1485fb7d9267SDarrick J. Wong if (error) 1486fb7d9267SDarrick J. Wong goto done; 1487f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1488f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1489f9e03706SDarrick J. Wong goto done; 1490f9e03706SDarrick J. Wong } 1491fb7d9267SDarrick J. Wong break; 1492fb7d9267SDarrick J. Wong 1493fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1494fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1495fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 1496fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1497fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1498fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG: 1499fb7d9267SDarrick J. Wong case RMAP_RIGHT_CONTIG: 1500fb7d9267SDarrick J. Wong /* 1501fb7d9267SDarrick J. Wong * These cases are all impossible. 1502fb7d9267SDarrick J. Wong */ 1503fb7d9267SDarrick J. Wong ASSERT(0); 1504fb7d9267SDarrick J. Wong } 1505fb7d9267SDarrick J. Wong 150650f02fe3SDave Chinner trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 1507fb7d9267SDarrick J. Wong unwritten, oinfo); 1508fb7d9267SDarrick J. Wong done: 1509fb7d9267SDarrick J. Wong if (error) 1510fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 151150f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 1512fb7d9267SDarrick J. Wong return error; 1513fb7d9267SDarrick J. Wong } 1514fb7d9267SDarrick J. Wong 15153f165b33SDarrick J. Wong /* 15163f165b33SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. If there is no 15173f165b33SDarrick J. Wong * possibility of overlapping extents, delegate to the simpler convert 15183f165b33SDarrick J. Wong * function. 15193f165b33SDarrick J. Wong */ 15203f165b33SDarrick J. Wong STATIC int 15213f165b33SDarrick J. Wong xfs_rmap_convert_shared( 15223f165b33SDarrick J. Wong struct xfs_btree_cur *cur, 15233f165b33SDarrick J. Wong xfs_agblock_t bno, 15243f165b33SDarrick J. Wong xfs_extlen_t len, 15253f165b33SDarrick J. Wong bool unwritten, 152666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 15273f165b33SDarrick J. Wong { 15283f165b33SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 15293f165b33SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 153066e3237eSDarrick J. Wong /* left is 0, right is 1, */ 153166e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 15323f165b33SDarrick J. Wong uint64_t owner; 15333f165b33SDarrick J. Wong uint64_t offset; 15343f165b33SDarrick J. Wong uint64_t new_endoff; 15353f165b33SDarrick J. Wong unsigned int oldext; 15363f165b33SDarrick J. Wong unsigned int newext; 15373f165b33SDarrick J. Wong unsigned int flags = 0; 15383f165b33SDarrick J. Wong int i; 15393f165b33SDarrick J. Wong int state = 0; 15403f165b33SDarrick J. Wong int error; 15413f165b33SDarrick J. Wong 15423f165b33SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 15433f165b33SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 15443f165b33SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 15453f165b33SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 15463f165b33SDarrick J. Wong new_endoff = offset + len; 154750f02fe3SDave Chinner trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len, 15483f165b33SDarrick J. Wong unwritten, oinfo); 15493f165b33SDarrick J. Wong 15503f165b33SDarrick J. Wong /* 15513f165b33SDarrick J. Wong * For the initial lookup, look for and exact match or the left-adjacent 15523f165b33SDarrick J. Wong * record for our insertion point. This will also give us the record for 15533f165b33SDarrick J. Wong * start block contiguity tests. 15543f165b33SDarrick J. Wong */ 1555ea843989SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext, 15563f165b33SDarrick J. Wong &PREV, &i); 155752101dfeSDarrick J. Wong if (error) 155852101dfeSDarrick J. Wong goto done; 1559f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1560f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1561f9e03706SDarrick J. Wong goto done; 1562f9e03706SDarrick J. Wong } 15633f165b33SDarrick J. Wong 15643f165b33SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 15653f165b33SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 15663f165b33SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 15673f165b33SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 15683f165b33SDarrick J. Wong 15693f165b33SDarrick J. Wong /* 15703f165b33SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 15713f165b33SDarrick J. Wong * extent is being replaced by a newext allocation. 15723f165b33SDarrick J. Wong */ 15733f165b33SDarrick J. Wong if (PREV.rm_offset == offset) 15743f165b33SDarrick J. Wong state |= RMAP_LEFT_FILLING; 15753f165b33SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 15763f165b33SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 15773f165b33SDarrick J. Wong 15783f165b33SDarrick J. Wong /* Is there a left record that abuts our range? */ 15793f165b33SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, 15803f165b33SDarrick J. Wong &LEFT, &i); 15813f165b33SDarrick J. Wong if (error) 15823f165b33SDarrick J. Wong goto done; 15833f165b33SDarrick J. Wong if (i) { 15843f165b33SDarrick J. Wong state |= RMAP_LEFT_VALID; 1585f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1586f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount > 1587f9e03706SDarrick J. Wong bno)) { 1588f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1589f9e03706SDarrick J. Wong goto done; 1590f9e03706SDarrick J. Wong } 15913f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) 15923f165b33SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 15933f165b33SDarrick J. Wong } 15943f165b33SDarrick J. Wong 15953f165b33SDarrick J. Wong /* Is there a right record that abuts our range? */ 15963f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 15973f165b33SDarrick J. Wong newext, &i); 15983f165b33SDarrick J. Wong if (error) 15993f165b33SDarrick J. Wong goto done; 16003f165b33SDarrick J. Wong if (i) { 16013f165b33SDarrick J. Wong state |= RMAP_RIGHT_VALID; 16023f165b33SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 16033f165b33SDarrick J. Wong if (error) 16043f165b33SDarrick J. Wong goto done; 1605f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1606f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1607f9e03706SDarrick J. Wong goto done; 1608f9e03706SDarrick J. Wong } 1609f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { 1610f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1611f9e03706SDarrick J. Wong goto done; 1612f9e03706SDarrick J. Wong } 16133f165b33SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 161450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock, 16153f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 16163f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 16173f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 16183f165b33SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 16193f165b33SDarrick J. Wong } 16203f165b33SDarrick J. Wong 16213f165b33SDarrick J. Wong /* check that left + prev + right is not too long */ 16223f165b33SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16233f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 16243f165b33SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16253f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 16263f165b33SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 16273f165b33SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 16283f165b33SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 16293f165b33SDarrick J. Wong 163050f02fe3SDave Chinner trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state, 16313f165b33SDarrick J. Wong _RET_IP_); 16323f165b33SDarrick J. Wong /* 16333f165b33SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 16343f165b33SDarrick J. Wong */ 16353f165b33SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16363f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 16373f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16383f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 16393f165b33SDarrick J. Wong /* 16403f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16413f165b33SDarrick J. Wong * The left and right neighbors are both contiguous with new. 16423f165b33SDarrick J. Wong */ 16433f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 16443f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 16453f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 16463f165b33SDarrick J. Wong if (error) 16473f165b33SDarrick J. Wong goto done; 16483f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 16493f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 16503f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 16513f165b33SDarrick J. Wong if (error) 16523f165b33SDarrick J. Wong goto done; 16533f165b33SDarrick J. Wong NEW = LEFT; 16543f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16553f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16563f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16573f165b33SDarrick J. Wong if (error) 16583f165b33SDarrick J. Wong goto done; 1659f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1660f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1661f9e03706SDarrick J. Wong goto done; 1662f9e03706SDarrick J. Wong } 16633f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 16643f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16653f165b33SDarrick J. Wong if (error) 16663f165b33SDarrick J. Wong goto done; 16673f165b33SDarrick J. Wong break; 16683f165b33SDarrick J. Wong 16693f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 16703f165b33SDarrick J. Wong /* 16713f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16723f165b33SDarrick J. Wong * The left neighbor is contiguous, the right is not. 16733f165b33SDarrick J. Wong */ 16743f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 16753f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 16763f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 16773f165b33SDarrick J. Wong if (error) 16783f165b33SDarrick J. Wong goto done; 16793f165b33SDarrick J. Wong NEW = LEFT; 16803f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16813f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16823f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16833f165b33SDarrick J. Wong if (error) 16843f165b33SDarrick J. Wong goto done; 1685f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1686f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1687f9e03706SDarrick J. Wong goto done; 1688f9e03706SDarrick J. Wong } 16893f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 16903f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16913f165b33SDarrick J. Wong if (error) 16923f165b33SDarrick J. Wong goto done; 16933f165b33SDarrick J. Wong break; 16943f165b33SDarrick J. Wong 16953f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 16963f165b33SDarrick J. Wong /* 16973f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16983f165b33SDarrick J. Wong * The right neighbor is contiguous, the left is not. 16993f165b33SDarrick J. Wong */ 17003f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 17013f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 17023f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 17033f165b33SDarrick J. Wong if (error) 17043f165b33SDarrick J. Wong goto done; 17053f165b33SDarrick J. Wong NEW = PREV; 17063f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17073f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17083f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17093f165b33SDarrick J. Wong if (error) 17103f165b33SDarrick J. Wong goto done; 1711f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1712f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1713f9e03706SDarrick J. Wong goto done; 1714f9e03706SDarrick J. Wong } 17153f165b33SDarrick J. Wong NEW.rm_blockcount += RIGHT.rm_blockcount; 17163f165b33SDarrick J. Wong NEW.rm_flags = RIGHT.rm_flags; 17173f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17183f165b33SDarrick J. Wong if (error) 17193f165b33SDarrick J. Wong goto done; 17203f165b33SDarrick J. Wong break; 17213f165b33SDarrick J. Wong 17223f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 17233f165b33SDarrick J. Wong /* 17243f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 17253f165b33SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 17263f165b33SDarrick J. Wong * the new one. 17273f165b33SDarrick J. Wong */ 17283f165b33SDarrick J. Wong NEW = PREV; 17293f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17303f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17313f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17323f165b33SDarrick J. Wong if (error) 17333f165b33SDarrick J. Wong goto done; 1734f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1735f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1736f9e03706SDarrick J. Wong goto done; 1737f9e03706SDarrick J. Wong } 17383f165b33SDarrick J. Wong NEW.rm_flags = newext; 17393f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17403f165b33SDarrick J. Wong if (error) 17413f165b33SDarrick J. Wong goto done; 17423f165b33SDarrick J. Wong break; 17433f165b33SDarrick J. Wong 17443f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 17453f165b33SDarrick J. Wong /* 17463f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 17473f165b33SDarrick J. Wong * The left neighbor is contiguous. 17483f165b33SDarrick J. Wong */ 17493f165b33SDarrick J. Wong NEW = PREV; 17503f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 17513f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17523f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17533f165b33SDarrick J. Wong if (error) 17543f165b33SDarrick J. Wong goto done; 17553f165b33SDarrick J. Wong NEW.rm_offset += len; 17563f165b33SDarrick J. Wong NEW.rm_startblock += len; 17573f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 17583f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 17593f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17603f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17613f165b33SDarrick J. Wong if (error) 17623f165b33SDarrick J. Wong goto done; 17633f165b33SDarrick J. Wong NEW = LEFT; 17643f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17653f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17663f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17673f165b33SDarrick J. Wong if (error) 17683f165b33SDarrick J. Wong goto done; 1769f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1770f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1771f9e03706SDarrick J. Wong goto done; 1772f9e03706SDarrick J. Wong } 17733f165b33SDarrick J. Wong NEW.rm_blockcount += len; 17743f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17753f165b33SDarrick J. Wong if (error) 17763f165b33SDarrick J. Wong goto done; 17773f165b33SDarrick J. Wong break; 17783f165b33SDarrick J. Wong 17793f165b33SDarrick J. Wong case RMAP_LEFT_FILLING: 17803f165b33SDarrick J. Wong /* 17813f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 17823f165b33SDarrick J. Wong * The left neighbor is not contiguous. 17833f165b33SDarrick J. Wong */ 17843f165b33SDarrick J. Wong NEW = PREV; 17853f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 17863f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17873f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17883f165b33SDarrick J. Wong if (error) 17893f165b33SDarrick J. Wong goto done; 17903f165b33SDarrick J. Wong NEW.rm_offset += len; 17913f165b33SDarrick J. Wong NEW.rm_startblock += len; 17923f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 17933f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 17943f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17953f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 17963f165b33SDarrick J. Wong if (error) 17973f165b33SDarrick J. Wong goto done; 17983f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 17993f165b33SDarrick J. Wong if (error) 18003f165b33SDarrick J. Wong goto done; 18013f165b33SDarrick J. Wong break; 18023f165b33SDarrick J. Wong 18033f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 18043f165b33SDarrick J. Wong /* 18053f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 18063f165b33SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 18073f165b33SDarrick J. Wong */ 18083f165b33SDarrick J. Wong NEW = PREV; 18093f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18103f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18113f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18123f165b33SDarrick J. Wong if (error) 18133f165b33SDarrick J. Wong goto done; 1814f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1815f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1816f9e03706SDarrick J. Wong goto done; 1817f9e03706SDarrick J. Wong } 18183f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 18193f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18203f165b33SDarrick J. Wong if (error) 18213f165b33SDarrick J. Wong goto done; 18223f165b33SDarrick J. Wong NEW = RIGHT; 18233f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 18243f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18253f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18263f165b33SDarrick J. Wong if (error) 18273f165b33SDarrick J. Wong goto done; 18283f165b33SDarrick J. Wong NEW.rm_offset = offset; 18293f165b33SDarrick J. Wong NEW.rm_startblock = bno; 18303f165b33SDarrick J. Wong NEW.rm_blockcount += len; 18313f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18323f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18333f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18343f165b33SDarrick J. Wong if (error) 18353f165b33SDarrick J. Wong goto done; 18363f165b33SDarrick J. Wong break; 18373f165b33SDarrick J. Wong 18383f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING: 18393f165b33SDarrick J. Wong /* 18403f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 18413f165b33SDarrick J. Wong * The right neighbor is not contiguous. 18423f165b33SDarrick J. Wong */ 18433f165b33SDarrick J. Wong NEW = PREV; 18443f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18453f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18463f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18473f165b33SDarrick J. Wong if (error) 18483f165b33SDarrick J. Wong goto done; 1849f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1850f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1851f9e03706SDarrick J. Wong goto done; 1852f9e03706SDarrick J. Wong } 18533f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 18543f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18553f165b33SDarrick J. Wong if (error) 18563f165b33SDarrick J. Wong goto done; 18573f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 18583f165b33SDarrick J. Wong if (error) 18593f165b33SDarrick J. Wong goto done; 18603f165b33SDarrick J. Wong break; 18613f165b33SDarrick J. Wong 18623f165b33SDarrick J. Wong case 0: 18633f165b33SDarrick J. Wong /* 18643f165b33SDarrick J. Wong * Setting the middle part of a previous oldext extent to 18653f165b33SDarrick J. Wong * newext. Contiguity is impossible here. 18663f165b33SDarrick J. Wong * One extent becomes three extents. 18673f165b33SDarrick J. Wong */ 18683f165b33SDarrick J. Wong /* new right extent - oldext */ 18693f165b33SDarrick J. Wong NEW.rm_startblock = bno + len; 18703f165b33SDarrick J. Wong NEW.rm_owner = owner; 18713f165b33SDarrick J. Wong NEW.rm_offset = new_endoff; 18723f165b33SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 18733f165b33SDarrick J. Wong new_endoff; 18743f165b33SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 18753f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18763f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 18773f165b33SDarrick J. Wong NEW.rm_flags); 18783f165b33SDarrick J. Wong if (error) 18793f165b33SDarrick J. Wong goto done; 18803f165b33SDarrick J. Wong /* new left extent - oldext */ 18813f165b33SDarrick J. Wong NEW = PREV; 18823f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18833f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18843f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18853f165b33SDarrick J. Wong if (error) 18863f165b33SDarrick J. Wong goto done; 1887f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1888f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1889f9e03706SDarrick J. Wong goto done; 1890f9e03706SDarrick J. Wong } 18913f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 18923f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18933f165b33SDarrick J. Wong if (error) 18943f165b33SDarrick J. Wong goto done; 18953f165b33SDarrick J. Wong /* new middle extent - newext */ 18963f165b33SDarrick J. Wong NEW.rm_startblock = bno; 18973f165b33SDarrick J. Wong NEW.rm_blockcount = len; 18983f165b33SDarrick J. Wong NEW.rm_owner = owner; 18993f165b33SDarrick J. Wong NEW.rm_offset = offset; 19003f165b33SDarrick J. Wong NEW.rm_flags = newext; 19013f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 19023f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 19033f165b33SDarrick J. Wong NEW.rm_flags); 19043f165b33SDarrick J. Wong if (error) 19053f165b33SDarrick J. Wong goto done; 19063f165b33SDarrick J. Wong break; 19073f165b33SDarrick J. Wong 19083f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 19093f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 19103f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 19113f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 19123f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 19133f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG: 19143f165b33SDarrick J. Wong case RMAP_RIGHT_CONTIG: 19153f165b33SDarrick J. Wong /* 19163f165b33SDarrick J. Wong * These cases are all impossible. 19173f165b33SDarrick J. Wong */ 19183f165b33SDarrick J. Wong ASSERT(0); 19193f165b33SDarrick J. Wong } 19203f165b33SDarrick J. Wong 192150f02fe3SDave Chinner trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 19223f165b33SDarrick J. Wong unwritten, oinfo); 19233f165b33SDarrick J. Wong done: 19243f165b33SDarrick J. Wong if (error) 19253f165b33SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 192650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 19273f165b33SDarrick J. Wong return error; 19283f165b33SDarrick J. Wong } 19293f165b33SDarrick J. Wong 1930fb7d9267SDarrick J. Wong #undef NEW 1931fb7d9267SDarrick J. Wong #undef LEFT 1932fb7d9267SDarrick J. Wong #undef RIGHT 1933fb7d9267SDarrick J. Wong #undef PREV 1934fb7d9267SDarrick J. Wong 1935ceeb9c83SDarrick J. Wong /* 1936ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and unmap it. For rmap extent types that 1937ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1938ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1939ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1940ceeb9c83SDarrick J. Wong * 1941ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1942ceeb9c83SDarrick J. Wong * so we can call the regular _free function. 1943ceeb9c83SDarrick J. Wong */ 1944ceeb9c83SDarrick J. Wong STATIC int 1945ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared( 1946ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1947ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1948ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1949ceeb9c83SDarrick J. Wong bool unwritten, 195066e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1951ceeb9c83SDarrick J. Wong { 1952ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1953ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 1954ceeb9c83SDarrick J. Wong uint64_t ltoff; 1955ceeb9c83SDarrick J. Wong int error = 0; 1956ceeb9c83SDarrick J. Wong int i; 1957ceeb9c83SDarrick J. Wong uint64_t owner; 1958ceeb9c83SDarrick J. Wong uint64_t offset; 1959ceeb9c83SDarrick J. Wong unsigned int flags; 1960ceeb9c83SDarrick J. Wong 1961ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1962ceeb9c83SDarrick J. Wong if (unwritten) 1963ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 196450f02fe3SDave Chinner trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len, 1965ceeb9c83SDarrick J. Wong unwritten, oinfo); 1966ceeb9c83SDarrick J. Wong 1967ceeb9c83SDarrick J. Wong /* 1968ceeb9c83SDarrick J. Wong * We should always have a left record because there's a static record 1969ceeb9c83SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 1970ceeb9c83SDarrick J. Wong * will not ever be removed from the tree. 1971ceeb9c83SDarrick J. Wong */ 1972ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 1973ceeb9c83SDarrick J. Wong <rec, &i); 1974ceeb9c83SDarrick J. Wong if (error) 1975ceeb9c83SDarrick J. Wong goto out_error; 1976f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1977f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1978f9e03706SDarrick J. Wong goto out_error; 1979f9e03706SDarrick J. Wong } 1980ceeb9c83SDarrick J. Wong ltoff = ltrec.rm_offset; 1981ceeb9c83SDarrick J. Wong 1982ceeb9c83SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 1983f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1984f9e03706SDarrick J. Wong ltrec.rm_startblock > bno || 1985f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount < 1986f9e03706SDarrick J. Wong bno + len)) { 1987f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1988f9e03706SDarrick J. Wong goto out_error; 1989f9e03706SDarrick J. Wong } 1990ceeb9c83SDarrick J. Wong 1991ceeb9c83SDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 1992f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) { 1993f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1994f9e03706SDarrick J. Wong goto out_error; 1995f9e03706SDarrick J. Wong } 1996ceeb9c83SDarrick J. Wong 1997ceeb9c83SDarrick J. Wong /* Make sure the unwritten flag matches. */ 1998f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1999f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) != 2000f9e03706SDarrick J. Wong (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) { 2001f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2002f9e03706SDarrick J. Wong goto out_error; 2003f9e03706SDarrick J. Wong } 2004ceeb9c83SDarrick J. Wong 2005ceeb9c83SDarrick J. Wong /* Check the offset. */ 2006f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) { 2007f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2008f9e03706SDarrick J. Wong goto out_error; 2009f9e03706SDarrick J. Wong } 2010f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) { 2011f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2012f9e03706SDarrick J. Wong goto out_error; 2013f9e03706SDarrick J. Wong } 2014ceeb9c83SDarrick J. Wong 2015ceeb9c83SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 2016ceeb9c83SDarrick J. Wong /* Exact match, simply remove the record from rmap tree. */ 2017ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 2018ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2019ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2020ceeb9c83SDarrick J. Wong if (error) 2021ceeb9c83SDarrick J. Wong goto out_error; 2022ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 2023ceeb9c83SDarrick J. Wong /* 2024ceeb9c83SDarrick J. Wong * Overlap left hand side of extent: move the start, trim the 2025ceeb9c83SDarrick J. Wong * length and update the current record. 2026ceeb9c83SDarrick J. Wong * 2027ceeb9c83SDarrick J. Wong * ltbno ltlen 2028ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2029ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2030ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 2031ceeb9c83SDarrick J. Wong * bno len 2032ceeb9c83SDarrick J. Wong */ 2033ceeb9c83SDarrick J. Wong 2034ceeb9c83SDarrick J. Wong /* Delete prev rmap. */ 2035ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 2036ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2037ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2038ceeb9c83SDarrick J. Wong if (error) 2039ceeb9c83SDarrick J. Wong goto out_error; 2040ceeb9c83SDarrick J. Wong 2041ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset. */ 2042ceeb9c83SDarrick J. Wong ltrec.rm_startblock += len; 2043ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 2044ceeb9c83SDarrick J. Wong ltrec.rm_offset += len; 2045ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, ltrec.rm_startblock, 2046ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2047ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2048ceeb9c83SDarrick J. Wong if (error) 2049ceeb9c83SDarrick J. Wong goto out_error; 2050ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 2051ceeb9c83SDarrick J. Wong /* 2052ceeb9c83SDarrick J. Wong * Overlap right hand side of extent: trim the length and 2053ceeb9c83SDarrick J. Wong * update the current record. 2054ceeb9c83SDarrick J. Wong * 2055ceeb9c83SDarrick J. Wong * ltbno ltlen 2056ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2057ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2058ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 2059ceeb9c83SDarrick J. Wong * bno len 2060ceeb9c83SDarrick J. Wong */ 2061ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2062ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2063ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2064ceeb9c83SDarrick J. Wong if (error) 2065ceeb9c83SDarrick J. Wong goto out_error; 2066f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2067f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2068f9e03706SDarrick J. Wong goto out_error; 2069f9e03706SDarrick J. Wong } 2070ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 2071ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2072ceeb9c83SDarrick J. Wong if (error) 2073ceeb9c83SDarrick J. Wong goto out_error; 2074ceeb9c83SDarrick J. Wong } else { 2075ceeb9c83SDarrick J. Wong /* 2076ceeb9c83SDarrick J. Wong * Overlap middle of extent: trim the length of the existing 2077ceeb9c83SDarrick J. Wong * record to the length of the new left-extent size, increment 2078ceeb9c83SDarrick J. Wong * the insertion position so we can insert a new record 2079ceeb9c83SDarrick J. Wong * containing the remaining right-extent space. 2080ceeb9c83SDarrick J. Wong * 2081ceeb9c83SDarrick J. Wong * ltbno ltlen 2082ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2083ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2084ceeb9c83SDarrick J. Wong * Result: |rrrrr| |rrrr| 2085ceeb9c83SDarrick J. Wong * bno len 2086ceeb9c83SDarrick J. Wong */ 2087ceeb9c83SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 2088ceeb9c83SDarrick J. Wong 2089ceeb9c83SDarrick J. Wong /* Shrink the left side of the rmap */ 2090ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2091ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2092ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2093ceeb9c83SDarrick J. Wong if (error) 2094ceeb9c83SDarrick J. Wong goto out_error; 2095f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2096f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2097f9e03706SDarrick J. Wong goto out_error; 2098f9e03706SDarrick J. Wong } 2099ceeb9c83SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 2100ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2101ceeb9c83SDarrick J. Wong if (error) 2102ceeb9c83SDarrick J. Wong goto out_error; 2103ceeb9c83SDarrick J. Wong 2104ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset */ 2105ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno + len, 2106ceeb9c83SDarrick J. Wong orig_len - len - ltrec.rm_blockcount, 2107ceeb9c83SDarrick J. Wong ltrec.rm_owner, offset + len, 2108ceeb9c83SDarrick J. Wong ltrec.rm_flags); 2109ceeb9c83SDarrick J. Wong if (error) 2110ceeb9c83SDarrick J. Wong goto out_error; 2111ceeb9c83SDarrick J. Wong } 2112ceeb9c83SDarrick J. Wong 211350f02fe3SDave Chinner trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 2114ceeb9c83SDarrick J. Wong unwritten, oinfo); 2115ceeb9c83SDarrick J. Wong out_error: 2116ceeb9c83SDarrick J. Wong if (error) 2117ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_error(cur->bc_mp, 211850f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 2119ceeb9c83SDarrick J. Wong return error; 2120ceeb9c83SDarrick J. Wong } 2121ceeb9c83SDarrick J. Wong 2122ceeb9c83SDarrick J. Wong /* 2123ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and map it. For rmap extent types that 2124ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 2125ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 2126ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 2127ceeb9c83SDarrick J. Wong * 2128ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 2129ceeb9c83SDarrick J. Wong * so we can call the regular _alloc function. 2130ceeb9c83SDarrick J. Wong */ 2131ceeb9c83SDarrick J. Wong STATIC int 2132ceeb9c83SDarrick J. Wong xfs_rmap_map_shared( 2133ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 2134ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 2135ceeb9c83SDarrick J. Wong xfs_extlen_t len, 2136ceeb9c83SDarrick J. Wong bool unwritten, 213766e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 2138ceeb9c83SDarrick J. Wong { 2139ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 2140ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 2141ceeb9c83SDarrick J. Wong struct xfs_rmap_irec gtrec; 2142ceeb9c83SDarrick J. Wong int have_gt; 2143ceeb9c83SDarrick J. Wong int have_lt; 2144ceeb9c83SDarrick J. Wong int error = 0; 2145ceeb9c83SDarrick J. Wong int i; 2146ceeb9c83SDarrick J. Wong uint64_t owner; 2147ceeb9c83SDarrick J. Wong uint64_t offset; 2148ceeb9c83SDarrick J. Wong unsigned int flags = 0; 2149ceeb9c83SDarrick J. Wong 2150ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2151ceeb9c83SDarrick J. Wong if (unwritten) 2152ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 215350f02fe3SDave Chinner trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len, 2154ceeb9c83SDarrick J. Wong unwritten, oinfo); 2155ceeb9c83SDarrick J. Wong 2156ceeb9c83SDarrick J. Wong /* Is there a left record that abuts our range? */ 2157ceeb9c83SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, 2158ceeb9c83SDarrick J. Wong <rec, &have_lt); 2159ceeb9c83SDarrick J. Wong if (error) 2160ceeb9c83SDarrick J. Wong goto out_error; 2161ceeb9c83SDarrick J. Wong if (have_lt && 2162ceeb9c83SDarrick J. Wong !xfs_rmap_is_mergeable(<rec, owner, flags)) 2163ceeb9c83SDarrick J. Wong have_lt = 0; 2164ceeb9c83SDarrick J. Wong 2165ceeb9c83SDarrick J. Wong /* Is there a right record that abuts our range? */ 2166ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 2167ceeb9c83SDarrick J. Wong flags, &have_gt); 2168ceeb9c83SDarrick J. Wong if (error) 2169ceeb9c83SDarrick J. Wong goto out_error; 2170ceeb9c83SDarrick J. Wong if (have_gt) { 2171ceeb9c83SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 2172ceeb9c83SDarrick J. Wong if (error) 2173ceeb9c83SDarrick J. Wong goto out_error; 2174f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) { 2175f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2176f9e03706SDarrick J. Wong goto out_error; 2177f9e03706SDarrick J. Wong } 2178ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 217950f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, gtrec.rm_startblock, 2180ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2181ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2182ceeb9c83SDarrick J. Wong 2183ceeb9c83SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 2184ceeb9c83SDarrick J. Wong have_gt = 0; 2185ceeb9c83SDarrick J. Wong } 2186ceeb9c83SDarrick J. Wong 2187ceeb9c83SDarrick J. Wong if (have_lt && 2188ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 2189ceeb9c83SDarrick J. Wong ltrec.rm_offset + ltrec.rm_blockcount == offset) { 2190ceeb9c83SDarrick J. Wong /* 2191ceeb9c83SDarrick J. Wong * Left edge contiguous, merge into left record. 2192ceeb9c83SDarrick J. Wong * 2193ceeb9c83SDarrick J. Wong * ltbno ltlen 2194ceeb9c83SDarrick J. Wong * orig: |ooooooooo| 2195ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2196ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 2197ceeb9c83SDarrick J. Wong * bno len 2198ceeb9c83SDarrick J. Wong */ 2199ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += len; 2200ceeb9c83SDarrick J. Wong if (have_gt && 2201ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 2202ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 2203ceeb9c83SDarrick J. Wong /* 2204ceeb9c83SDarrick J. Wong * Right edge also contiguous, delete right record 2205ceeb9c83SDarrick J. Wong * and merge into left record. 2206ceeb9c83SDarrick J. Wong * 2207ceeb9c83SDarrick J. Wong * ltbno ltlen gtbno gtlen 2208ceeb9c83SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 2209ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2210ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 2211ceeb9c83SDarrick J. Wong */ 2212ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 2213ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2214ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2215ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2216ceeb9c83SDarrick J. Wong if (error) 2217ceeb9c83SDarrick J. Wong goto out_error; 2218ceeb9c83SDarrick J. Wong } 2219ceeb9c83SDarrick J. Wong 2220ceeb9c83SDarrick J. Wong /* Point the cursor back to the left record and update. */ 2221ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2222ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2223ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2224ceeb9c83SDarrick J. Wong if (error) 2225ceeb9c83SDarrick J. Wong goto out_error; 2226f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2227f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2228f9e03706SDarrick J. Wong goto out_error; 2229f9e03706SDarrick J. Wong } 2230ceeb9c83SDarrick J. Wong 2231ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2232ceeb9c83SDarrick J. Wong if (error) 2233ceeb9c83SDarrick J. Wong goto out_error; 2234ceeb9c83SDarrick J. Wong } else if (have_gt && 2235ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 2236ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 2237ceeb9c83SDarrick J. Wong /* 2238ceeb9c83SDarrick J. Wong * Right edge contiguous, merge into right record. 2239ceeb9c83SDarrick J. Wong * 2240ceeb9c83SDarrick J. Wong * gtbno gtlen 2241ceeb9c83SDarrick J. Wong * Orig: |ooooooooo| 2242ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2243ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 2244ceeb9c83SDarrick J. Wong * bno len 2245ceeb9c83SDarrick J. Wong */ 2246ceeb9c83SDarrick J. Wong /* Delete the old record. */ 2247ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2248ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2249ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2250ceeb9c83SDarrick J. Wong if (error) 2251ceeb9c83SDarrick J. Wong goto out_error; 2252ceeb9c83SDarrick J. Wong 2253ceeb9c83SDarrick J. Wong /* Move the start and re-add it. */ 2254ceeb9c83SDarrick J. Wong gtrec.rm_startblock = bno; 2255ceeb9c83SDarrick J. Wong gtrec.rm_blockcount += len; 2256ceeb9c83SDarrick J. Wong gtrec.rm_offset = offset; 2257ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, gtrec.rm_startblock, 2258ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2259ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2260ceeb9c83SDarrick J. Wong if (error) 2261ceeb9c83SDarrick J. Wong goto out_error; 2262ceeb9c83SDarrick J. Wong } else { 2263ceeb9c83SDarrick J. Wong /* 2264ceeb9c83SDarrick J. Wong * No contiguous edge with identical owner, insert 2265ceeb9c83SDarrick J. Wong * new record at current cursor position. 2266ceeb9c83SDarrick J. Wong */ 2267ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); 2268ceeb9c83SDarrick J. Wong if (error) 2269ceeb9c83SDarrick J. Wong goto out_error; 2270ceeb9c83SDarrick J. Wong } 2271ceeb9c83SDarrick J. Wong 227250f02fe3SDave Chinner trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 2273ceeb9c83SDarrick J. Wong unwritten, oinfo); 2274ceeb9c83SDarrick J. Wong out_error: 2275ceeb9c83SDarrick J. Wong if (error) 2276ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_error(cur->bc_mp, 227750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 2278ceeb9c83SDarrick J. Wong return error; 2279ceeb9c83SDarrick J. Wong } 2280ceeb9c83SDarrick J. Wong 22814d4f86b4SDarrick J. Wong /* Insert a raw rmap into the rmapbt. */ 22824d4f86b4SDarrick J. Wong int 22834d4f86b4SDarrick J. Wong xfs_rmap_map_raw( 22844d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 22854d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rmap) 22864d4f86b4SDarrick J. Wong { 22874d4f86b4SDarrick J. Wong struct xfs_owner_info oinfo; 22884d4f86b4SDarrick J. Wong 22894d4f86b4SDarrick J. Wong oinfo.oi_owner = rmap->rm_owner; 22904d4f86b4SDarrick J. Wong oinfo.oi_offset = rmap->rm_offset; 22914d4f86b4SDarrick J. Wong oinfo.oi_flags = 0; 22924d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_ATTR_FORK) 22934d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK; 22944d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK) 22954d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; 22964d4f86b4SDarrick J. Wong 22974d4f86b4SDarrick J. Wong if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner)) 22984d4f86b4SDarrick J. Wong return xfs_rmap_map(cur, rmap->rm_startblock, 22994d4f86b4SDarrick J. Wong rmap->rm_blockcount, 23004d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 23014d4f86b4SDarrick J. Wong &oinfo); 23024d4f86b4SDarrick J. Wong 23034d4f86b4SDarrick J. Wong return xfs_rmap_map_shared(cur, rmap->rm_startblock, 23044d4f86b4SDarrick J. Wong rmap->rm_blockcount, 23054d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 23064d4f86b4SDarrick J. Wong &oinfo); 23074d4f86b4SDarrick J. Wong } 23084d4f86b4SDarrick J. Wong 2309c543838aSDarrick J. Wong struct xfs_rmap_query_range_info { 2310c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn; 2311c543838aSDarrick J. Wong void *priv; 2312c543838aSDarrick J. Wong }; 2313c543838aSDarrick J. Wong 2314c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */ 2315c543838aSDarrick J. Wong STATIC int 2316c543838aSDarrick J. Wong xfs_rmap_query_range_helper( 2317c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2318159eb69dSDarrick J. Wong const union xfs_btree_rec *rec, 2319c543838aSDarrick J. Wong void *priv) 2320c543838aSDarrick J. Wong { 2321c543838aSDarrick J. Wong struct xfs_rmap_query_range_info *query = priv; 2322c543838aSDarrick J. Wong struct xfs_rmap_irec irec; 2323c543838aSDarrick J. Wong int error; 2324c543838aSDarrick J. Wong 2325c543838aSDarrick J. Wong error = xfs_rmap_btrec_to_irec(rec, &irec); 2326c543838aSDarrick J. Wong if (error) 2327c543838aSDarrick J. Wong return error; 2328c543838aSDarrick J. Wong return query->fn(cur, &irec, query->priv); 2329c543838aSDarrick J. Wong } 2330c543838aSDarrick J. Wong 2331c543838aSDarrick J. Wong /* Find all rmaps between two keys. */ 2332c543838aSDarrick J. Wong int 2333c543838aSDarrick J. Wong xfs_rmap_query_range( 2334c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 233504dcb474SDarrick J. Wong const struct xfs_rmap_irec *low_rec, 233604dcb474SDarrick J. Wong const struct xfs_rmap_irec *high_rec, 2337c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2338c543838aSDarrick J. Wong void *priv) 2339c543838aSDarrick J. Wong { 2340c543838aSDarrick J. Wong union xfs_btree_irec low_brec; 2341c543838aSDarrick J. Wong union xfs_btree_irec high_brec; 2342c543838aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2343c543838aSDarrick J. Wong 2344c543838aSDarrick J. Wong low_brec.r = *low_rec; 2345c543838aSDarrick J. Wong high_brec.r = *high_rec; 2346c543838aSDarrick J. Wong query.priv = priv; 2347c543838aSDarrick J. Wong query.fn = fn; 2348c543838aSDarrick J. Wong return xfs_btree_query_range(cur, &low_brec, &high_brec, 2349c543838aSDarrick J. Wong xfs_rmap_query_range_helper, &query); 2350e9a2599aSDarrick J. Wong } 2351e9a2599aSDarrick J. Wong 2352e9a2599aSDarrick J. Wong /* Find all rmaps. */ 2353e9a2599aSDarrick J. Wong int 2354e9a2599aSDarrick J. Wong xfs_rmap_query_all( 2355e9a2599aSDarrick J. Wong struct xfs_btree_cur *cur, 2356e9a2599aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2357e9a2599aSDarrick J. Wong void *priv) 2358e9a2599aSDarrick J. Wong { 2359e9a2599aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2360e9a2599aSDarrick J. Wong 2361e9a2599aSDarrick J. Wong query.priv = priv; 2362e9a2599aSDarrick J. Wong query.fn = fn; 2363e9a2599aSDarrick J. Wong return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query); 2364c543838aSDarrick J. Wong } 23659c194644SDarrick J. Wong 23669c194644SDarrick J. Wong /* Clean up after calling xfs_rmap_finish_one. */ 23679c194644SDarrick J. Wong void 23689c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup( 23699c194644SDarrick J. Wong struct xfs_trans *tp, 23709c194644SDarrick J. Wong struct xfs_btree_cur *rcur, 23719c194644SDarrick J. Wong int error) 23729c194644SDarrick J. Wong { 23739c194644SDarrick J. Wong struct xfs_buf *agbp; 23749c194644SDarrick J. Wong 23759c194644SDarrick J. Wong if (rcur == NULL) 23769c194644SDarrick J. Wong return; 2377576af732SDave Chinner agbp = rcur->bc_ag.agbp; 23780b04b6b8SDarrick J. Wong xfs_btree_del_cursor(rcur, error); 23799c194644SDarrick J. Wong if (error) 23809c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 23819c194644SDarrick J. Wong } 23829c194644SDarrick J. Wong 23839c194644SDarrick J. Wong /* 23849c194644SDarrick J. Wong * Process one of the deferred rmap operations. We pass back the 23859c194644SDarrick J. Wong * btree cursor to maintain our lock on the rmapbt between calls. 23869c194644SDarrick J. Wong * This saves time and eliminates a buffer deadlock between the 23879c194644SDarrick J. Wong * superblock and the AGF because we'll always grab them in the same 23889c194644SDarrick J. Wong * order. 23899c194644SDarrick J. Wong */ 23909c194644SDarrick J. Wong int 23919c194644SDarrick J. Wong xfs_rmap_finish_one( 23929c194644SDarrick J. Wong struct xfs_trans *tp, 2393*1534328bSDarrick J. Wong struct xfs_rmap_intent *ri, 23949c194644SDarrick J. Wong struct xfs_btree_cur **pcur) 23959c194644SDarrick J. Wong { 23969c194644SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 239745d06621SDave Chinner struct xfs_perag *pag; 23989c194644SDarrick J. Wong struct xfs_btree_cur *rcur; 23999c194644SDarrick J. Wong struct xfs_buf *agbp = NULL; 24009c194644SDarrick J. Wong int error = 0; 24019c194644SDarrick J. Wong struct xfs_owner_info oinfo; 24029c194644SDarrick J. Wong xfs_agblock_t bno; 24039c194644SDarrick J. Wong bool unwritten; 24049c194644SDarrick J. Wong 2405*1534328bSDarrick J. Wong pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock)); 2406*1534328bSDarrick J. Wong bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock); 24079c194644SDarrick J. Wong 2408*1534328bSDarrick J. Wong trace_xfs_rmap_deferred(mp, pag->pag_agno, ri->ri_type, bno, 2409*1534328bSDarrick J. Wong ri->ri_owner, ri->ri_whichfork, 2410*1534328bSDarrick J. Wong ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount, 2411*1534328bSDarrick J. Wong ri->ri_bmap.br_state); 24129c194644SDarrick J. Wong 241345d06621SDave Chinner if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) { 241445d06621SDave Chinner error = -EIO; 241545d06621SDave Chinner goto out_drop; 241645d06621SDave Chinner } 241745d06621SDave Chinner 24189c194644SDarrick J. Wong 24199c194644SDarrick J. Wong /* 24209c194644SDarrick J. Wong * If we haven't gotten a cursor or the cursor AG doesn't match 24219c194644SDarrick J. Wong * the startblock, get one now. 24229c194644SDarrick J. Wong */ 24239c194644SDarrick J. Wong rcur = *pcur; 242450f02fe3SDave Chinner if (rcur != NULL && rcur->bc_ag.pag != pag) { 24259c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup(tp, rcur, 0); 24269c194644SDarrick J. Wong rcur = NULL; 24279c194644SDarrick J. Wong *pcur = NULL; 24289c194644SDarrick J. Wong } 24299c194644SDarrick J. Wong if (rcur == NULL) { 24309c194644SDarrick J. Wong /* 24319c194644SDarrick J. Wong * Refresh the freelist before we start changing the 24329c194644SDarrick J. Wong * rmapbt, because a shape change could cause us to 24339c194644SDarrick J. Wong * allocate blocks. 24349c194644SDarrick J. Wong */ 243545d06621SDave Chinner error = xfs_free_extent_fix_freelist(tp, pag, &agbp); 24369c194644SDarrick J. Wong if (error) 243745d06621SDave Chinner goto out_drop; 243845d06621SDave Chinner if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) { 243945d06621SDave Chinner error = -EFSCORRUPTED; 244045d06621SDave Chinner goto out_drop; 244145d06621SDave Chinner } 24429c194644SDarrick J. Wong 2443fa9c3c19SDave Chinner rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); 24449c194644SDarrick J. Wong } 24459c194644SDarrick J. Wong *pcur = rcur; 24469c194644SDarrick J. Wong 2447*1534328bSDarrick J. Wong xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork, 2448*1534328bSDarrick J. Wong ri->ri_bmap.br_startoff); 2449*1534328bSDarrick J. Wong unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN; 2450*1534328bSDarrick J. Wong bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock); 24519c194644SDarrick J. Wong 2452*1534328bSDarrick J. Wong switch (ri->ri_type) { 24539c194644SDarrick J. Wong case XFS_RMAP_ALLOC: 24549c194644SDarrick J. Wong case XFS_RMAP_MAP: 2455*1534328bSDarrick J. Wong error = xfs_rmap_map(rcur, bno, ri->ri_bmap.br_blockcount, 2456*1534328bSDarrick J. Wong unwritten, &oinfo); 24579c194644SDarrick J. Wong break; 2458ceeb9c83SDarrick J. Wong case XFS_RMAP_MAP_SHARED: 2459*1534328bSDarrick J. Wong error = xfs_rmap_map_shared(rcur, bno, 2460*1534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, unwritten, &oinfo); 2461ceeb9c83SDarrick J. Wong break; 24629c194644SDarrick J. Wong case XFS_RMAP_FREE: 24639c194644SDarrick J. Wong case XFS_RMAP_UNMAP: 2464*1534328bSDarrick J. Wong error = xfs_rmap_unmap(rcur, bno, ri->ri_bmap.br_blockcount, 2465*1534328bSDarrick J. Wong unwritten, &oinfo); 24669c194644SDarrick J. Wong break; 2467ceeb9c83SDarrick J. Wong case XFS_RMAP_UNMAP_SHARED: 2468*1534328bSDarrick J. Wong error = xfs_rmap_unmap_shared(rcur, bno, 2469*1534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, unwritten, &oinfo); 2470ceeb9c83SDarrick J. Wong break; 24719c194644SDarrick J. Wong case XFS_RMAP_CONVERT: 2472*1534328bSDarrick J. Wong error = xfs_rmap_convert(rcur, bno, ri->ri_bmap.br_blockcount, 2473*1534328bSDarrick J. Wong !unwritten, &oinfo); 24749c194644SDarrick J. Wong break; 24753f165b33SDarrick J. Wong case XFS_RMAP_CONVERT_SHARED: 2476*1534328bSDarrick J. Wong error = xfs_rmap_convert_shared(rcur, bno, 2477*1534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, !unwritten, &oinfo); 24783f165b33SDarrick J. Wong break; 24799c194644SDarrick J. Wong default: 24809c194644SDarrick J. Wong ASSERT(0); 24819c194644SDarrick J. Wong error = -EFSCORRUPTED; 24829c194644SDarrick J. Wong } 248345d06621SDave Chinner out_drop: 248445d06621SDave Chinner xfs_perag_put(pag); 24859c194644SDarrick J. Wong return error; 24869c194644SDarrick J. Wong } 24879c194644SDarrick J. Wong 24889c194644SDarrick J. Wong /* 24899c194644SDarrick J. Wong * Don't defer an rmap if we aren't an rmap filesystem. 24909c194644SDarrick J. Wong */ 24919c194644SDarrick J. Wong static bool 24929c194644SDarrick J. Wong xfs_rmap_update_is_needed( 24933993baebSDarrick J. Wong struct xfs_mount *mp, 24943993baebSDarrick J. Wong int whichfork) 24959c194644SDarrick J. Wong { 249638c26bfdSDave Chinner return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK; 24979c194644SDarrick J. Wong } 24989c194644SDarrick J. Wong 24999c194644SDarrick J. Wong /* 25009c194644SDarrick J. Wong * Record a rmap intent; the list is kept sorted first by AG and then by 25019c194644SDarrick J. Wong * increasing age. 25029c194644SDarrick J. Wong */ 2503bc46ac64SDarrick J. Wong static void 25049c194644SDarrick J. Wong __xfs_rmap_add( 25050f37d178SBrian Foster struct xfs_trans *tp, 25069c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2507c8ce540dSDarrick J. Wong uint64_t owner, 25089c194644SDarrick J. Wong int whichfork, 25099c194644SDarrick J. Wong struct xfs_bmbt_irec *bmap) 25109c194644SDarrick J. Wong { 25119c194644SDarrick J. Wong struct xfs_rmap_intent *ri; 25129c194644SDarrick J. Wong 25130f37d178SBrian Foster trace_xfs_rmap_defer(tp->t_mountp, 25140f37d178SBrian Foster XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock), 25159c194644SDarrick J. Wong type, 25160f37d178SBrian Foster XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock), 25179c194644SDarrick J. Wong owner, whichfork, 25189c194644SDarrick J. Wong bmap->br_startoff, 25199c194644SDarrick J. Wong bmap->br_blockcount, 25209c194644SDarrick J. Wong bmap->br_state); 25219c194644SDarrick J. Wong 2522f3c799c2SDarrick J. Wong ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL); 25239c194644SDarrick J. Wong INIT_LIST_HEAD(&ri->ri_list); 25249c194644SDarrick J. Wong ri->ri_type = type; 25259c194644SDarrick J. Wong ri->ri_owner = owner; 25269c194644SDarrick J. Wong ri->ri_whichfork = whichfork; 25279c194644SDarrick J. Wong ri->ri_bmap = *bmap; 25289c194644SDarrick J. Wong 25290f37d178SBrian Foster xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); 25309c194644SDarrick J. Wong } 25319c194644SDarrick J. Wong 25329c194644SDarrick J. Wong /* Map an extent into a file. */ 2533bc46ac64SDarrick J. Wong void 25349c194644SDarrick J. Wong xfs_rmap_map_extent( 25350f37d178SBrian Foster struct xfs_trans *tp, 25369c194644SDarrick J. Wong struct xfs_inode *ip, 25379c194644SDarrick J. Wong int whichfork, 25389c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25399c194644SDarrick J. Wong { 2540d7884e6eSDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_MAP; 2541d7884e6eSDarrick J. Wong 25420f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2543bc46ac64SDarrick J. Wong return; 25449c194644SDarrick J. Wong 2545d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip)) 2546d7884e6eSDarrick J. Wong type = XFS_RMAP_MAP_SHARED; 2547d7884e6eSDarrick J. Wong 2548d7884e6eSDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV); 25499c194644SDarrick J. Wong } 25509c194644SDarrick J. Wong 25519c194644SDarrick J. Wong /* Unmap an extent out of a file. */ 2552bc46ac64SDarrick J. Wong void 25539c194644SDarrick J. Wong xfs_rmap_unmap_extent( 25540f37d178SBrian Foster struct xfs_trans *tp, 25559c194644SDarrick J. Wong struct xfs_inode *ip, 25569c194644SDarrick J. Wong int whichfork, 25579c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25589c194644SDarrick J. Wong { 2559d7884e6eSDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP; 2560d7884e6eSDarrick J. Wong 25610f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2562bc46ac64SDarrick J. Wong return; 25639c194644SDarrick J. Wong 2564d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip)) 2565d7884e6eSDarrick J. Wong type = XFS_RMAP_UNMAP_SHARED; 2566d7884e6eSDarrick J. Wong 2567d7884e6eSDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV); 25689c194644SDarrick J. Wong } 25699c194644SDarrick J. Wong 25700f37d178SBrian Foster /* 25710f37d178SBrian Foster * Convert a data fork extent from unwritten to real or vice versa. 25720f37d178SBrian Foster * 25730f37d178SBrian Foster * Note that tp can be NULL here as no transaction is used for COW fork 25740f37d178SBrian Foster * unwritten conversion. 25750f37d178SBrian Foster */ 2576bc46ac64SDarrick J. Wong void 25779c194644SDarrick J. Wong xfs_rmap_convert_extent( 25789c194644SDarrick J. Wong struct xfs_mount *mp, 25790f37d178SBrian Foster struct xfs_trans *tp, 25809c194644SDarrick J. Wong struct xfs_inode *ip, 25819c194644SDarrick J. Wong int whichfork, 25829c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25839c194644SDarrick J. Wong { 2584d7884e6eSDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT; 2585d7884e6eSDarrick J. Wong 25863993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 2587bc46ac64SDarrick J. Wong return; 25889c194644SDarrick J. Wong 2589d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip)) 2590d7884e6eSDarrick J. Wong type = XFS_RMAP_CONVERT_SHARED; 2591d7884e6eSDarrick J. Wong 2592d7884e6eSDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV); 25939c194644SDarrick J. Wong } 25949c194644SDarrick J. Wong 25959c194644SDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */ 2596bc46ac64SDarrick J. Wong void 25979c194644SDarrick J. Wong xfs_rmap_alloc_extent( 25980f37d178SBrian Foster struct xfs_trans *tp, 25999c194644SDarrick J. Wong xfs_agnumber_t agno, 26009c194644SDarrick J. Wong xfs_agblock_t bno, 26019c194644SDarrick J. Wong xfs_extlen_t len, 2602c8ce540dSDarrick J. Wong uint64_t owner) 26039c194644SDarrick J. Wong { 26049c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 26059c194644SDarrick J. Wong 26060f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2607bc46ac64SDarrick J. Wong return; 26089c194644SDarrick J. Wong 26090f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 26109c194644SDarrick J. Wong bmap.br_blockcount = len; 26119c194644SDarrick J. Wong bmap.br_startoff = 0; 26129c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 26139c194644SDarrick J. Wong 2614bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap); 26159c194644SDarrick J. Wong } 26169c194644SDarrick J. Wong 26179c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */ 2618bc46ac64SDarrick J. Wong void 26199c194644SDarrick J. Wong xfs_rmap_free_extent( 26200f37d178SBrian Foster struct xfs_trans *tp, 26219c194644SDarrick J. Wong xfs_agnumber_t agno, 26229c194644SDarrick J. Wong xfs_agblock_t bno, 26239c194644SDarrick J. Wong xfs_extlen_t len, 2624c8ce540dSDarrick J. Wong uint64_t owner) 26259c194644SDarrick J. Wong { 26269c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 26279c194644SDarrick J. Wong 26280f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2629bc46ac64SDarrick J. Wong return; 26309c194644SDarrick J. Wong 26310f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 26329c194644SDarrick J. Wong bmap.br_blockcount = len; 26339c194644SDarrick J. Wong bmap.br_startoff = 0; 26349c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 26359c194644SDarrick J. Wong 2636bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap); 26379c194644SDarrick J. Wong } 2638e89c0413SDarrick J. Wong 2639e89c0413SDarrick J. Wong /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ 2640e89c0413SDarrick J. Wong int 2641e89c0413SDarrick J. Wong xfs_rmap_compare( 2642e89c0413SDarrick J. Wong const struct xfs_rmap_irec *a, 2643e89c0413SDarrick J. Wong const struct xfs_rmap_irec *b) 2644e89c0413SDarrick J. Wong { 2645e89c0413SDarrick J. Wong __u64 oa; 2646e89c0413SDarrick J. Wong __u64 ob; 2647e89c0413SDarrick J. Wong 2648e89c0413SDarrick J. Wong oa = xfs_rmap_irec_offset_pack(a); 2649e89c0413SDarrick J. Wong ob = xfs_rmap_irec_offset_pack(b); 2650e89c0413SDarrick J. Wong 2651e89c0413SDarrick J. Wong if (a->rm_startblock < b->rm_startblock) 2652e89c0413SDarrick J. Wong return -1; 2653e89c0413SDarrick J. Wong else if (a->rm_startblock > b->rm_startblock) 2654e89c0413SDarrick J. Wong return 1; 2655e89c0413SDarrick J. Wong else if (a->rm_owner < b->rm_owner) 2656e89c0413SDarrick J. Wong return -1; 2657e89c0413SDarrick J. Wong else if (a->rm_owner > b->rm_owner) 2658e89c0413SDarrick J. Wong return 1; 2659e89c0413SDarrick J. Wong else if (oa < ob) 2660e89c0413SDarrick J. Wong return -1; 2661e89c0413SDarrick J. Wong else if (oa > ob) 2662e89c0413SDarrick J. Wong return 1; 2663e89c0413SDarrick J. Wong else 2664e89c0413SDarrick J. Wong return 0; 2665e89c0413SDarrick J. Wong } 2666ed7c52d4SDarrick J. Wong 2667ed7c52d4SDarrick J. Wong /* Is there a record covering a given extent? */ 2668ed7c52d4SDarrick J. Wong int 2669ed7c52d4SDarrick J. Wong xfs_rmap_has_record( 2670ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2671ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2672ed7c52d4SDarrick J. Wong xfs_extlen_t len, 2673ed7c52d4SDarrick J. Wong bool *exists) 2674ed7c52d4SDarrick J. Wong { 2675ed7c52d4SDarrick J. Wong union xfs_btree_irec low; 2676ed7c52d4SDarrick J. Wong union xfs_btree_irec high; 2677ed7c52d4SDarrick J. Wong 2678ed7c52d4SDarrick J. Wong memset(&low, 0, sizeof(low)); 2679ed7c52d4SDarrick J. Wong low.r.rm_startblock = bno; 2680ed7c52d4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 2681ed7c52d4SDarrick J. Wong high.r.rm_startblock = bno + len - 1; 2682ed7c52d4SDarrick J. Wong 2683ed7c52d4SDarrick J. Wong return xfs_btree_has_record(cur, &low, &high, exists); 2684ed7c52d4SDarrick J. Wong } 2685ed7c52d4SDarrick J. Wong 2686ed7c52d4SDarrick J. Wong /* 2687ed7c52d4SDarrick J. Wong * Is there a record for this owner completely covering a given physical 2688ed7c52d4SDarrick J. Wong * extent? If so, *has_rmap will be set to true. If there is no record 2689ed7c52d4SDarrick J. Wong * or the record only covers part of the range, we set *has_rmap to false. 2690ed7c52d4SDarrick J. Wong * This function doesn't perform range lookups or offset checks, so it is 2691ed7c52d4SDarrick J. Wong * not suitable for checking data fork blocks. 2692ed7c52d4SDarrick J. Wong */ 2693ed7c52d4SDarrick J. Wong int 2694ed7c52d4SDarrick J. Wong xfs_rmap_record_exists( 2695ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2696ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2697ed7c52d4SDarrick J. Wong xfs_extlen_t len, 269866e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 2699ed7c52d4SDarrick J. Wong bool *has_rmap) 2700ed7c52d4SDarrick J. Wong { 2701ed7c52d4SDarrick J. Wong uint64_t owner; 2702ed7c52d4SDarrick J. Wong uint64_t offset; 2703ed7c52d4SDarrick J. Wong unsigned int flags; 2704ed7c52d4SDarrick J. Wong int has_record; 2705ed7c52d4SDarrick J. Wong struct xfs_rmap_irec irec; 2706ed7c52d4SDarrick J. Wong int error; 2707ed7c52d4SDarrick J. Wong 2708ed7c52d4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2709ed7c52d4SDarrick J. Wong ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || 2710ed7c52d4SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK)); 2711ed7c52d4SDarrick J. Wong 27125b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &irec, 2713ed7c52d4SDarrick J. Wong &has_record); 2714ed7c52d4SDarrick J. Wong if (error) 2715ed7c52d4SDarrick J. Wong return error; 2716ed7c52d4SDarrick J. Wong if (!has_record) { 2717ed7c52d4SDarrick J. Wong *has_rmap = false; 2718ed7c52d4SDarrick J. Wong return 0; 2719ed7c52d4SDarrick J. Wong } 2720ed7c52d4SDarrick J. Wong 2721ed7c52d4SDarrick J. Wong *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno && 2722ed7c52d4SDarrick J. Wong irec.rm_startblock + irec.rm_blockcount >= bno + len); 2723ed7c52d4SDarrick J. Wong return 0; 2724ed7c52d4SDarrick J. Wong } 27254d4f86b4SDarrick J. Wong 27264d4f86b4SDarrick J. Wong struct xfs_rmap_key_state { 27274d4f86b4SDarrick J. Wong uint64_t owner; 27284d4f86b4SDarrick J. Wong uint64_t offset; 27294d4f86b4SDarrick J. Wong unsigned int flags; 27304d4f86b4SDarrick J. Wong }; 27314d4f86b4SDarrick J. Wong 27324d4f86b4SDarrick J. Wong /* For each rmap given, figure out if it doesn't match the key we want. */ 27334d4f86b4SDarrick J. Wong STATIC int 27344d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper( 27354d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 2736159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec, 27374d4f86b4SDarrick J. Wong void *priv) 27384d4f86b4SDarrick J. Wong { 27394d4f86b4SDarrick J. Wong struct xfs_rmap_key_state *rks = priv; 27404d4f86b4SDarrick J. Wong 27414d4f86b4SDarrick J. Wong if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset && 27424d4f86b4SDarrick J. Wong ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags) 27434d4f86b4SDarrick J. Wong return 0; 2744e7ee96dfSDarrick J. Wong return -ECANCELED; 27454d4f86b4SDarrick J. Wong } 27464d4f86b4SDarrick J. Wong 27474d4f86b4SDarrick J. Wong /* 27484d4f86b4SDarrick J. Wong * Given an extent and some owner info, can we find records overlapping 27494d4f86b4SDarrick J. Wong * the extent whose owner info does not match the given owner? 27504d4f86b4SDarrick J. Wong */ 27514d4f86b4SDarrick J. Wong int 27524d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys( 27534d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 27544d4f86b4SDarrick J. Wong xfs_agblock_t bno, 27554d4f86b4SDarrick J. Wong xfs_extlen_t len, 275666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 27574d4f86b4SDarrick J. Wong bool *has_rmap) 27584d4f86b4SDarrick J. Wong { 27594d4f86b4SDarrick J. Wong struct xfs_rmap_irec low = {0}; 27604d4f86b4SDarrick J. Wong struct xfs_rmap_irec high; 27614d4f86b4SDarrick J. Wong struct xfs_rmap_key_state rks; 27624d4f86b4SDarrick J. Wong int error; 27634d4f86b4SDarrick J. Wong 27644d4f86b4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags); 2765a71e4228SDarrick J. Wong *has_rmap = false; 27664d4f86b4SDarrick J. Wong 27674d4f86b4SDarrick J. Wong low.rm_startblock = bno; 27684d4f86b4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 27694d4f86b4SDarrick J. Wong high.rm_startblock = bno + len - 1; 27704d4f86b4SDarrick J. Wong 27714d4f86b4SDarrick J. Wong error = xfs_rmap_query_range(cur, &low, &high, 27724d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper, &rks); 2773a71e4228SDarrick J. Wong if (error == -ECANCELED) { 2774a71e4228SDarrick J. Wong *has_rmap = true; 27757380e8feSDarrick J. Wong return 0; 27764d4f86b4SDarrick J. Wong } 27777280fedaSDarrick J. Wong 2778a71e4228SDarrick J. Wong return error; 2779a71e4228SDarrick J. Wong } 2780a71e4228SDarrick J. Wong 27817280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = { 27827280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_NULL, 27837280fedaSDarrick J. Wong }; 27847280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = { 27857280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_UNKNOWN, 27867280fedaSDarrick J. Wong }; 27877280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_FS = { 27887280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_FS, 27897280fedaSDarrick J. Wong }; 27907280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_LOG = { 27917280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_LOG, 27927280fedaSDarrick J. Wong }; 27937280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_AG = { 27947280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_AG, 27957280fedaSDarrick J. Wong }; 27967280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = { 27977280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INOBT, 27987280fedaSDarrick J. Wong }; 27997280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INODES = { 28007280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INODES, 28017280fedaSDarrick J. Wong }; 28027280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_REFC = { 28037280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_REFC, 28047280fedaSDarrick J. Wong }; 28057280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_COW = { 28067280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_COW, 28077280fedaSDarrick J. Wong }; 2808f3c799c2SDarrick J. Wong 2809f3c799c2SDarrick J. Wong int __init 2810f3c799c2SDarrick J. Wong xfs_rmap_intent_init_cache(void) 2811f3c799c2SDarrick J. Wong { 2812f3c799c2SDarrick J. Wong xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent", 2813f3c799c2SDarrick J. Wong sizeof(struct xfs_rmap_intent), 2814f3c799c2SDarrick J. Wong 0, 0, NULL); 2815f3c799c2SDarrick J. Wong 2816f3c799c2SDarrick J. Wong return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM; 2817f3c799c2SDarrick J. Wong } 2818f3c799c2SDarrick J. Wong 2819f3c799c2SDarrick J. Wong void 2820f3c799c2SDarrick J. Wong xfs_rmap_intent_destroy_cache(void) 2821f3c799c2SDarrick J. Wong { 2822f3c799c2SDarrick J. Wong kmem_cache_destroy(xfs_rmap_intent_cache); 2823f3c799c2SDarrick J. Wong xfs_rmap_intent_cache = NULL; 2824f3c799c2SDarrick J. Wong } 2825