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. */ 19639ab26d5SDarrick J. Wong xfs_failaddr_t 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 208c4e34172SDarrick J. Wong /* Simple checks for rmap records. */ 209c4e34172SDarrick J. Wong xfs_failaddr_t 210c4e34172SDarrick J. Wong xfs_rmap_check_irec( 211c4e34172SDarrick J. Wong struct xfs_btree_cur *cur, 212c4e34172SDarrick J. Wong const struct xfs_rmap_irec *irec) 213c4e34172SDarrick J. Wong { 214c4e34172SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 2157d7d6d2fSDarrick J. Wong bool is_inode; 2167d7d6d2fSDarrick J. Wong bool is_unwritten; 2177d7d6d2fSDarrick J. Wong bool is_bmbt; 2187d7d6d2fSDarrick J. Wong bool is_attr; 219c4e34172SDarrick J. Wong 220c4e34172SDarrick J. Wong if (irec->rm_blockcount == 0) 221c4e34172SDarrick J. Wong return __this_address; 222c4e34172SDarrick J. Wong if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) { 223c4e34172SDarrick J. Wong if (irec->rm_owner != XFS_RMAP_OWN_FS) 224c4e34172SDarrick J. Wong return __this_address; 225c4e34172SDarrick J. Wong if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1) 226c4e34172SDarrick J. Wong return __this_address; 227c4e34172SDarrick J. Wong } else { 228c4e34172SDarrick J. Wong /* check for valid extent range, including overflow */ 229c4e34172SDarrick J. Wong if (!xfs_verify_agbext(cur->bc_ag.pag, irec->rm_startblock, 230c4e34172SDarrick J. Wong irec->rm_blockcount)) 231c4e34172SDarrick J. Wong return __this_address; 232c4e34172SDarrick J. Wong } 233c4e34172SDarrick J. Wong 234c4e34172SDarrick J. Wong if (!(xfs_verify_ino(mp, irec->rm_owner) || 235c4e34172SDarrick J. Wong (irec->rm_owner <= XFS_RMAP_OWN_FS && 236c4e34172SDarrick J. Wong irec->rm_owner >= XFS_RMAP_OWN_MIN))) 237c4e34172SDarrick J. Wong return __this_address; 238c4e34172SDarrick J. Wong 2397d7d6d2fSDarrick J. Wong /* Check flags. */ 2407d7d6d2fSDarrick J. Wong is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner); 2417d7d6d2fSDarrick J. Wong is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK; 2427d7d6d2fSDarrick J. Wong is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK; 2437d7d6d2fSDarrick J. Wong is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN; 2447d7d6d2fSDarrick J. Wong 2457d7d6d2fSDarrick J. Wong if (is_bmbt && irec->rm_offset != 0) 2467d7d6d2fSDarrick J. Wong return __this_address; 2477d7d6d2fSDarrick J. Wong 2487d7d6d2fSDarrick J. Wong if (!is_inode && irec->rm_offset != 0) 2497d7d6d2fSDarrick J. Wong return __this_address; 2507d7d6d2fSDarrick J. Wong 2517d7d6d2fSDarrick J. Wong if (is_unwritten && (is_bmbt || !is_inode || is_attr)) 2527d7d6d2fSDarrick J. Wong return __this_address; 2537d7d6d2fSDarrick J. Wong 2547d7d6d2fSDarrick J. Wong if (!is_inode && (is_bmbt || is_unwritten || is_attr)) 2557d7d6d2fSDarrick J. Wong return __this_address; 2567d7d6d2fSDarrick J. Wong 257*e774b2eaSDarrick J. Wong /* Check for a valid fork offset, if applicable. */ 258*e774b2eaSDarrick J. Wong if (is_inode && !is_bmbt && 259*e774b2eaSDarrick J. Wong !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount)) 260*e774b2eaSDarrick J. Wong return __this_address; 261*e774b2eaSDarrick J. Wong 262c4e34172SDarrick J. Wong return NULL; 263c4e34172SDarrick J. Wong } 264c4e34172SDarrick J. Wong 265ee12eaaaSDarrick J. Wong static inline int 266ee12eaaaSDarrick J. Wong xfs_rmap_complain_bad_rec( 267ee12eaaaSDarrick J. Wong struct xfs_btree_cur *cur, 268ee12eaaaSDarrick J. Wong xfs_failaddr_t fa, 269ee12eaaaSDarrick J. Wong const struct xfs_rmap_irec *irec) 270ee12eaaaSDarrick J. Wong { 271ee12eaaaSDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 272ee12eaaaSDarrick J. Wong 273ee12eaaaSDarrick J. Wong xfs_warn(mp, 274ee12eaaaSDarrick J. Wong "Reverse Mapping BTree record corruption in AG %d detected at %pS!", 275ee12eaaaSDarrick J. Wong cur->bc_ag.pag->pag_agno, fa); 276ee12eaaaSDarrick J. Wong xfs_warn(mp, 277ee12eaaaSDarrick J. Wong "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", 278ee12eaaaSDarrick J. Wong irec->rm_owner, irec->rm_flags, irec->rm_startblock, 279ee12eaaaSDarrick J. Wong irec->rm_blockcount); 280ee12eaaaSDarrick J. Wong return -EFSCORRUPTED; 281ee12eaaaSDarrick J. Wong } 282ee12eaaaSDarrick J. Wong 2834b8ed677SDarrick J. Wong /* 2844b8ed677SDarrick J. Wong * Get the data from the pointed-to record. 2854b8ed677SDarrick J. Wong */ 2864b8ed677SDarrick J. Wong int 2874b8ed677SDarrick J. Wong xfs_rmap_get_rec( 2884b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 2894b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec, 2904b8ed677SDarrick J. Wong int *stat) 2914b8ed677SDarrick J. Wong { 2924b8ed677SDarrick J. Wong union xfs_btree_rec *rec; 293c4e34172SDarrick J. Wong xfs_failaddr_t fa; 2944b8ed677SDarrick J. Wong int error; 2954b8ed677SDarrick J. Wong 2964b8ed677SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat); 2974b8ed677SDarrick J. Wong if (error || !*stat) 2984b8ed677SDarrick J. Wong return error; 2994b8ed677SDarrick J. Wong 300c4e34172SDarrick J. Wong fa = xfs_rmap_btrec_to_irec(rec, irec); 301c4e34172SDarrick J. Wong if (!fa) 302c4e34172SDarrick J. Wong fa = xfs_rmap_check_irec(cur, irec); 303c4e34172SDarrick J. Wong if (fa) 304ee12eaaaSDarrick J. Wong return xfs_rmap_complain_bad_rec(cur, fa, irec); 3059e6c08d4SDave Chinner 3069e6c08d4SDave Chinner return 0; 3074b8ed677SDarrick J. Wong } 3084b8ed677SDarrick J. Wong 309ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info { 310ceeb9c83SDarrick J. Wong struct xfs_rmap_irec high; 311ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec; 312ceeb9c83SDarrick J. Wong }; 313ceeb9c83SDarrick J. Wong 314ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 315ceeb9c83SDarrick J. Wong STATIC int 316ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper( 317ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 318159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec, 319ceeb9c83SDarrick J. Wong void *priv) 320ceeb9c83SDarrick J. Wong { 321ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 322ceeb9c83SDarrick J. Wong 323ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, 32450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, rec->rm_startblock, 325ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 326ceeb9c83SDarrick J. Wong rec->rm_flags); 327ceeb9c83SDarrick J. Wong 328ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 32939ee2239SDarrick J. Wong return 0; 330ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 331ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 332ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) 33339ee2239SDarrick J. Wong return 0; 334ceeb9c83SDarrick J. Wong 335ceeb9c83SDarrick J. Wong *info->irec = *rec; 336e7ee96dfSDarrick J. Wong return -ECANCELED; 337ceeb9c83SDarrick J. Wong } 338ceeb9c83SDarrick J. Wong 339ceeb9c83SDarrick J. Wong /* 340ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 341ceeb9c83SDarrick J. Wong * return a match with the same owner and adjacent physical and logical 342ceeb9c83SDarrick J. Wong * block ranges. 343ceeb9c83SDarrick J. Wong */ 3441edf8056SDarrick J. Wong STATIC int 345ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor( 346ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 347ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 348ceeb9c83SDarrick J. Wong uint64_t owner, 349ceeb9c83SDarrick J. Wong uint64_t offset, 350ceeb9c83SDarrick J. Wong unsigned int flags, 351ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 352ceeb9c83SDarrick J. Wong int *stat) 353ceeb9c83SDarrick J. Wong { 354ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 3551edf8056SDarrick J. Wong int found = 0; 356ceeb9c83SDarrick J. Wong int error; 357ceeb9c83SDarrick J. Wong 358ceeb9c83SDarrick J. Wong *stat = 0; 359ceeb9c83SDarrick J. Wong if (bno == 0) 360ceeb9c83SDarrick J. Wong return 0; 361ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno - 1; 362ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 363ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && 364ceeb9c83SDarrick J. Wong !(flags & XFS_RMAP_BMBT_BLOCK)) { 365ceeb9c83SDarrick J. Wong if (offset == 0) 366ceeb9c83SDarrick J. Wong return 0; 367ceeb9c83SDarrick J. Wong info.high.rm_offset = offset - 1; 368ceeb9c83SDarrick J. Wong } else 369ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 370ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 371ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 372ceeb9c83SDarrick J. Wong info.irec = irec; 373ceeb9c83SDarrick J. Wong 374ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, 37550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags); 376ceeb9c83SDarrick J. Wong 3771edf8056SDarrick J. Wong /* 3781edf8056SDarrick J. Wong * Historically, we always used the range query to walk every reverse 3791edf8056SDarrick J. Wong * mapping that could possibly overlap the key that the caller asked 3801edf8056SDarrick J. Wong * for, and filter out the ones that don't. That is very slow when 3811edf8056SDarrick J. Wong * there are a lot of records. 3821edf8056SDarrick J. Wong * 3831edf8056SDarrick J. Wong * However, there are two scenarios where the classic btree search can 3841edf8056SDarrick J. Wong * produce correct results -- if the index contains a record that is an 3851edf8056SDarrick J. Wong * exact match for the lookup key; and if there are no other records 3861edf8056SDarrick J. Wong * between the record we want and the key we supplied. 3871edf8056SDarrick J. Wong * 3881edf8056SDarrick J. Wong * As an optimization, try a non-overlapped lookup first. This makes 3891edf8056SDarrick J. Wong * extent conversion and remap operations run a bit faster if the 3901edf8056SDarrick J. Wong * physical extents aren't being shared. If we don't find what we 3911edf8056SDarrick J. Wong * want, we fall back to the overlapped query. 3921edf8056SDarrick J. Wong */ 3931edf8056SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec, 3941edf8056SDarrick J. Wong &found); 3951edf8056SDarrick J. Wong if (error) 3961edf8056SDarrick J. Wong return error; 3971edf8056SDarrick J. Wong if (found) 3981edf8056SDarrick J. Wong error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info); 3991edf8056SDarrick J. Wong if (!error) 400ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 401ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper, &info); 4021edf8056SDarrick J. Wong if (error != -ECANCELED) 4031edf8056SDarrick J. Wong return error; 4041edf8056SDarrick J. Wong 4051edf8056SDarrick J. Wong *stat = 1; 406ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 40750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, irec->rm_startblock, 4081edf8056SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, irec->rm_offset, 4091edf8056SDarrick J. Wong irec->rm_flags); 4101edf8056SDarrick J. Wong return 0; 411ceeb9c83SDarrick J. Wong } 412ceeb9c83SDarrick J. Wong 413ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 414ceeb9c83SDarrick J. Wong STATIC int 415ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper( 416ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 417159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec, 418ceeb9c83SDarrick J. Wong void *priv) 419ceeb9c83SDarrick J. Wong { 420ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 421ceeb9c83SDarrick J. Wong 422ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, 42350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, rec->rm_startblock, 424ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 425ceeb9c83SDarrick J. Wong rec->rm_flags); 426ceeb9c83SDarrick J. Wong 427ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 42839ee2239SDarrick J. Wong return 0; 429ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 430ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 431ceeb9c83SDarrick J. Wong (rec->rm_offset > info->high.rm_offset || 432ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) 43339ee2239SDarrick J. Wong return 0; 434ceeb9c83SDarrick J. Wong 435ceeb9c83SDarrick J. Wong *info->irec = *rec; 436e7ee96dfSDarrick J. Wong return -ECANCELED; 437ceeb9c83SDarrick J. Wong } 438ceeb9c83SDarrick J. Wong 439ceeb9c83SDarrick J. Wong /* 440ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 441ceeb9c83SDarrick J. Wong * return a match with the same owner and overlapping physical and logical 442ceeb9c83SDarrick J. Wong * block ranges. This is the overlapping-interval version of 443ceeb9c83SDarrick J. Wong * xfs_rmap_lookup_le. 444ceeb9c83SDarrick J. Wong */ 445ceeb9c83SDarrick J. Wong int 446ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range( 447ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 448ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 449ceeb9c83SDarrick J. Wong uint64_t owner, 450ceeb9c83SDarrick J. Wong uint64_t offset, 451ceeb9c83SDarrick J. Wong unsigned int flags, 452ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 453ceeb9c83SDarrick J. Wong int *stat) 454ceeb9c83SDarrick J. Wong { 455ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 45675d893d1SDarrick J. Wong int found = 0; 457ceeb9c83SDarrick J. Wong int error; 458ceeb9c83SDarrick J. Wong 459ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno; 460ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 461ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) 462ceeb9c83SDarrick J. Wong info.high.rm_offset = offset; 463ceeb9c83SDarrick J. Wong else 464ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 465ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 466ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 467ceeb9c83SDarrick J. Wong *stat = 0; 468ceeb9c83SDarrick J. Wong info.irec = irec; 469ceeb9c83SDarrick J. Wong 47075d893d1SDarrick J. Wong trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno, 47175d893d1SDarrick J. Wong bno, 0, owner, offset, flags); 47275d893d1SDarrick J. Wong 47375d893d1SDarrick J. Wong /* 47475d893d1SDarrick J. Wong * Historically, we always used the range query to walk every reverse 47575d893d1SDarrick J. Wong * mapping that could possibly overlap the key that the caller asked 47675d893d1SDarrick J. Wong * for, and filter out the ones that don't. That is very slow when 47775d893d1SDarrick J. Wong * there are a lot of records. 47875d893d1SDarrick J. Wong * 47975d893d1SDarrick J. Wong * However, there are two scenarios where the classic btree search can 48075d893d1SDarrick J. Wong * produce correct results -- if the index contains a record that is an 48175d893d1SDarrick J. Wong * exact match for the lookup key; and if there are no other records 48275d893d1SDarrick J. Wong * between the record we want and the key we supplied. 48375d893d1SDarrick J. Wong * 48475d893d1SDarrick J. Wong * As an optimization, try a non-overlapped lookup first. This makes 48575d893d1SDarrick J. Wong * scrub run much faster on most filesystems because bmbt records are 48675d893d1SDarrick J. Wong * usually an exact match for rmap records. If we don't find what we 48775d893d1SDarrick J. Wong * want, we fall back to the overlapped query. 48875d893d1SDarrick J. Wong */ 48975d893d1SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec, 49075d893d1SDarrick J. Wong &found); 49175d893d1SDarrick J. Wong if (error) 49275d893d1SDarrick J. Wong return error; 49375d893d1SDarrick J. Wong if (found) 49475d893d1SDarrick J. Wong error = xfs_rmap_lookup_le_range_helper(cur, irec, &info); 49575d893d1SDarrick J. Wong if (!error) 496ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 497ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper, &info); 49875d893d1SDarrick J. Wong if (error != -ECANCELED) 49975d893d1SDarrick J. Wong return error; 50075d893d1SDarrick J. Wong 50175d893d1SDarrick J. Wong *stat = 1; 502ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 50350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, irec->rm_startblock, 50475d893d1SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, irec->rm_offset, 50575d893d1SDarrick J. Wong irec->rm_flags); 50675d893d1SDarrick J. Wong return 0; 507ceeb9c83SDarrick J. Wong } 508ceeb9c83SDarrick J. Wong 509f922cd90SDarrick J. Wong /* 51068c58e9bSDarrick J. Wong * Perform all the relevant owner checks for a removal op. If we're doing an 51168c58e9bSDarrick J. Wong * unknown-owner removal then we have no owner information to check. 51268c58e9bSDarrick J. Wong */ 51368c58e9bSDarrick J. Wong static int 51468c58e9bSDarrick J. Wong xfs_rmap_free_check_owner( 51568c58e9bSDarrick J. Wong struct xfs_mount *mp, 51668c58e9bSDarrick J. Wong uint64_t ltoff, 51768c58e9bSDarrick J. Wong struct xfs_rmap_irec *rec, 51868c58e9bSDarrick J. Wong xfs_filblks_t len, 51968c58e9bSDarrick J. Wong uint64_t owner, 52068c58e9bSDarrick J. Wong uint64_t offset, 52168c58e9bSDarrick J. Wong unsigned int flags) 52268c58e9bSDarrick J. Wong { 52368c58e9bSDarrick J. Wong int error = 0; 52468c58e9bSDarrick J. Wong 52568c58e9bSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN) 52668c58e9bSDarrick J. Wong return 0; 52768c58e9bSDarrick J. Wong 52868c58e9bSDarrick J. Wong /* Make sure the unwritten flag matches. */ 529f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 530f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) != 531f9e03706SDarrick J. Wong (rec->rm_flags & XFS_RMAP_UNWRITTEN))) { 532f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 533f9e03706SDarrick J. Wong goto out; 534f9e03706SDarrick J. Wong } 53568c58e9bSDarrick J. Wong 53668c58e9bSDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 537f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) { 538f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 539f9e03706SDarrick J. Wong goto out; 540f9e03706SDarrick J. Wong } 54168c58e9bSDarrick J. Wong 54268c58e9bSDarrick J. Wong /* Check the offset, if necessary. */ 54368c58e9bSDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(owner)) 54468c58e9bSDarrick J. Wong goto out; 54568c58e9bSDarrick J. Wong 54668c58e9bSDarrick J. Wong if (flags & XFS_RMAP_BMBT_BLOCK) { 547f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 548f9e03706SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) { 549f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 550f9e03706SDarrick J. Wong goto out; 551f9e03706SDarrick J. Wong } 55268c58e9bSDarrick J. Wong } else { 553f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) { 554f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 555f9e03706SDarrick J. Wong goto out; 556f9e03706SDarrick J. Wong } 557f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 558f9e03706SDarrick J. Wong offset + len > ltoff + rec->rm_blockcount)) { 559f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 560f9e03706SDarrick J. Wong goto out; 561f9e03706SDarrick J. Wong } 56268c58e9bSDarrick J. Wong } 56368c58e9bSDarrick J. Wong 56468c58e9bSDarrick J. Wong out: 56568c58e9bSDarrick J. Wong return error; 56668c58e9bSDarrick J. Wong } 56768c58e9bSDarrick J. Wong 56868c58e9bSDarrick J. Wong /* 569f922cd90SDarrick J. Wong * Find the extent in the rmap btree and remove it. 570f922cd90SDarrick J. Wong * 571f922cd90SDarrick J. Wong * The record we find should always be an exact match for the extent that we're 572f922cd90SDarrick J. Wong * looking for, since we insert them into the btree without modification. 573f922cd90SDarrick J. Wong * 574f922cd90SDarrick J. Wong * Special Case #1: when growing the filesystem, we "free" an extent when 575f922cd90SDarrick J. Wong * growing the last AG. This extent is new space and so it is not tracked as 576f922cd90SDarrick J. Wong * used space in the btree. The growfs code will pass in an owner of 577f922cd90SDarrick J. Wong * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this 578f922cd90SDarrick J. Wong * extent. We verify that - the extent lookup result in a record that does not 579f922cd90SDarrick J. Wong * overlap. 580f922cd90SDarrick J. Wong * 581f922cd90SDarrick J. Wong * Special Case #2: EFIs do not record the owner of the extent, so when 582f922cd90SDarrick J. Wong * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap 583f922cd90SDarrick J. Wong * btree to ignore the owner (i.e. wildcard match) so we don't trigger 584f922cd90SDarrick J. Wong * corruption checks during log recovery. 585f922cd90SDarrick J. Wong */ 586f922cd90SDarrick J. Wong STATIC int 587f922cd90SDarrick J. Wong xfs_rmap_unmap( 588f922cd90SDarrick J. Wong struct xfs_btree_cur *cur, 589f922cd90SDarrick J. Wong xfs_agblock_t bno, 590f922cd90SDarrick J. Wong xfs_extlen_t len, 591f922cd90SDarrick J. Wong bool unwritten, 59266e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 593f922cd90SDarrick J. Wong { 594f922cd90SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 595f922cd90SDarrick J. Wong struct xfs_rmap_irec ltrec; 596f922cd90SDarrick J. Wong uint64_t ltoff; 597f922cd90SDarrick J. Wong int error = 0; 598f922cd90SDarrick J. Wong int i; 599f922cd90SDarrick J. Wong uint64_t owner; 600f922cd90SDarrick J. Wong uint64_t offset; 601f922cd90SDarrick J. Wong unsigned int flags; 602f922cd90SDarrick J. Wong bool ignore_off; 603f922cd90SDarrick J. Wong 604f922cd90SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 605f922cd90SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 606f922cd90SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 607f922cd90SDarrick J. Wong if (unwritten) 608f922cd90SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 60950f02fe3SDave Chinner trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len, 610f922cd90SDarrick J. Wong unwritten, oinfo); 611f922cd90SDarrick J. Wong 612f922cd90SDarrick J. Wong /* 613f922cd90SDarrick J. Wong * We should always have a left record because there's a static record 614f922cd90SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 615f922cd90SDarrick J. Wong * will not ever be removed from the tree. 616f922cd90SDarrick J. Wong */ 6175b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i); 618f922cd90SDarrick J. Wong if (error) 619f922cd90SDarrick J. Wong goto out_error; 620f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 621f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 622f9e03706SDarrick J. Wong goto out_error; 623f9e03706SDarrick J. Wong } 624f922cd90SDarrick J. Wong 625f922cd90SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 62650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, ltrec.rm_startblock, 627f922cd90SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 628f922cd90SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 629f922cd90SDarrick J. Wong ltoff = ltrec.rm_offset; 630f922cd90SDarrick J. Wong 631f922cd90SDarrick J. Wong /* 632f922cd90SDarrick J. Wong * For growfs, the incoming extent must be beyond the left record we 633f922cd90SDarrick J. Wong * just found as it is new space and won't be used by anyone. This is 634f922cd90SDarrick J. Wong * just a corruption check as we don't actually do anything with this 635f922cd90SDarrick J. Wong * extent. Note that we need to use >= instead of > because it might 636f922cd90SDarrick J. Wong * be the case that the "left" extent goes all the way to EOFS. 637f922cd90SDarrick J. Wong */ 638f922cd90SDarrick J. Wong if (owner == XFS_RMAP_OWN_NULL) { 639f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 640f9e03706SDarrick J. Wong bno < 641f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount)) { 642f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 643f9e03706SDarrick J. Wong goto out_error; 644f9e03706SDarrick J. Wong } 645f922cd90SDarrick J. Wong goto out_done; 646f922cd90SDarrick J. Wong } 647f922cd90SDarrick J. Wong 64833df3a9cSDarrick J. Wong /* 64933df3a9cSDarrick J. Wong * If we're doing an unknown-owner removal for EFI recovery, we expect 65033df3a9cSDarrick J. Wong * to find the full range in the rmapbt or nothing at all. If we 65133df3a9cSDarrick J. Wong * don't find any rmaps overlapping either end of the range, we're 65233df3a9cSDarrick J. Wong * done. Hopefully this means that the EFI creator already queued 65333df3a9cSDarrick J. Wong * (and finished) a RUI to remove the rmap. 65433df3a9cSDarrick J. Wong */ 65533df3a9cSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN && 65633df3a9cSDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 65733df3a9cSDarrick J. Wong struct xfs_rmap_irec rtrec; 65833df3a9cSDarrick J. Wong 65933df3a9cSDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 66033df3a9cSDarrick J. Wong if (error) 66133df3a9cSDarrick J. Wong goto out_error; 66233df3a9cSDarrick J. Wong if (i == 0) 66333df3a9cSDarrick J. Wong goto out_done; 66433df3a9cSDarrick J. Wong error = xfs_rmap_get_rec(cur, &rtrec, &i); 66533df3a9cSDarrick J. Wong if (error) 66633df3a9cSDarrick J. Wong goto out_error; 667f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 668f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 669f9e03706SDarrick J. Wong goto out_error; 670f9e03706SDarrick J. Wong } 67133df3a9cSDarrick J. Wong if (rtrec.rm_startblock >= bno + len) 67233df3a9cSDarrick J. Wong goto out_done; 67333df3a9cSDarrick J. Wong } 67433df3a9cSDarrick J. Wong 675f922cd90SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 676f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 677f9e03706SDarrick J. Wong ltrec.rm_startblock > bno || 678f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount < 679f9e03706SDarrick J. Wong bno + len)) { 680f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 681f9e03706SDarrick J. Wong goto out_error; 682f9e03706SDarrick J. Wong } 683f922cd90SDarrick J. Wong 68468c58e9bSDarrick J. Wong /* Check owner information. */ 685a1f69417SEric Sandeen error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner, 68668c58e9bSDarrick J. Wong offset, flags); 68768c58e9bSDarrick J. Wong if (error) 68868c58e9bSDarrick J. Wong goto out_error; 689f922cd90SDarrick J. Wong 690f922cd90SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 691f922cd90SDarrick J. Wong /* exact match, simply remove the record from rmap tree */ 69250f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 693f922cd90SDarrick J. Wong ltrec.rm_startblock, ltrec.rm_blockcount, 694f922cd90SDarrick J. Wong ltrec.rm_owner, ltrec.rm_offset, 695f922cd90SDarrick J. Wong ltrec.rm_flags); 696f922cd90SDarrick J. Wong error = xfs_btree_delete(cur, &i); 697f922cd90SDarrick J. Wong if (error) 698f922cd90SDarrick J. Wong goto out_error; 699f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 700f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 701f9e03706SDarrick J. Wong goto out_error; 702f9e03706SDarrick J. Wong } 703f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 704f922cd90SDarrick J. Wong /* 705f922cd90SDarrick J. Wong * overlap left hand side of extent: move the start, trim the 706f922cd90SDarrick J. Wong * length and update the current record. 707f922cd90SDarrick J. Wong * 708f922cd90SDarrick J. Wong * ltbno ltlen 709f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 710f922cd90SDarrick J. Wong * Freeing: |fffffffff| 711f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 712f922cd90SDarrick J. Wong * bno len 713f922cd90SDarrick J. Wong */ 714f922cd90SDarrick J. Wong ltrec.rm_startblock += len; 715f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 716f922cd90SDarrick J. Wong if (!ignore_off) 717f922cd90SDarrick J. Wong ltrec.rm_offset += len; 718f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 719f922cd90SDarrick J. Wong if (error) 720f922cd90SDarrick J. Wong goto out_error; 721f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 722f922cd90SDarrick J. Wong /* 723f922cd90SDarrick J. Wong * overlap right hand side of extent: trim the length and update 724f922cd90SDarrick J. Wong * the current record. 725f922cd90SDarrick J. Wong * 726f922cd90SDarrick J. Wong * ltbno ltlen 727f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 728f922cd90SDarrick J. Wong * Freeing: |fffffffff| 729f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 730f922cd90SDarrick J. Wong * bno len 731f922cd90SDarrick J. Wong */ 732f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 733f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 734f922cd90SDarrick J. Wong if (error) 735f922cd90SDarrick J. Wong goto out_error; 736f922cd90SDarrick J. Wong } else { 737f922cd90SDarrick J. Wong 738f922cd90SDarrick J. Wong /* 739f922cd90SDarrick J. Wong * overlap middle of extent: trim the length of the existing 740f922cd90SDarrick J. Wong * record to the length of the new left-extent size, increment 741f922cd90SDarrick J. Wong * the insertion position so we can insert a new record 742f922cd90SDarrick J. Wong * containing the remaining right-extent space. 743f922cd90SDarrick J. Wong * 744f922cd90SDarrick J. Wong * ltbno ltlen 745f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 746f922cd90SDarrick J. Wong * Freeing: |fffffffff| 747f922cd90SDarrick J. Wong * Result: |rrrrr| |rrrr| 748f922cd90SDarrick J. Wong * bno len 749f922cd90SDarrick J. Wong */ 750f922cd90SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 751f922cd90SDarrick J. Wong 752f922cd90SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 753f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 754f922cd90SDarrick J. Wong if (error) 755f922cd90SDarrick J. Wong goto out_error; 756f922cd90SDarrick J. Wong 757f922cd90SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 758f922cd90SDarrick J. Wong if (error) 759f922cd90SDarrick J. Wong goto out_error; 760f922cd90SDarrick J. Wong 761f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno + len; 762f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount = orig_len - len - 763f922cd90SDarrick J. Wong ltrec.rm_blockcount; 764f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner = ltrec.rm_owner; 765f922cd90SDarrick J. Wong if (ignore_off) 766f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = 0; 767f922cd90SDarrick J. Wong else 768f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = offset + len; 769f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 77050f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, 771f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock, 772f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount, 773f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner, 774f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset, 775f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags); 776f922cd90SDarrick J. Wong error = xfs_btree_insert(cur, &i); 777f922cd90SDarrick J. Wong if (error) 778f922cd90SDarrick J. Wong goto out_error; 779f922cd90SDarrick J. Wong } 780f922cd90SDarrick J. Wong 781f922cd90SDarrick J. Wong out_done: 78250f02fe3SDave Chinner trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 783f922cd90SDarrick J. Wong unwritten, oinfo); 784f922cd90SDarrick J. Wong out_error: 785f922cd90SDarrick J. Wong if (error) 78650f02fe3SDave Chinner trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno, 787f922cd90SDarrick J. Wong error, _RET_IP_); 788f922cd90SDarrick J. Wong return error; 789f922cd90SDarrick J. Wong } 790f922cd90SDarrick J. Wong 791f922cd90SDarrick J. Wong /* 792f922cd90SDarrick J. Wong * Remove a reference to an extent in the rmap btree. 793f922cd90SDarrick J. Wong */ 794673930c3SDarrick J. Wong int 795673930c3SDarrick J. Wong xfs_rmap_free( 796673930c3SDarrick J. Wong struct xfs_trans *tp, 797673930c3SDarrick J. Wong struct xfs_buf *agbp, 798fa9c3c19SDave Chinner struct xfs_perag *pag, 799673930c3SDarrick J. Wong xfs_agblock_t bno, 800673930c3SDarrick J. Wong xfs_extlen_t len, 80166e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 802673930c3SDarrick J. Wong { 803673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 804f922cd90SDarrick J. Wong struct xfs_btree_cur *cur; 805f922cd90SDarrick J. Wong int error; 806673930c3SDarrick J. Wong 80738c26bfdSDave Chinner if (!xfs_has_rmapbt(mp)) 808673930c3SDarrick J. Wong return 0; 809673930c3SDarrick J. Wong 810fa9c3c19SDave Chinner cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); 811f922cd90SDarrick J. Wong 812f922cd90SDarrick J. Wong error = xfs_rmap_unmap(cur, bno, len, false, oinfo); 813f922cd90SDarrick J. Wong 8140b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 815673930c3SDarrick J. Wong return error; 816673930c3SDarrick J. Wong } 817673930c3SDarrick J. Wong 8180a1b0b38SDarrick J. Wong /* 8190a1b0b38SDarrick J. Wong * A mergeable rmap must have the same owner and the same values for 8200a1b0b38SDarrick J. Wong * the unwritten, attr_fork, and bmbt flags. The startblock and 8210a1b0b38SDarrick J. Wong * offset are checked separately. 8220a1b0b38SDarrick J. Wong */ 8230a1b0b38SDarrick J. Wong static bool 8240a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable( 8250a1b0b38SDarrick J. Wong struct xfs_rmap_irec *irec, 8260a1b0b38SDarrick J. Wong uint64_t owner, 8270a1b0b38SDarrick J. Wong unsigned int flags) 8280a1b0b38SDarrick J. Wong { 8290a1b0b38SDarrick J. Wong if (irec->rm_owner == XFS_RMAP_OWN_NULL) 8300a1b0b38SDarrick J. Wong return false; 8310a1b0b38SDarrick J. Wong if (irec->rm_owner != owner) 8320a1b0b38SDarrick J. Wong return false; 8330a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_UNWRITTEN) ^ 8340a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_UNWRITTEN)) 8350a1b0b38SDarrick J. Wong return false; 8360a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_ATTR_FORK) ^ 8370a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_ATTR_FORK)) 8380a1b0b38SDarrick J. Wong return false; 8390a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_BMBT_BLOCK) ^ 8400a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) 8410a1b0b38SDarrick J. Wong return false; 8420a1b0b38SDarrick J. Wong return true; 8430a1b0b38SDarrick J. Wong } 8440a1b0b38SDarrick J. Wong 8450a1b0b38SDarrick J. Wong /* 8460a1b0b38SDarrick J. Wong * When we allocate a new block, the first thing we do is add a reference to 8470a1b0b38SDarrick J. Wong * the extent in the rmap btree. This takes the form of a [agbno, length, 8480a1b0b38SDarrick J. Wong * owner, offset] record. Flags are encoded in the high bits of the offset 8490a1b0b38SDarrick J. Wong * field. 8500a1b0b38SDarrick J. Wong */ 8510a1b0b38SDarrick J. Wong STATIC int 8520a1b0b38SDarrick J. Wong xfs_rmap_map( 8530a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur, 8540a1b0b38SDarrick J. Wong xfs_agblock_t bno, 8550a1b0b38SDarrick J. Wong xfs_extlen_t len, 8560a1b0b38SDarrick J. Wong bool unwritten, 85766e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 8580a1b0b38SDarrick J. Wong { 8590a1b0b38SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 8600a1b0b38SDarrick J. Wong struct xfs_rmap_irec ltrec; 8610a1b0b38SDarrick J. Wong struct xfs_rmap_irec gtrec; 8620a1b0b38SDarrick J. Wong int have_gt; 8630a1b0b38SDarrick J. Wong int have_lt; 8640a1b0b38SDarrick J. Wong int error = 0; 8650a1b0b38SDarrick J. Wong int i; 8660a1b0b38SDarrick J. Wong uint64_t owner; 8670a1b0b38SDarrick J. Wong uint64_t offset; 8680a1b0b38SDarrick J. Wong unsigned int flags = 0; 8690a1b0b38SDarrick J. Wong bool ignore_off; 8700a1b0b38SDarrick J. Wong 8710a1b0b38SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 8720a1b0b38SDarrick J. Wong ASSERT(owner != 0); 8730a1b0b38SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 8740a1b0b38SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 8750a1b0b38SDarrick J. Wong if (unwritten) 8760a1b0b38SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 87750f02fe3SDave Chinner trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len, 8780a1b0b38SDarrick J. Wong unwritten, oinfo); 87933df3a9cSDarrick J. Wong ASSERT(!xfs_rmap_should_skip_owner_update(oinfo)); 8800a1b0b38SDarrick J. Wong 8810a1b0b38SDarrick J. Wong /* 8820a1b0b38SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 8830a1b0b38SDarrick J. Wong * record for our insertion point. This will also give us the record for 8840a1b0b38SDarrick J. Wong * start block contiguity tests. 8850a1b0b38SDarrick J. Wong */ 8865b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, 8870a1b0b38SDarrick J. Wong &have_lt); 8880a1b0b38SDarrick J. Wong if (error) 8890a1b0b38SDarrick J. Wong goto out_error; 890fa248de9SDarrick J. Wong if (have_lt) { 8910a1b0b38SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 89250f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, ltrec.rm_startblock, 8930a1b0b38SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 8940a1b0b38SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 8950a1b0b38SDarrick J. Wong 8960a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(<rec, owner, flags)) 8970a1b0b38SDarrick J. Wong have_lt = 0; 898fa248de9SDarrick J. Wong } 8990a1b0b38SDarrick J. Wong 900f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 901f9e03706SDarrick J. Wong have_lt != 0 && 902f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount > bno)) { 903f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 904f9e03706SDarrick J. Wong goto out_error; 905f9e03706SDarrick J. Wong } 9060a1b0b38SDarrick J. Wong 9070a1b0b38SDarrick J. Wong /* 9080a1b0b38SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 9090a1b0b38SDarrick J. Wong * insertion point. This will give us the record for end block 9100a1b0b38SDarrick J. Wong * contiguity tests. 9110a1b0b38SDarrick J. Wong */ 9120a1b0b38SDarrick J. Wong error = xfs_btree_increment(cur, 0, &have_gt); 9130a1b0b38SDarrick J. Wong if (error) 9140a1b0b38SDarrick J. Wong goto out_error; 9150a1b0b38SDarrick J. Wong if (have_gt) { 9160a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 9170a1b0b38SDarrick J. Wong if (error) 9180a1b0b38SDarrick J. Wong goto out_error; 919f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) { 920f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 921f9e03706SDarrick J. Wong goto out_error; 922f9e03706SDarrick J. Wong } 923f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) { 924f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 925f9e03706SDarrick J. Wong goto out_error; 926f9e03706SDarrick J. Wong } 9270a1b0b38SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 92850f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, gtrec.rm_startblock, 9290a1b0b38SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 9300a1b0b38SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 9310a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 9320a1b0b38SDarrick J. Wong have_gt = 0; 9330a1b0b38SDarrick J. Wong } 9340a1b0b38SDarrick J. Wong 9350a1b0b38SDarrick J. Wong /* 9360a1b0b38SDarrick J. Wong * Note: cursor currently points one record to the right of ltrec, even 9370a1b0b38SDarrick J. Wong * if there is no record in the tree to the right. 9380a1b0b38SDarrick J. Wong */ 9390a1b0b38SDarrick J. Wong if (have_lt && 9400a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 9410a1b0b38SDarrick J. Wong (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { 9420a1b0b38SDarrick J. Wong /* 9430a1b0b38SDarrick J. Wong * left edge contiguous, merge into left record. 9440a1b0b38SDarrick J. Wong * 9450a1b0b38SDarrick J. Wong * ltbno ltlen 9460a1b0b38SDarrick J. Wong * orig: |ooooooooo| 9470a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 9480a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 9490a1b0b38SDarrick J. Wong * bno len 9500a1b0b38SDarrick J. Wong */ 9510a1b0b38SDarrick J. Wong ltrec.rm_blockcount += len; 9520a1b0b38SDarrick J. Wong if (have_gt && 9530a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 9540a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset) && 9550a1b0b38SDarrick J. Wong (unsigned long)ltrec.rm_blockcount + len + 9560a1b0b38SDarrick J. Wong gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { 9570a1b0b38SDarrick J. Wong /* 9580a1b0b38SDarrick J. Wong * right edge also contiguous, delete right record 9590a1b0b38SDarrick J. Wong * and merge into left record. 9600a1b0b38SDarrick J. Wong * 9610a1b0b38SDarrick J. Wong * ltbno ltlen gtbno gtlen 9620a1b0b38SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 9630a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 9640a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 9650a1b0b38SDarrick J. Wong */ 9660a1b0b38SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 96750f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 9680a1b0b38SDarrick J. Wong gtrec.rm_startblock, 9690a1b0b38SDarrick J. Wong gtrec.rm_blockcount, 9700a1b0b38SDarrick J. Wong gtrec.rm_owner, 9710a1b0b38SDarrick J. Wong gtrec.rm_offset, 9720a1b0b38SDarrick J. Wong gtrec.rm_flags); 9730a1b0b38SDarrick J. Wong error = xfs_btree_delete(cur, &i); 9740a1b0b38SDarrick J. Wong if (error) 9750a1b0b38SDarrick J. Wong goto out_error; 976f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 977f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 978f9e03706SDarrick J. Wong goto out_error; 979f9e03706SDarrick J. Wong } 9800a1b0b38SDarrick J. Wong } 9810a1b0b38SDarrick J. Wong 9820a1b0b38SDarrick J. Wong /* point the cursor back to the left record and update */ 9830a1b0b38SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &have_gt); 9840a1b0b38SDarrick J. Wong if (error) 9850a1b0b38SDarrick J. Wong goto out_error; 9860a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 9870a1b0b38SDarrick J. Wong if (error) 9880a1b0b38SDarrick J. Wong goto out_error; 9890a1b0b38SDarrick J. Wong } else if (have_gt && 9900a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 9910a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset)) { 9920a1b0b38SDarrick J. Wong /* 9930a1b0b38SDarrick J. Wong * right edge contiguous, merge into right record. 9940a1b0b38SDarrick J. Wong * 9950a1b0b38SDarrick J. Wong * gtbno gtlen 9960a1b0b38SDarrick J. Wong * Orig: |ooooooooo| 9970a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 9980a1b0b38SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 9990a1b0b38SDarrick J. Wong * bno len 10000a1b0b38SDarrick J. Wong */ 10010a1b0b38SDarrick J. Wong gtrec.rm_startblock = bno; 10020a1b0b38SDarrick J. Wong gtrec.rm_blockcount += len; 10030a1b0b38SDarrick J. Wong if (!ignore_off) 10040a1b0b38SDarrick J. Wong gtrec.rm_offset = offset; 10050a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, >rec); 10060a1b0b38SDarrick J. Wong if (error) 10070a1b0b38SDarrick J. Wong goto out_error; 10080a1b0b38SDarrick J. Wong } else { 10090a1b0b38SDarrick J. Wong /* 10100a1b0b38SDarrick J. Wong * no contiguous edge with identical owner, insert 10110a1b0b38SDarrick J. Wong * new record at current cursor position. 10120a1b0b38SDarrick J. Wong */ 10130a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 10140a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 10150a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 10160a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 10170a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 101850f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len, 10190a1b0b38SDarrick J. Wong owner, offset, flags); 10200a1b0b38SDarrick J. Wong error = xfs_btree_insert(cur, &i); 10210a1b0b38SDarrick J. Wong if (error) 10220a1b0b38SDarrick J. Wong goto out_error; 1023f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1024f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1025f9e03706SDarrick J. Wong goto out_error; 1026f9e03706SDarrick J. Wong } 10270a1b0b38SDarrick J. Wong } 10280a1b0b38SDarrick J. Wong 102950f02fe3SDave Chinner trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 10300a1b0b38SDarrick J. Wong unwritten, oinfo); 10310a1b0b38SDarrick J. Wong out_error: 10320a1b0b38SDarrick J. Wong if (error) 103350f02fe3SDave Chinner trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno, 10340a1b0b38SDarrick J. Wong error, _RET_IP_); 10350a1b0b38SDarrick J. Wong return error; 10360a1b0b38SDarrick J. Wong } 10370a1b0b38SDarrick J. Wong 10380a1b0b38SDarrick J. Wong /* 10390a1b0b38SDarrick J. Wong * Add a reference to an extent in the rmap btree. 10400a1b0b38SDarrick J. Wong */ 1041673930c3SDarrick J. Wong int 1042673930c3SDarrick J. Wong xfs_rmap_alloc( 1043673930c3SDarrick J. Wong struct xfs_trans *tp, 1044673930c3SDarrick J. Wong struct xfs_buf *agbp, 1045fa9c3c19SDave Chinner struct xfs_perag *pag, 1046673930c3SDarrick J. Wong xfs_agblock_t bno, 1047673930c3SDarrick J. Wong xfs_extlen_t len, 104866e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1049673930c3SDarrick J. Wong { 1050673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 10510a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur; 10520a1b0b38SDarrick J. Wong int error; 1053673930c3SDarrick J. Wong 105438c26bfdSDave Chinner if (!xfs_has_rmapbt(mp)) 1055673930c3SDarrick J. Wong return 0; 1056673930c3SDarrick J. Wong 1057fa9c3c19SDave Chinner cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); 10580a1b0b38SDarrick J. Wong error = xfs_rmap_map(cur, bno, len, false, oinfo); 10590a1b0b38SDarrick J. Wong 10600b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 1061673930c3SDarrick J. Wong return error; 1062673930c3SDarrick J. Wong } 1063c543838aSDarrick J. Wong 1064fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG (1 << 0) 1065fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG (1 << 1) 1066fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING (1 << 2) 1067fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING (1 << 3) 1068fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID (1 << 6) 1069fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID (1 << 7) 1070fb7d9267SDarrick J. Wong 1071fb7d9267SDarrick J. Wong #define LEFT r[0] 1072fb7d9267SDarrick J. Wong #define RIGHT r[1] 1073fb7d9267SDarrick J. Wong #define PREV r[2] 1074fb7d9267SDarrick J. Wong #define NEW r[3] 1075fb7d9267SDarrick J. Wong 1076fb7d9267SDarrick J. Wong /* 1077fb7d9267SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. 1078fb7d9267SDarrick J. Wong * Does not handle overlapping extents. 1079fb7d9267SDarrick J. Wong */ 1080fb7d9267SDarrick J. Wong STATIC int 1081fb7d9267SDarrick J. Wong xfs_rmap_convert( 1082fb7d9267SDarrick J. Wong struct xfs_btree_cur *cur, 1083fb7d9267SDarrick J. Wong xfs_agblock_t bno, 1084fb7d9267SDarrick J. Wong xfs_extlen_t len, 1085fb7d9267SDarrick J. Wong bool unwritten, 108666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 1087fb7d9267SDarrick J. Wong { 1088fb7d9267SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1089fb7d9267SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 109066e3237eSDarrick J. Wong /* left is 0, right is 1, */ 109166e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 1092fb7d9267SDarrick J. Wong uint64_t owner; 1093fb7d9267SDarrick J. Wong uint64_t offset; 1094fb7d9267SDarrick J. Wong uint64_t new_endoff; 1095fb7d9267SDarrick J. Wong unsigned int oldext; 1096fb7d9267SDarrick J. Wong unsigned int newext; 1097fb7d9267SDarrick J. Wong unsigned int flags = 0; 1098fb7d9267SDarrick J. Wong int i; 1099fb7d9267SDarrick J. Wong int state = 0; 1100fb7d9267SDarrick J. Wong int error; 1101fb7d9267SDarrick J. Wong 1102fb7d9267SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1103fb7d9267SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 1104fb7d9267SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 1105fb7d9267SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 1106fb7d9267SDarrick J. Wong new_endoff = offset + len; 110750f02fe3SDave Chinner trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len, 1108fb7d9267SDarrick J. Wong unwritten, oinfo); 1109fb7d9267SDarrick J. Wong 1110fb7d9267SDarrick J. Wong /* 1111fb7d9267SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 1112fb7d9267SDarrick J. Wong * record for our insertion point. This will also give us the record for 1113fb7d9267SDarrick J. Wong * start block contiguity tests. 1114fb7d9267SDarrick J. Wong */ 11155b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i); 1116fb7d9267SDarrick J. Wong if (error) 1117fb7d9267SDarrick J. Wong goto done; 1118f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1119f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1120f9e03706SDarrick J. Wong goto done; 1121f9e03706SDarrick J. Wong } 1122fb7d9267SDarrick J. Wong 1123fb7d9267SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 112450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, PREV.rm_startblock, 1125fb7d9267SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 1126fb7d9267SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 1127fb7d9267SDarrick J. Wong 1128fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 1129fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 1130fb7d9267SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 1131fb7d9267SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 1132fb7d9267SDarrick J. Wong 1133fb7d9267SDarrick J. Wong /* 1134fb7d9267SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 1135fb7d9267SDarrick J. Wong * extent is being replaced by a newext allocation. 1136fb7d9267SDarrick J. Wong */ 1137fb7d9267SDarrick J. Wong if (PREV.rm_offset == offset) 1138fb7d9267SDarrick J. Wong state |= RMAP_LEFT_FILLING; 1139fb7d9267SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 1140fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 1141fb7d9267SDarrick J. Wong 1142fb7d9267SDarrick J. Wong /* 1143fb7d9267SDarrick J. Wong * Decrement the cursor to see if we have a left-adjacent record to our 1144fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1145fb7d9267SDarrick J. Wong * contiguity tests. 1146fb7d9267SDarrick J. Wong */ 1147fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1148fb7d9267SDarrick J. Wong if (error) 1149fb7d9267SDarrick J. Wong goto done; 1150fb7d9267SDarrick J. Wong if (i) { 1151fb7d9267SDarrick J. Wong state |= RMAP_LEFT_VALID; 1152fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &LEFT, &i); 1153fb7d9267SDarrick J. Wong if (error) 1154fb7d9267SDarrick J. Wong goto done; 1155f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1156f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1157f9e03706SDarrick J. Wong goto done; 1158f9e03706SDarrick J. Wong } 1159f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1160f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount > 1161f9e03706SDarrick J. Wong bno)) { 1162f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1163f9e03706SDarrick J. Wong goto done; 1164f9e03706SDarrick J. Wong } 1165fb7d9267SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 116650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, LEFT.rm_startblock, 1167fb7d9267SDarrick J. Wong LEFT.rm_blockcount, LEFT.rm_owner, 1168fb7d9267SDarrick J. Wong LEFT.rm_offset, LEFT.rm_flags); 1169fb7d9267SDarrick J. Wong if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && 1170fb7d9267SDarrick J. Wong LEFT.rm_offset + LEFT.rm_blockcount == offset && 1171fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&LEFT, owner, newext)) 1172fb7d9267SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 1173fb7d9267SDarrick J. Wong } 1174fb7d9267SDarrick J. Wong 1175fb7d9267SDarrick J. Wong /* 1176fb7d9267SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 1177fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1178fb7d9267SDarrick J. Wong * contiguity tests. 1179fb7d9267SDarrick J. Wong */ 1180fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1181fb7d9267SDarrick J. Wong if (error) 1182fb7d9267SDarrick J. Wong goto done; 1183f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1184f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1185f9e03706SDarrick J. Wong goto done; 1186f9e03706SDarrick J. Wong } 1187fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1188fb7d9267SDarrick J. Wong if (error) 1189fb7d9267SDarrick J. Wong goto done; 1190fb7d9267SDarrick J. Wong if (i) { 1191fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_VALID; 1192fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 1193fb7d9267SDarrick J. Wong if (error) 1194fb7d9267SDarrick J. Wong goto done; 1195f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1196f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1197f9e03706SDarrick J. Wong goto done; 1198f9e03706SDarrick J. Wong } 1199f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { 1200f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1201f9e03706SDarrick J. Wong goto done; 1202f9e03706SDarrick J. Wong } 1203fb7d9267SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 120450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock, 1205fb7d9267SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 1206fb7d9267SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 1207fb7d9267SDarrick J. Wong if (bno + len == RIGHT.rm_startblock && 1208fb7d9267SDarrick J. Wong offset + len == RIGHT.rm_offset && 1209fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 1210fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 1211fb7d9267SDarrick J. Wong } 1212fb7d9267SDarrick J. Wong 1213fb7d9267SDarrick J. Wong /* check that left + prev + right is not too long */ 1214fb7d9267SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1215fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 1216fb7d9267SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1217fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 1218fb7d9267SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 1219fb7d9267SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 1220fb7d9267SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 1221fb7d9267SDarrick J. Wong 122250f02fe3SDave Chinner trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state, 1223fb7d9267SDarrick J. Wong _RET_IP_); 1224fb7d9267SDarrick J. Wong 1225fb7d9267SDarrick J. Wong /* reset the cursor back to PREV */ 12265b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i); 1227fb7d9267SDarrick J. Wong if (error) 1228fb7d9267SDarrick J. Wong goto done; 1229f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1230f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1231f9e03706SDarrick J. Wong goto done; 1232f9e03706SDarrick J. Wong } 1233fb7d9267SDarrick J. Wong 1234fb7d9267SDarrick J. Wong /* 1235fb7d9267SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 1236fb7d9267SDarrick J. Wong */ 1237fb7d9267SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1238fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 1239fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1240fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1241fb7d9267SDarrick J. Wong /* 1242fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1243fb7d9267SDarrick J. Wong * The left and right neighbors are both contiguous with new. 1244fb7d9267SDarrick J. Wong */ 1245fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1246fb7d9267SDarrick J. Wong if (error) 1247fb7d9267SDarrick J. Wong goto done; 1248f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1249f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1250f9e03706SDarrick J. Wong goto done; 1251f9e03706SDarrick J. Wong } 125250f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1253fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1254fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1255fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1256fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1257fb7d9267SDarrick J. Wong if (error) 1258fb7d9267SDarrick J. Wong goto done; 1259f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1260f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1261f9e03706SDarrick J. Wong goto done; 1262f9e03706SDarrick J. Wong } 1263fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1264fb7d9267SDarrick J. Wong if (error) 1265fb7d9267SDarrick J. Wong goto done; 1266f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1267f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1268f9e03706SDarrick J. Wong goto done; 1269f9e03706SDarrick J. Wong } 127050f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1271fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1272fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1273fb7d9267SDarrick J. Wong PREV.rm_flags); 1274fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1275fb7d9267SDarrick J. Wong if (error) 1276fb7d9267SDarrick J. Wong goto done; 1277f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1278f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1279f9e03706SDarrick J. Wong goto done; 1280f9e03706SDarrick J. Wong } 1281fb7d9267SDarrick J. Wong error = xfs_btree_decrement(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 } 1288fb7d9267SDarrick J. Wong NEW = LEFT; 1289fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 1290fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1291fb7d9267SDarrick J. Wong if (error) 1292fb7d9267SDarrick J. Wong goto done; 1293fb7d9267SDarrick J. Wong break; 1294fb7d9267SDarrick J. Wong 1295fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1296fb7d9267SDarrick J. Wong /* 1297fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1298fb7d9267SDarrick J. Wong * The left neighbor is contiguous, the right is not. 1299fb7d9267SDarrick J. Wong */ 130050f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1301fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1302fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1303fb7d9267SDarrick J. Wong PREV.rm_flags); 1304fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1305fb7d9267SDarrick J. Wong if (error) 1306fb7d9267SDarrick J. Wong goto done; 1307f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1308f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1309f9e03706SDarrick J. Wong goto done; 1310f9e03706SDarrick J. Wong } 1311fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1312fb7d9267SDarrick J. Wong if (error) 1313fb7d9267SDarrick J. Wong goto done; 1314f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1315f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1316f9e03706SDarrick J. Wong goto done; 1317f9e03706SDarrick J. Wong } 1318fb7d9267SDarrick J. Wong NEW = LEFT; 1319fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 1320fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1321fb7d9267SDarrick J. Wong if (error) 1322fb7d9267SDarrick J. Wong goto done; 1323fb7d9267SDarrick J. Wong break; 1324fb7d9267SDarrick J. Wong 1325fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1326fb7d9267SDarrick J. Wong /* 1327fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1328fb7d9267SDarrick J. Wong * The right neighbor is contiguous, the left is not. 1329fb7d9267SDarrick J. Wong */ 1330fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1331fb7d9267SDarrick J. Wong if (error) 1332fb7d9267SDarrick J. Wong goto done; 1333f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1334f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1335f9e03706SDarrick J. Wong goto done; 1336f9e03706SDarrick J. Wong } 133750f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno, 1338fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1339fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1340fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1341fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1342fb7d9267SDarrick J. Wong if (error) 1343fb7d9267SDarrick J. Wong goto done; 1344f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1345f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1346f9e03706SDarrick J. Wong goto done; 1347f9e03706SDarrick J. Wong } 1348fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1349fb7d9267SDarrick J. Wong if (error) 1350fb7d9267SDarrick J. Wong goto done; 1351f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1352f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1353f9e03706SDarrick J. Wong goto done; 1354f9e03706SDarrick J. Wong } 1355fb7d9267SDarrick J. Wong NEW = PREV; 1356fb7d9267SDarrick J. Wong NEW.rm_blockcount = len + RIGHT.rm_blockcount; 1357fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1358fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1359fb7d9267SDarrick J. Wong if (error) 1360fb7d9267SDarrick J. Wong goto done; 1361fb7d9267SDarrick J. Wong break; 1362fb7d9267SDarrick J. Wong 1363fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1364fb7d9267SDarrick J. Wong /* 1365fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1366fb7d9267SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 1367fb7d9267SDarrick J. Wong * the new one. 1368fb7d9267SDarrick J. Wong */ 1369fb7d9267SDarrick J. Wong NEW = PREV; 1370fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1371fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1372fb7d9267SDarrick J. Wong if (error) 1373fb7d9267SDarrick J. Wong goto done; 1374fb7d9267SDarrick J. Wong break; 1375fb7d9267SDarrick J. Wong 1376fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1377fb7d9267SDarrick J. Wong /* 1378fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1379fb7d9267SDarrick J. Wong * The left neighbor is contiguous. 1380fb7d9267SDarrick J. Wong */ 1381fb7d9267SDarrick J. Wong NEW = PREV; 1382fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1383fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 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_decrement(cur, 0, &i); 1389fb7d9267SDarrick J. Wong if (error) 1390fb7d9267SDarrick J. Wong goto done; 1391fb7d9267SDarrick J. Wong NEW = LEFT; 1392fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1393fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1394fb7d9267SDarrick J. Wong if (error) 1395fb7d9267SDarrick J. Wong goto done; 1396fb7d9267SDarrick J. Wong break; 1397fb7d9267SDarrick J. Wong 1398fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING: 1399fb7d9267SDarrick J. Wong /* 1400fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1401fb7d9267SDarrick J. Wong * The left neighbor is not contiguous. 1402fb7d9267SDarrick J. Wong */ 1403fb7d9267SDarrick J. Wong NEW = PREV; 1404fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1405fb7d9267SDarrick J. Wong NEW.rm_offset += len; 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 NEW.rm_startblock = bno; 1411fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1412fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1413fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1414fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1415fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 141650f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, 1417fb7d9267SDarrick J. Wong len, owner, offset, newext); 1418fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1419fb7d9267SDarrick J. Wong if (error) 1420fb7d9267SDarrick J. Wong goto done; 1421f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1422f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1423f9e03706SDarrick J. Wong goto done; 1424f9e03706SDarrick J. Wong } 1425fb7d9267SDarrick J. Wong break; 1426fb7d9267SDarrick J. Wong 1427fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1428fb7d9267SDarrick J. Wong /* 1429fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1430fb7d9267SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 1431fb7d9267SDarrick J. Wong */ 1432fb7d9267SDarrick J. Wong NEW = PREV; 1433fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1434fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1435fb7d9267SDarrick J. Wong if (error) 1436fb7d9267SDarrick J. Wong goto done; 1437fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1438fb7d9267SDarrick J. Wong if (error) 1439fb7d9267SDarrick J. Wong goto done; 1440fb7d9267SDarrick J. Wong NEW = RIGHT; 1441fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1442fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1443fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1444fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1445fb7d9267SDarrick J. Wong if (error) 1446fb7d9267SDarrick J. Wong goto done; 1447fb7d9267SDarrick J. Wong break; 1448fb7d9267SDarrick J. Wong 1449fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING: 1450fb7d9267SDarrick J. Wong /* 1451fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1452fb7d9267SDarrick J. Wong * The right neighbor is not contiguous. 1453fb7d9267SDarrick J. Wong */ 1454fb7d9267SDarrick J. Wong NEW = PREV; 1455fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1456fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1457fb7d9267SDarrick J. Wong if (error) 1458fb7d9267SDarrick J. Wong goto done; 1459fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1460fb7d9267SDarrick J. Wong oldext, &i); 1461fb7d9267SDarrick J. Wong if (error) 1462fb7d9267SDarrick J. Wong goto done; 1463f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) { 1464f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1465f9e03706SDarrick J. Wong goto done; 1466f9e03706SDarrick J. Wong } 1467fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1468fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1469fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1470fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1471fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1472fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 147350f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, 1474fb7d9267SDarrick J. Wong len, owner, offset, newext); 1475fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1476fb7d9267SDarrick J. Wong if (error) 1477fb7d9267SDarrick J. Wong goto done; 1478f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1479f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1480f9e03706SDarrick J. Wong goto done; 1481f9e03706SDarrick J. Wong } 1482fb7d9267SDarrick J. Wong break; 1483fb7d9267SDarrick J. Wong 1484fb7d9267SDarrick J. Wong case 0: 1485fb7d9267SDarrick J. Wong /* 1486fb7d9267SDarrick J. Wong * Setting the middle part of a previous oldext extent to 1487fb7d9267SDarrick J. Wong * newext. Contiguity is impossible here. 1488fb7d9267SDarrick J. Wong * One extent becomes three extents. 1489fb7d9267SDarrick J. Wong */ 1490fb7d9267SDarrick J. Wong /* new right extent - oldext */ 1491fb7d9267SDarrick J. Wong NEW.rm_startblock = bno + len; 1492fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1493fb7d9267SDarrick J. Wong NEW.rm_offset = new_endoff; 1494fb7d9267SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 1495fb7d9267SDarrick J. Wong new_endoff; 1496fb7d9267SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 1497fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1498fb7d9267SDarrick J. Wong if (error) 1499fb7d9267SDarrick J. Wong goto done; 1500fb7d9267SDarrick J. Wong /* new left extent - oldext */ 1501fb7d9267SDarrick J. Wong NEW = PREV; 1502fb7d9267SDarrick J. Wong NEW.rm_blockcount = offset - PREV.rm_offset; 1503fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 150450f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, 1505fb7d9267SDarrick J. Wong NEW.rm_startblock, NEW.rm_blockcount, 1506fb7d9267SDarrick J. Wong NEW.rm_owner, NEW.rm_offset, 1507fb7d9267SDarrick J. Wong NEW.rm_flags); 1508fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1509fb7d9267SDarrick J. Wong if (error) 1510fb7d9267SDarrick J. Wong goto done; 1511f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1512f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1513f9e03706SDarrick J. Wong goto done; 1514f9e03706SDarrick J. Wong } 1515fb7d9267SDarrick J. Wong /* 1516fb7d9267SDarrick J. Wong * Reset the cursor to the position of the new extent 1517fb7d9267SDarrick J. Wong * we are about to insert as we can't trust it after 1518fb7d9267SDarrick J. Wong * the previous insert. 1519fb7d9267SDarrick J. Wong */ 1520fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1521fb7d9267SDarrick J. Wong oldext, &i); 1522fb7d9267SDarrick J. Wong if (error) 1523fb7d9267SDarrick J. Wong goto done; 1524f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) { 1525f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1526f9e03706SDarrick J. Wong goto done; 1527f9e03706SDarrick J. Wong } 1528fb7d9267SDarrick J. Wong /* new middle extent - newext */ 1529fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; 1530fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags |= newext; 153150f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len, 1532fb7d9267SDarrick J. Wong owner, offset, newext); 1533fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1534fb7d9267SDarrick J. Wong if (error) 1535fb7d9267SDarrick J. Wong goto done; 1536f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1537f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1538f9e03706SDarrick J. Wong goto done; 1539f9e03706SDarrick J. Wong } 1540fb7d9267SDarrick J. Wong break; 1541fb7d9267SDarrick J. Wong 1542fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1543fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1544fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 1545fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1546fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1547fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG: 1548fb7d9267SDarrick J. Wong case RMAP_RIGHT_CONTIG: 1549fb7d9267SDarrick J. Wong /* 1550fb7d9267SDarrick J. Wong * These cases are all impossible. 1551fb7d9267SDarrick J. Wong */ 1552fb7d9267SDarrick J. Wong ASSERT(0); 1553fb7d9267SDarrick J. Wong } 1554fb7d9267SDarrick J. Wong 155550f02fe3SDave Chinner trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 1556fb7d9267SDarrick J. Wong unwritten, oinfo); 1557fb7d9267SDarrick J. Wong done: 1558fb7d9267SDarrick J. Wong if (error) 1559fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 156050f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 1561fb7d9267SDarrick J. Wong return error; 1562fb7d9267SDarrick J. Wong } 1563fb7d9267SDarrick J. Wong 15643f165b33SDarrick J. Wong /* 15653f165b33SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. If there is no 15663f165b33SDarrick J. Wong * possibility of overlapping extents, delegate to the simpler convert 15673f165b33SDarrick J. Wong * function. 15683f165b33SDarrick J. Wong */ 15693f165b33SDarrick J. Wong STATIC int 15703f165b33SDarrick J. Wong xfs_rmap_convert_shared( 15713f165b33SDarrick J. Wong struct xfs_btree_cur *cur, 15723f165b33SDarrick J. Wong xfs_agblock_t bno, 15733f165b33SDarrick J. Wong xfs_extlen_t len, 15743f165b33SDarrick J. Wong bool unwritten, 157566e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 15763f165b33SDarrick J. Wong { 15773f165b33SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 15783f165b33SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 157966e3237eSDarrick J. Wong /* left is 0, right is 1, */ 158066e3237eSDarrick J. Wong /* prev is 2, new is 3 */ 15813f165b33SDarrick J. Wong uint64_t owner; 15823f165b33SDarrick J. Wong uint64_t offset; 15833f165b33SDarrick J. Wong uint64_t new_endoff; 15843f165b33SDarrick J. Wong unsigned int oldext; 15853f165b33SDarrick J. Wong unsigned int newext; 15863f165b33SDarrick J. Wong unsigned int flags = 0; 15873f165b33SDarrick J. Wong int i; 15883f165b33SDarrick J. Wong int state = 0; 15893f165b33SDarrick J. Wong int error; 15903f165b33SDarrick J. Wong 15913f165b33SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 15923f165b33SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 15933f165b33SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 15943f165b33SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 15953f165b33SDarrick J. Wong new_endoff = offset + len; 159650f02fe3SDave Chinner trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len, 15973f165b33SDarrick J. Wong unwritten, oinfo); 15983f165b33SDarrick J. Wong 15993f165b33SDarrick J. Wong /* 16003f165b33SDarrick J. Wong * For the initial lookup, look for and exact match or the left-adjacent 16013f165b33SDarrick J. Wong * record for our insertion point. This will also give us the record for 16023f165b33SDarrick J. Wong * start block contiguity tests. 16033f165b33SDarrick J. Wong */ 1604ea843989SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext, 16053f165b33SDarrick J. Wong &PREV, &i); 160652101dfeSDarrick J. Wong if (error) 160752101dfeSDarrick J. Wong goto done; 1608f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1609f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1610f9e03706SDarrick J. Wong goto done; 1611f9e03706SDarrick J. Wong } 16123f165b33SDarrick J. Wong 16133f165b33SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 16143f165b33SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 16153f165b33SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 16163f165b33SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 16173f165b33SDarrick J. Wong 16183f165b33SDarrick J. Wong /* 16193f165b33SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 16203f165b33SDarrick J. Wong * extent is being replaced by a newext allocation. 16213f165b33SDarrick J. Wong */ 16223f165b33SDarrick J. Wong if (PREV.rm_offset == offset) 16233f165b33SDarrick J. Wong state |= RMAP_LEFT_FILLING; 16243f165b33SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 16253f165b33SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 16263f165b33SDarrick J. Wong 16273f165b33SDarrick J. Wong /* Is there a left record that abuts our range? */ 16283f165b33SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, 16293f165b33SDarrick J. Wong &LEFT, &i); 16303f165b33SDarrick J. Wong if (error) 16313f165b33SDarrick J. Wong goto done; 16323f165b33SDarrick J. Wong if (i) { 16333f165b33SDarrick J. Wong state |= RMAP_LEFT_VALID; 1634f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 1635f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount > 1636f9e03706SDarrick J. Wong bno)) { 1637f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1638f9e03706SDarrick J. Wong goto done; 1639f9e03706SDarrick J. Wong } 16403f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) 16413f165b33SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 16423f165b33SDarrick J. Wong } 16433f165b33SDarrick J. Wong 16443f165b33SDarrick J. Wong /* Is there a right record that abuts our range? */ 16453f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 16463f165b33SDarrick J. Wong newext, &i); 16473f165b33SDarrick J. Wong if (error) 16483f165b33SDarrick J. Wong goto done; 16493f165b33SDarrick J. Wong if (i) { 16503f165b33SDarrick J. Wong state |= RMAP_RIGHT_VALID; 16513f165b33SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 16523f165b33SDarrick J. Wong if (error) 16533f165b33SDarrick J. Wong goto done; 1654f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1655f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1656f9e03706SDarrick J. Wong goto done; 1657f9e03706SDarrick J. Wong } 1658f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { 1659f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1660f9e03706SDarrick J. Wong goto done; 1661f9e03706SDarrick J. Wong } 16623f165b33SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 166350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock, 16643f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 16653f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 16663f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 16673f165b33SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 16683f165b33SDarrick J. Wong } 16693f165b33SDarrick J. Wong 16703f165b33SDarrick J. Wong /* check that left + prev + right is not too long */ 16713f165b33SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16723f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 16733f165b33SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16743f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 16753f165b33SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 16763f165b33SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 16773f165b33SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 16783f165b33SDarrick J. Wong 167950f02fe3SDave Chinner trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state, 16803f165b33SDarrick J. Wong _RET_IP_); 16813f165b33SDarrick J. Wong /* 16823f165b33SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 16833f165b33SDarrick J. Wong */ 16843f165b33SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16853f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 16863f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 16873f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 16883f165b33SDarrick J. Wong /* 16893f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 16903f165b33SDarrick J. Wong * The left and right neighbors are both contiguous with new. 16913f165b33SDarrick J. Wong */ 16923f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 16933f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 16943f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 16953f165b33SDarrick J. Wong if (error) 16963f165b33SDarrick J. Wong goto done; 16973f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 16983f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 16993f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 17003f165b33SDarrick J. Wong if (error) 17013f165b33SDarrick J. Wong goto done; 17023f165b33SDarrick J. Wong NEW = LEFT; 17033f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17043f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17053f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17063f165b33SDarrick J. Wong if (error) 17073f165b33SDarrick J. Wong goto done; 1708f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1709f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1710f9e03706SDarrick J. Wong goto done; 1711f9e03706SDarrick J. Wong } 17123f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 17133f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17143f165b33SDarrick J. Wong if (error) 17153f165b33SDarrick J. Wong goto done; 17163f165b33SDarrick J. Wong break; 17173f165b33SDarrick J. Wong 17183f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 17193f165b33SDarrick J. Wong /* 17203f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 17213f165b33SDarrick J. Wong * The left neighbor is contiguous, the right is not. 17223f165b33SDarrick J. Wong */ 17233f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 17243f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 17253f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 17263f165b33SDarrick J. Wong if (error) 17273f165b33SDarrick J. Wong goto done; 17283f165b33SDarrick J. Wong NEW = LEFT; 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_blockcount += PREV.rm_blockcount; 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_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 17453f165b33SDarrick J. Wong /* 17463f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 17473f165b33SDarrick J. Wong * The right neighbor is contiguous, the left is not. 17483f165b33SDarrick J. Wong */ 17493f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 17503f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 17513f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 17523f165b33SDarrick J. Wong if (error) 17533f165b33SDarrick J. Wong goto done; 17543f165b33SDarrick J. Wong NEW = PREV; 17553f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17563f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17573f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17583f165b33SDarrick J. Wong if (error) 17593f165b33SDarrick J. Wong goto done; 1760f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1761f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1762f9e03706SDarrick J. Wong goto done; 1763f9e03706SDarrick J. Wong } 17643f165b33SDarrick J. Wong NEW.rm_blockcount += RIGHT.rm_blockcount; 17653f165b33SDarrick J. Wong NEW.rm_flags = RIGHT.rm_flags; 17663f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17673f165b33SDarrick J. Wong if (error) 17683f165b33SDarrick J. Wong goto done; 17693f165b33SDarrick J. Wong break; 17703f165b33SDarrick J. Wong 17713f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 17723f165b33SDarrick J. Wong /* 17733f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 17743f165b33SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 17753f165b33SDarrick J. Wong * the new one. 17763f165b33SDarrick J. Wong */ 17773f165b33SDarrick J. Wong NEW = PREV; 17783f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 17793f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 17803f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 17813f165b33SDarrick J. Wong if (error) 17823f165b33SDarrick J. Wong goto done; 1783f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1784f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1785f9e03706SDarrick J. Wong goto done; 1786f9e03706SDarrick J. Wong } 17873f165b33SDarrick J. Wong NEW.rm_flags = newext; 17883f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 17893f165b33SDarrick J. Wong if (error) 17903f165b33SDarrick J. Wong goto done; 17913f165b33SDarrick J. Wong break; 17923f165b33SDarrick J. Wong 17933f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 17943f165b33SDarrick J. Wong /* 17953f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 17963f165b33SDarrick J. Wong * The left neighbor is contiguous. 17973f165b33SDarrick J. Wong */ 17983f165b33SDarrick J. Wong NEW = PREV; 17993f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 18003f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18013f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18023f165b33SDarrick J. Wong if (error) 18033f165b33SDarrick J. Wong goto done; 18043f165b33SDarrick J. Wong NEW.rm_offset += len; 18053f165b33SDarrick J. Wong NEW.rm_startblock += len; 18063f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 18073f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18083f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18093f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18103f165b33SDarrick J. Wong if (error) 18113f165b33SDarrick J. Wong goto done; 18123f165b33SDarrick J. Wong NEW = LEFT; 18133f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18143f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18153f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18163f165b33SDarrick J. Wong if (error) 18173f165b33SDarrick J. Wong goto done; 1818f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1819f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1820f9e03706SDarrick J. Wong goto done; 1821f9e03706SDarrick J. Wong } 18223f165b33SDarrick J. Wong NEW.rm_blockcount += len; 18233f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18243f165b33SDarrick J. Wong if (error) 18253f165b33SDarrick J. Wong goto done; 18263f165b33SDarrick J. Wong break; 18273f165b33SDarrick J. Wong 18283f165b33SDarrick J. Wong case RMAP_LEFT_FILLING: 18293f165b33SDarrick J. Wong /* 18303f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 18313f165b33SDarrick J. Wong * The left neighbor is not contiguous. 18323f165b33SDarrick J. Wong */ 18333f165b33SDarrick J. Wong NEW = PREV; 18343f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 18353f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18363f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18373f165b33SDarrick J. Wong if (error) 18383f165b33SDarrick J. Wong goto done; 18393f165b33SDarrick J. Wong NEW.rm_offset += len; 18403f165b33SDarrick J. Wong NEW.rm_startblock += len; 18413f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 18423f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18433f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18443f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18453f165b33SDarrick J. Wong if (error) 18463f165b33SDarrick J. Wong goto done; 18473f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 18483f165b33SDarrick J. Wong if (error) 18493f165b33SDarrick J. Wong goto done; 18503f165b33SDarrick J. Wong break; 18513f165b33SDarrick J. Wong 18523f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 18533f165b33SDarrick J. Wong /* 18543f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 18553f165b33SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 18563f165b33SDarrick J. Wong */ 18573f165b33SDarrick J. Wong NEW = PREV; 18583f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18593f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18603f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18613f165b33SDarrick J. Wong if (error) 18623f165b33SDarrick J. Wong goto done; 1863f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1864f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1865f9e03706SDarrick J. Wong goto done; 1866f9e03706SDarrick J. Wong } 18673f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 18683f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 18693f165b33SDarrick J. Wong if (error) 18703f165b33SDarrick J. Wong goto done; 18713f165b33SDarrick J. Wong NEW = RIGHT; 18723f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 18733f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18743f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18753f165b33SDarrick J. Wong if (error) 18763f165b33SDarrick J. Wong goto done; 18773f165b33SDarrick J. Wong NEW.rm_offset = offset; 18783f165b33SDarrick J. Wong NEW.rm_startblock = bno; 18793f165b33SDarrick J. Wong NEW.rm_blockcount += len; 18803f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 18813f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18823f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 18833f165b33SDarrick J. Wong if (error) 18843f165b33SDarrick J. Wong goto done; 18853f165b33SDarrick J. Wong break; 18863f165b33SDarrick J. Wong 18873f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING: 18883f165b33SDarrick J. Wong /* 18893f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 18903f165b33SDarrick J. Wong * The right neighbor is not contiguous. 18913f165b33SDarrick J. Wong */ 18923f165b33SDarrick J. Wong NEW = PREV; 18933f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 18943f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 18953f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 18963f165b33SDarrick J. Wong if (error) 18973f165b33SDarrick J. Wong goto done; 1898f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1899f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1900f9e03706SDarrick J. Wong goto done; 1901f9e03706SDarrick J. Wong } 19023f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 19033f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 19043f165b33SDarrick J. Wong if (error) 19053f165b33SDarrick J. Wong goto done; 19063f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 19073f165b33SDarrick J. Wong if (error) 19083f165b33SDarrick J. Wong goto done; 19093f165b33SDarrick J. Wong break; 19103f165b33SDarrick J. Wong 19113f165b33SDarrick J. Wong case 0: 19123f165b33SDarrick J. Wong /* 19133f165b33SDarrick J. Wong * Setting the middle part of a previous oldext extent to 19143f165b33SDarrick J. Wong * newext. Contiguity is impossible here. 19153f165b33SDarrick J. Wong * One extent becomes three extents. 19163f165b33SDarrick J. Wong */ 19173f165b33SDarrick J. Wong /* new right extent - oldext */ 19183f165b33SDarrick J. Wong NEW.rm_startblock = bno + len; 19193f165b33SDarrick J. Wong NEW.rm_owner = owner; 19203f165b33SDarrick J. Wong NEW.rm_offset = new_endoff; 19213f165b33SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 19223f165b33SDarrick J. Wong new_endoff; 19233f165b33SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 19243f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 19253f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 19263f165b33SDarrick J. Wong NEW.rm_flags); 19273f165b33SDarrick J. Wong if (error) 19283f165b33SDarrick J. Wong goto done; 19293f165b33SDarrick J. Wong /* new left extent - oldext */ 19303f165b33SDarrick J. Wong NEW = PREV; 19313f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 19323f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 19333f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 19343f165b33SDarrick J. Wong if (error) 19353f165b33SDarrick J. Wong goto done; 1936f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 1937f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 1938f9e03706SDarrick J. Wong goto done; 1939f9e03706SDarrick J. Wong } 19403f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 19413f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 19423f165b33SDarrick J. Wong if (error) 19433f165b33SDarrick J. Wong goto done; 19443f165b33SDarrick J. Wong /* new middle extent - newext */ 19453f165b33SDarrick J. Wong NEW.rm_startblock = bno; 19463f165b33SDarrick J. Wong NEW.rm_blockcount = len; 19473f165b33SDarrick J. Wong NEW.rm_owner = owner; 19483f165b33SDarrick J. Wong NEW.rm_offset = offset; 19493f165b33SDarrick J. Wong NEW.rm_flags = newext; 19503f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 19513f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 19523f165b33SDarrick J. Wong NEW.rm_flags); 19533f165b33SDarrick J. Wong if (error) 19543f165b33SDarrick J. Wong goto done; 19553f165b33SDarrick J. Wong break; 19563f165b33SDarrick J. Wong 19573f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 19583f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 19593f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 19603f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 19613f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 19623f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG: 19633f165b33SDarrick J. Wong case RMAP_RIGHT_CONTIG: 19643f165b33SDarrick J. Wong /* 19653f165b33SDarrick J. Wong * These cases are all impossible. 19663f165b33SDarrick J. Wong */ 19673f165b33SDarrick J. Wong ASSERT(0); 19683f165b33SDarrick J. Wong } 19693f165b33SDarrick J. Wong 197050f02fe3SDave Chinner trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 19713f165b33SDarrick J. Wong unwritten, oinfo); 19723f165b33SDarrick J. Wong done: 19733f165b33SDarrick J. Wong if (error) 19743f165b33SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 197550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 19763f165b33SDarrick J. Wong return error; 19773f165b33SDarrick J. Wong } 19783f165b33SDarrick J. Wong 1979fb7d9267SDarrick J. Wong #undef NEW 1980fb7d9267SDarrick J. Wong #undef LEFT 1981fb7d9267SDarrick J. Wong #undef RIGHT 1982fb7d9267SDarrick J. Wong #undef PREV 1983fb7d9267SDarrick J. Wong 1984ceeb9c83SDarrick J. Wong /* 1985ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and unmap it. For rmap extent types that 1986ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1987ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1988ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1989ceeb9c83SDarrick J. Wong * 1990ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1991ceeb9c83SDarrick J. Wong * so we can call the regular _free function. 1992ceeb9c83SDarrick J. Wong */ 1993ceeb9c83SDarrick J. Wong STATIC int 1994ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared( 1995ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1996ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1997ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1998ceeb9c83SDarrick J. Wong bool unwritten, 199966e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 2000ceeb9c83SDarrick J. Wong { 2001ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 2002ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 2003ceeb9c83SDarrick J. Wong uint64_t ltoff; 2004ceeb9c83SDarrick J. Wong int error = 0; 2005ceeb9c83SDarrick J. Wong int i; 2006ceeb9c83SDarrick J. Wong uint64_t owner; 2007ceeb9c83SDarrick J. Wong uint64_t offset; 2008ceeb9c83SDarrick J. Wong unsigned int flags; 2009ceeb9c83SDarrick J. Wong 2010ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2011ceeb9c83SDarrick J. Wong if (unwritten) 2012ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 201350f02fe3SDave Chinner trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len, 2014ceeb9c83SDarrick J. Wong unwritten, oinfo); 2015ceeb9c83SDarrick J. Wong 2016ceeb9c83SDarrick J. Wong /* 2017ceeb9c83SDarrick J. Wong * We should always have a left record because there's a static record 2018ceeb9c83SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 2019ceeb9c83SDarrick J. Wong * will not ever be removed from the tree. 2020ceeb9c83SDarrick J. Wong */ 2021ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 2022ceeb9c83SDarrick J. Wong <rec, &i); 2023ceeb9c83SDarrick J. Wong if (error) 2024ceeb9c83SDarrick J. Wong goto out_error; 2025f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2026f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2027f9e03706SDarrick J. Wong goto out_error; 2028f9e03706SDarrick J. Wong } 2029ceeb9c83SDarrick J. Wong ltoff = ltrec.rm_offset; 2030ceeb9c83SDarrick J. Wong 2031ceeb9c83SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 2032f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 2033f9e03706SDarrick J. Wong ltrec.rm_startblock > bno || 2034f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount < 2035f9e03706SDarrick J. Wong bno + len)) { 2036f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2037f9e03706SDarrick J. Wong goto out_error; 2038f9e03706SDarrick J. Wong } 2039ceeb9c83SDarrick J. Wong 2040ceeb9c83SDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 2041f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) { 2042f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2043f9e03706SDarrick J. Wong goto out_error; 2044f9e03706SDarrick J. Wong } 2045ceeb9c83SDarrick J. Wong 2046ceeb9c83SDarrick J. Wong /* Make sure the unwritten flag matches. */ 2047f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, 2048f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) != 2049f9e03706SDarrick J. Wong (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) { 2050f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2051f9e03706SDarrick J. Wong goto out_error; 2052f9e03706SDarrick J. Wong } 2053ceeb9c83SDarrick J. Wong 2054ceeb9c83SDarrick J. Wong /* Check the offset. */ 2055f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) { 2056f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2057f9e03706SDarrick J. Wong goto out_error; 2058f9e03706SDarrick J. Wong } 2059f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) { 2060f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2061f9e03706SDarrick J. Wong goto out_error; 2062f9e03706SDarrick J. Wong } 2063ceeb9c83SDarrick J. Wong 2064ceeb9c83SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 2065ceeb9c83SDarrick J. Wong /* Exact match, simply remove the record from rmap tree. */ 2066ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 2067ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2068ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2069ceeb9c83SDarrick J. Wong if (error) 2070ceeb9c83SDarrick J. Wong goto out_error; 2071ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 2072ceeb9c83SDarrick J. Wong /* 2073ceeb9c83SDarrick J. Wong * Overlap left hand side of extent: move the start, trim the 2074ceeb9c83SDarrick J. Wong * length and update the current record. 2075ceeb9c83SDarrick J. Wong * 2076ceeb9c83SDarrick J. Wong * ltbno ltlen 2077ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2078ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2079ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 2080ceeb9c83SDarrick J. Wong * bno len 2081ceeb9c83SDarrick J. Wong */ 2082ceeb9c83SDarrick J. Wong 2083ceeb9c83SDarrick J. Wong /* Delete prev rmap. */ 2084ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 2085ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2086ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2087ceeb9c83SDarrick J. Wong if (error) 2088ceeb9c83SDarrick J. Wong goto out_error; 2089ceeb9c83SDarrick J. Wong 2090ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset. */ 2091ceeb9c83SDarrick J. Wong ltrec.rm_startblock += len; 2092ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 2093ceeb9c83SDarrick J. Wong ltrec.rm_offset += len; 2094ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, ltrec.rm_startblock, 2095ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2096ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 2097ceeb9c83SDarrick J. Wong if (error) 2098ceeb9c83SDarrick J. Wong goto out_error; 2099ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 2100ceeb9c83SDarrick J. Wong /* 2101ceeb9c83SDarrick J. Wong * Overlap right hand side of extent: trim the length and 2102ceeb9c83SDarrick J. Wong * update the current record. 2103ceeb9c83SDarrick J. Wong * 2104ceeb9c83SDarrick J. Wong * ltbno ltlen 2105ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2106ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2107ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 2108ceeb9c83SDarrick J. Wong * bno len 2109ceeb9c83SDarrick J. Wong */ 2110ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2111ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2112ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2113ceeb9c83SDarrick J. Wong if (error) 2114ceeb9c83SDarrick J. Wong goto out_error; 2115f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2116f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2117f9e03706SDarrick J. Wong goto out_error; 2118f9e03706SDarrick J. Wong } 2119ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 2120ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2121ceeb9c83SDarrick J. Wong if (error) 2122ceeb9c83SDarrick J. Wong goto out_error; 2123ceeb9c83SDarrick J. Wong } else { 2124ceeb9c83SDarrick J. Wong /* 2125ceeb9c83SDarrick J. Wong * Overlap middle of extent: trim the length of the existing 2126ceeb9c83SDarrick J. Wong * record to the length of the new left-extent size, increment 2127ceeb9c83SDarrick J. Wong * the insertion position so we can insert a new record 2128ceeb9c83SDarrick J. Wong * containing the remaining right-extent space. 2129ceeb9c83SDarrick J. Wong * 2130ceeb9c83SDarrick J. Wong * ltbno ltlen 2131ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 2132ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 2133ceeb9c83SDarrick J. Wong * Result: |rrrrr| |rrrr| 2134ceeb9c83SDarrick J. Wong * bno len 2135ceeb9c83SDarrick J. Wong */ 2136ceeb9c83SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 2137ceeb9c83SDarrick J. Wong 2138ceeb9c83SDarrick J. Wong /* Shrink the left side of the rmap */ 2139ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2140ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2141ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2142ceeb9c83SDarrick J. Wong if (error) 2143ceeb9c83SDarrick J. Wong goto out_error; 2144f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2145f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2146f9e03706SDarrick J. Wong goto out_error; 2147f9e03706SDarrick J. Wong } 2148ceeb9c83SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 2149ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2150ceeb9c83SDarrick J. Wong if (error) 2151ceeb9c83SDarrick J. Wong goto out_error; 2152ceeb9c83SDarrick J. Wong 2153ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset */ 2154ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno + len, 2155ceeb9c83SDarrick J. Wong orig_len - len - ltrec.rm_blockcount, 2156ceeb9c83SDarrick J. Wong ltrec.rm_owner, offset + len, 2157ceeb9c83SDarrick J. Wong ltrec.rm_flags); 2158ceeb9c83SDarrick J. Wong if (error) 2159ceeb9c83SDarrick J. Wong goto out_error; 2160ceeb9c83SDarrick J. Wong } 2161ceeb9c83SDarrick J. Wong 216250f02fe3SDave Chinner trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 2163ceeb9c83SDarrick J. Wong unwritten, oinfo); 2164ceeb9c83SDarrick J. Wong out_error: 2165ceeb9c83SDarrick J. Wong if (error) 2166ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_error(cur->bc_mp, 216750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 2168ceeb9c83SDarrick J. Wong return error; 2169ceeb9c83SDarrick J. Wong } 2170ceeb9c83SDarrick J. Wong 2171ceeb9c83SDarrick J. Wong /* 2172ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and map it. For rmap extent types that 2173ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 2174ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 2175ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 2176ceeb9c83SDarrick J. Wong * 2177ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 2178ceeb9c83SDarrick J. Wong * so we can call the regular _alloc function. 2179ceeb9c83SDarrick J. Wong */ 2180ceeb9c83SDarrick J. Wong STATIC int 2181ceeb9c83SDarrick J. Wong xfs_rmap_map_shared( 2182ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 2183ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 2184ceeb9c83SDarrick J. Wong xfs_extlen_t len, 2185ceeb9c83SDarrick J. Wong bool unwritten, 218666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo) 2187ceeb9c83SDarrick J. Wong { 2188ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 2189ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 2190ceeb9c83SDarrick J. Wong struct xfs_rmap_irec gtrec; 2191ceeb9c83SDarrick J. Wong int have_gt; 2192ceeb9c83SDarrick J. Wong int have_lt; 2193ceeb9c83SDarrick J. Wong int error = 0; 2194ceeb9c83SDarrick J. Wong int i; 2195ceeb9c83SDarrick J. Wong uint64_t owner; 2196ceeb9c83SDarrick J. Wong uint64_t offset; 2197ceeb9c83SDarrick J. Wong unsigned int flags = 0; 2198ceeb9c83SDarrick J. Wong 2199ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2200ceeb9c83SDarrick J. Wong if (unwritten) 2201ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 220250f02fe3SDave Chinner trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len, 2203ceeb9c83SDarrick J. Wong unwritten, oinfo); 2204ceeb9c83SDarrick J. Wong 2205ceeb9c83SDarrick J. Wong /* Is there a left record that abuts our range? */ 2206ceeb9c83SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, 2207ceeb9c83SDarrick J. Wong <rec, &have_lt); 2208ceeb9c83SDarrick J. Wong if (error) 2209ceeb9c83SDarrick J. Wong goto out_error; 2210ceeb9c83SDarrick J. Wong if (have_lt && 2211ceeb9c83SDarrick J. Wong !xfs_rmap_is_mergeable(<rec, owner, flags)) 2212ceeb9c83SDarrick J. Wong have_lt = 0; 2213ceeb9c83SDarrick J. Wong 2214ceeb9c83SDarrick J. Wong /* Is there a right record that abuts our range? */ 2215ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 2216ceeb9c83SDarrick J. Wong flags, &have_gt); 2217ceeb9c83SDarrick J. Wong if (error) 2218ceeb9c83SDarrick J. Wong goto out_error; 2219ceeb9c83SDarrick J. Wong if (have_gt) { 2220ceeb9c83SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 2221ceeb9c83SDarrick J. Wong if (error) 2222ceeb9c83SDarrick J. Wong goto out_error; 2223f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) { 2224f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2225f9e03706SDarrick J. Wong goto out_error; 2226f9e03706SDarrick J. Wong } 2227ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 222850f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, gtrec.rm_startblock, 2229ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2230ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2231ceeb9c83SDarrick J. Wong 2232ceeb9c83SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 2233ceeb9c83SDarrick J. Wong have_gt = 0; 2234ceeb9c83SDarrick J. Wong } 2235ceeb9c83SDarrick J. Wong 2236ceeb9c83SDarrick J. Wong if (have_lt && 2237ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 2238ceeb9c83SDarrick J. Wong ltrec.rm_offset + ltrec.rm_blockcount == offset) { 2239ceeb9c83SDarrick J. Wong /* 2240ceeb9c83SDarrick J. Wong * Left edge contiguous, merge into left record. 2241ceeb9c83SDarrick J. Wong * 2242ceeb9c83SDarrick J. Wong * ltbno ltlen 2243ceeb9c83SDarrick J. Wong * orig: |ooooooooo| 2244ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2245ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 2246ceeb9c83SDarrick J. Wong * bno len 2247ceeb9c83SDarrick J. Wong */ 2248ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += len; 2249ceeb9c83SDarrick J. Wong if (have_gt && 2250ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 2251ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 2252ceeb9c83SDarrick J. Wong /* 2253ceeb9c83SDarrick J. Wong * Right edge also contiguous, delete right record 2254ceeb9c83SDarrick J. Wong * and merge into left record. 2255ceeb9c83SDarrick J. Wong * 2256ceeb9c83SDarrick J. Wong * ltbno ltlen gtbno gtlen 2257ceeb9c83SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 2258ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2259ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 2260ceeb9c83SDarrick J. Wong */ 2261ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 2262ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2263ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2264ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2265ceeb9c83SDarrick J. Wong if (error) 2266ceeb9c83SDarrick J. Wong goto out_error; 2267ceeb9c83SDarrick J. Wong } 2268ceeb9c83SDarrick J. Wong 2269ceeb9c83SDarrick J. Wong /* Point the cursor back to the left record and update. */ 2270ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 2271ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 2272ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 2273ceeb9c83SDarrick J. Wong if (error) 2274ceeb9c83SDarrick J. Wong goto out_error; 2275f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) { 2276f9e03706SDarrick J. Wong error = -EFSCORRUPTED; 2277f9e03706SDarrick J. Wong goto out_error; 2278f9e03706SDarrick J. Wong } 2279ceeb9c83SDarrick J. Wong 2280ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 2281ceeb9c83SDarrick J. Wong if (error) 2282ceeb9c83SDarrick J. Wong goto out_error; 2283ceeb9c83SDarrick J. Wong } else if (have_gt && 2284ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 2285ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 2286ceeb9c83SDarrick J. Wong /* 2287ceeb9c83SDarrick J. Wong * Right edge contiguous, merge into right record. 2288ceeb9c83SDarrick J. Wong * 2289ceeb9c83SDarrick J. Wong * gtbno gtlen 2290ceeb9c83SDarrick J. Wong * Orig: |ooooooooo| 2291ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 2292ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 2293ceeb9c83SDarrick J. Wong * bno len 2294ceeb9c83SDarrick J. Wong */ 2295ceeb9c83SDarrick J. Wong /* Delete the old record. */ 2296ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2297ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2298ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2299ceeb9c83SDarrick J. Wong if (error) 2300ceeb9c83SDarrick J. Wong goto out_error; 2301ceeb9c83SDarrick J. Wong 2302ceeb9c83SDarrick J. Wong /* Move the start and re-add it. */ 2303ceeb9c83SDarrick J. Wong gtrec.rm_startblock = bno; 2304ceeb9c83SDarrick J. Wong gtrec.rm_blockcount += len; 2305ceeb9c83SDarrick J. Wong gtrec.rm_offset = offset; 2306ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, gtrec.rm_startblock, 2307ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2308ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2309ceeb9c83SDarrick J. Wong if (error) 2310ceeb9c83SDarrick J. Wong goto out_error; 2311ceeb9c83SDarrick J. Wong } else { 2312ceeb9c83SDarrick J. Wong /* 2313ceeb9c83SDarrick J. Wong * No contiguous edge with identical owner, insert 2314ceeb9c83SDarrick J. Wong * new record at current cursor position. 2315ceeb9c83SDarrick J. Wong */ 2316ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); 2317ceeb9c83SDarrick J. Wong if (error) 2318ceeb9c83SDarrick J. Wong goto out_error; 2319ceeb9c83SDarrick J. Wong } 2320ceeb9c83SDarrick J. Wong 232150f02fe3SDave Chinner trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len, 2322ceeb9c83SDarrick J. Wong unwritten, oinfo); 2323ceeb9c83SDarrick J. Wong out_error: 2324ceeb9c83SDarrick J. Wong if (error) 2325ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_error(cur->bc_mp, 232650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_); 2327ceeb9c83SDarrick J. Wong return error; 2328ceeb9c83SDarrick J. Wong } 2329ceeb9c83SDarrick J. Wong 23304d4f86b4SDarrick J. Wong /* Insert a raw rmap into the rmapbt. */ 23314d4f86b4SDarrick J. Wong int 23324d4f86b4SDarrick J. Wong xfs_rmap_map_raw( 23334d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 23344d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rmap) 23354d4f86b4SDarrick J. Wong { 23364d4f86b4SDarrick J. Wong struct xfs_owner_info oinfo; 23374d4f86b4SDarrick J. Wong 23384d4f86b4SDarrick J. Wong oinfo.oi_owner = rmap->rm_owner; 23394d4f86b4SDarrick J. Wong oinfo.oi_offset = rmap->rm_offset; 23404d4f86b4SDarrick J. Wong oinfo.oi_flags = 0; 23414d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_ATTR_FORK) 23424d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK; 23434d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK) 23444d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; 23454d4f86b4SDarrick J. Wong 23464d4f86b4SDarrick J. Wong if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner)) 23474d4f86b4SDarrick J. Wong return xfs_rmap_map(cur, rmap->rm_startblock, 23484d4f86b4SDarrick J. Wong rmap->rm_blockcount, 23494d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 23504d4f86b4SDarrick J. Wong &oinfo); 23514d4f86b4SDarrick J. Wong 23524d4f86b4SDarrick J. Wong return xfs_rmap_map_shared(cur, rmap->rm_startblock, 23534d4f86b4SDarrick J. Wong rmap->rm_blockcount, 23544d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN, 23554d4f86b4SDarrick J. Wong &oinfo); 23564d4f86b4SDarrick J. Wong } 23574d4f86b4SDarrick J. Wong 2358c543838aSDarrick J. Wong struct xfs_rmap_query_range_info { 2359c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn; 2360c543838aSDarrick J. Wong void *priv; 2361c543838aSDarrick J. Wong }; 2362c543838aSDarrick J. Wong 2363c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */ 2364c543838aSDarrick J. Wong STATIC int 2365c543838aSDarrick J. Wong xfs_rmap_query_range_helper( 2366c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2367159eb69dSDarrick J. Wong const union xfs_btree_rec *rec, 2368c543838aSDarrick J. Wong void *priv) 2369c543838aSDarrick J. Wong { 2370c543838aSDarrick J. Wong struct xfs_rmap_query_range_info *query = priv; 2371c543838aSDarrick J. Wong struct xfs_rmap_irec irec; 2372ee12eaaaSDarrick J. Wong xfs_failaddr_t fa; 2373c543838aSDarrick J. Wong 2374ee12eaaaSDarrick J. Wong fa = xfs_rmap_btrec_to_irec(rec, &irec); 2375ee12eaaaSDarrick J. Wong if (!fa) 2376ee12eaaaSDarrick J. Wong fa = xfs_rmap_check_irec(cur, &irec); 2377ee12eaaaSDarrick J. Wong if (fa) 2378ee12eaaaSDarrick J. Wong return xfs_rmap_complain_bad_rec(cur, fa, &irec); 237939ab26d5SDarrick J. Wong 2380c543838aSDarrick J. Wong return query->fn(cur, &irec, query->priv); 2381c543838aSDarrick J. Wong } 2382c543838aSDarrick J. Wong 2383c543838aSDarrick J. Wong /* Find all rmaps between two keys. */ 2384c543838aSDarrick J. Wong int 2385c543838aSDarrick J. Wong xfs_rmap_query_range( 2386c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 238704dcb474SDarrick J. Wong const struct xfs_rmap_irec *low_rec, 238804dcb474SDarrick J. Wong const struct xfs_rmap_irec *high_rec, 2389c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2390c543838aSDarrick J. Wong void *priv) 2391c543838aSDarrick J. Wong { 2392c543838aSDarrick J. Wong union xfs_btree_irec low_brec; 2393c543838aSDarrick J. Wong union xfs_btree_irec high_brec; 2394c543838aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2395c543838aSDarrick J. Wong 2396c543838aSDarrick J. Wong low_brec.r = *low_rec; 2397c543838aSDarrick J. Wong high_brec.r = *high_rec; 2398c543838aSDarrick J. Wong query.priv = priv; 2399c543838aSDarrick J. Wong query.fn = fn; 2400c543838aSDarrick J. Wong return xfs_btree_query_range(cur, &low_brec, &high_brec, 2401c543838aSDarrick J. Wong xfs_rmap_query_range_helper, &query); 2402e9a2599aSDarrick J. Wong } 2403e9a2599aSDarrick J. Wong 2404e9a2599aSDarrick J. Wong /* Find all rmaps. */ 2405e9a2599aSDarrick J. Wong int 2406e9a2599aSDarrick J. Wong xfs_rmap_query_all( 2407e9a2599aSDarrick J. Wong struct xfs_btree_cur *cur, 2408e9a2599aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2409e9a2599aSDarrick J. Wong void *priv) 2410e9a2599aSDarrick J. Wong { 2411e9a2599aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2412e9a2599aSDarrick J. Wong 2413e9a2599aSDarrick J. Wong query.priv = priv; 2414e9a2599aSDarrick J. Wong query.fn = fn; 2415e9a2599aSDarrick J. Wong return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query); 2416c543838aSDarrick J. Wong } 24179c194644SDarrick J. Wong 24189c194644SDarrick J. Wong /* Clean up after calling xfs_rmap_finish_one. */ 24199c194644SDarrick J. Wong void 24209c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup( 24219c194644SDarrick J. Wong struct xfs_trans *tp, 24229c194644SDarrick J. Wong struct xfs_btree_cur *rcur, 24239c194644SDarrick J. Wong int error) 24249c194644SDarrick J. Wong { 24259c194644SDarrick J. Wong struct xfs_buf *agbp; 24269c194644SDarrick J. Wong 24279c194644SDarrick J. Wong if (rcur == NULL) 24289c194644SDarrick J. Wong return; 2429576af732SDave Chinner agbp = rcur->bc_ag.agbp; 24300b04b6b8SDarrick J. Wong xfs_btree_del_cursor(rcur, error); 24319c194644SDarrick J. Wong if (error) 24329c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 24339c194644SDarrick J. Wong } 24349c194644SDarrick J. Wong 24359c194644SDarrick J. Wong /* 24369c194644SDarrick J. Wong * Process one of the deferred rmap operations. We pass back the 24379c194644SDarrick J. Wong * btree cursor to maintain our lock on the rmapbt between calls. 24389c194644SDarrick J. Wong * This saves time and eliminates a buffer deadlock between the 24399c194644SDarrick J. Wong * superblock and the AGF because we'll always grab them in the same 24409c194644SDarrick J. Wong * order. 24419c194644SDarrick J. Wong */ 24429c194644SDarrick J. Wong int 24439c194644SDarrick J. Wong xfs_rmap_finish_one( 24449c194644SDarrick J. Wong struct xfs_trans *tp, 24451534328bSDarrick J. Wong struct xfs_rmap_intent *ri, 24469c194644SDarrick J. Wong struct xfs_btree_cur **pcur) 24479c194644SDarrick J. Wong { 24489c194644SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 24499c194644SDarrick J. Wong struct xfs_btree_cur *rcur; 24509c194644SDarrick J. Wong struct xfs_buf *agbp = NULL; 24519c194644SDarrick J. Wong int error = 0; 24529c194644SDarrick J. Wong struct xfs_owner_info oinfo; 24539c194644SDarrick J. Wong xfs_agblock_t bno; 24549c194644SDarrick J. Wong bool unwritten; 24559c194644SDarrick J. Wong 24561534328bSDarrick J. Wong bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock); 24579c194644SDarrick J. Wong 2458c13418e8SDarrick J. Wong trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno, 24591534328bSDarrick J. Wong ri->ri_owner, ri->ri_whichfork, 24601534328bSDarrick J. Wong ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount, 24611534328bSDarrick J. Wong ri->ri_bmap.br_state); 24629c194644SDarrick J. Wong 2463c13418e8SDarrick J. Wong if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) 2464c13418e8SDarrick J. Wong return -EIO; 24659c194644SDarrick J. Wong 24669c194644SDarrick J. Wong /* 24679c194644SDarrick J. Wong * If we haven't gotten a cursor or the cursor AG doesn't match 24689c194644SDarrick J. Wong * the startblock, get one now. 24699c194644SDarrick J. Wong */ 24709c194644SDarrick J. Wong rcur = *pcur; 2471c13418e8SDarrick J. Wong if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) { 24729c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup(tp, rcur, 0); 24739c194644SDarrick J. Wong rcur = NULL; 24749c194644SDarrick J. Wong *pcur = NULL; 24759c194644SDarrick J. Wong } 24769c194644SDarrick J. Wong if (rcur == NULL) { 24779c194644SDarrick J. Wong /* 24789c194644SDarrick J. Wong * Refresh the freelist before we start changing the 24799c194644SDarrick J. Wong * rmapbt, because a shape change could cause us to 24809c194644SDarrick J. Wong * allocate blocks. 24819c194644SDarrick J. Wong */ 2482c13418e8SDarrick J. Wong error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp); 24839c194644SDarrick J. Wong if (error) 2484c13418e8SDarrick J. Wong return error; 2485c13418e8SDarrick J. Wong if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) 2486c13418e8SDarrick J. Wong return -EFSCORRUPTED; 24879c194644SDarrick J. Wong 2488c13418e8SDarrick J. Wong rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag); 24899c194644SDarrick J. Wong } 24909c194644SDarrick J. Wong *pcur = rcur; 24919c194644SDarrick J. Wong 24921534328bSDarrick J. Wong xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork, 24931534328bSDarrick J. Wong ri->ri_bmap.br_startoff); 24941534328bSDarrick J. Wong unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN; 24951534328bSDarrick J. Wong bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock); 24969c194644SDarrick J. Wong 24971534328bSDarrick J. Wong switch (ri->ri_type) { 24989c194644SDarrick J. Wong case XFS_RMAP_ALLOC: 24999c194644SDarrick J. Wong case XFS_RMAP_MAP: 25001534328bSDarrick J. Wong error = xfs_rmap_map(rcur, bno, ri->ri_bmap.br_blockcount, 25011534328bSDarrick J. Wong unwritten, &oinfo); 25029c194644SDarrick J. Wong break; 2503ceeb9c83SDarrick J. Wong case XFS_RMAP_MAP_SHARED: 25041534328bSDarrick J. Wong error = xfs_rmap_map_shared(rcur, bno, 25051534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, unwritten, &oinfo); 2506ceeb9c83SDarrick J. Wong break; 25079c194644SDarrick J. Wong case XFS_RMAP_FREE: 25089c194644SDarrick J. Wong case XFS_RMAP_UNMAP: 25091534328bSDarrick J. Wong error = xfs_rmap_unmap(rcur, bno, ri->ri_bmap.br_blockcount, 25101534328bSDarrick J. Wong unwritten, &oinfo); 25119c194644SDarrick J. Wong break; 2512ceeb9c83SDarrick J. Wong case XFS_RMAP_UNMAP_SHARED: 25131534328bSDarrick J. Wong error = xfs_rmap_unmap_shared(rcur, bno, 25141534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, unwritten, &oinfo); 2515ceeb9c83SDarrick J. Wong break; 25169c194644SDarrick J. Wong case XFS_RMAP_CONVERT: 25171534328bSDarrick J. Wong error = xfs_rmap_convert(rcur, bno, ri->ri_bmap.br_blockcount, 25181534328bSDarrick J. Wong !unwritten, &oinfo); 25199c194644SDarrick J. Wong break; 25203f165b33SDarrick J. Wong case XFS_RMAP_CONVERT_SHARED: 25211534328bSDarrick J. Wong error = xfs_rmap_convert_shared(rcur, bno, 25221534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, !unwritten, &oinfo); 25233f165b33SDarrick J. Wong break; 25249c194644SDarrick J. Wong default: 25259c194644SDarrick J. Wong ASSERT(0); 25269c194644SDarrick J. Wong error = -EFSCORRUPTED; 25279c194644SDarrick J. Wong } 2528c13418e8SDarrick J. Wong 25299c194644SDarrick J. Wong return error; 25309c194644SDarrick J. Wong } 25319c194644SDarrick J. Wong 25329c194644SDarrick J. Wong /* 25339c194644SDarrick J. Wong * Don't defer an rmap if we aren't an rmap filesystem. 25349c194644SDarrick J. Wong */ 25359c194644SDarrick J. Wong static bool 25369c194644SDarrick J. Wong xfs_rmap_update_is_needed( 25373993baebSDarrick J. Wong struct xfs_mount *mp, 25383993baebSDarrick J. Wong int whichfork) 25399c194644SDarrick J. Wong { 254038c26bfdSDave Chinner return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK; 25419c194644SDarrick J. Wong } 25429c194644SDarrick J. Wong 25439c194644SDarrick J. Wong /* 25449c194644SDarrick J. Wong * Record a rmap intent; the list is kept sorted first by AG and then by 25459c194644SDarrick J. Wong * increasing age. 25469c194644SDarrick J. Wong */ 2547bc46ac64SDarrick J. Wong static void 25489c194644SDarrick J. Wong __xfs_rmap_add( 25490f37d178SBrian Foster struct xfs_trans *tp, 25509c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2551c8ce540dSDarrick J. Wong uint64_t owner, 25529c194644SDarrick J. Wong int whichfork, 25539c194644SDarrick J. Wong struct xfs_bmbt_irec *bmap) 25549c194644SDarrick J. Wong { 25559c194644SDarrick J. Wong struct xfs_rmap_intent *ri; 25569c194644SDarrick J. Wong 25570f37d178SBrian Foster trace_xfs_rmap_defer(tp->t_mountp, 25580f37d178SBrian Foster XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock), 25599c194644SDarrick J. Wong type, 25600f37d178SBrian Foster XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock), 25619c194644SDarrick J. Wong owner, whichfork, 25629c194644SDarrick J. Wong bmap->br_startoff, 25639c194644SDarrick J. Wong bmap->br_blockcount, 25649c194644SDarrick J. Wong bmap->br_state); 25659c194644SDarrick J. Wong 2566f3c799c2SDarrick J. Wong ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL); 25679c194644SDarrick J. Wong INIT_LIST_HEAD(&ri->ri_list); 25689c194644SDarrick J. Wong ri->ri_type = type; 25699c194644SDarrick J. Wong ri->ri_owner = owner; 25709c194644SDarrick J. Wong ri->ri_whichfork = whichfork; 25719c194644SDarrick J. Wong ri->ri_bmap = *bmap; 25729c194644SDarrick J. Wong 2573c13418e8SDarrick J. Wong xfs_rmap_update_get_group(tp->t_mountp, ri); 25740f37d178SBrian Foster xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); 25759c194644SDarrick J. Wong } 25769c194644SDarrick J. Wong 25779c194644SDarrick J. Wong /* Map an extent into a file. */ 2578bc46ac64SDarrick J. Wong void 25799c194644SDarrick J. Wong xfs_rmap_map_extent( 25800f37d178SBrian Foster struct xfs_trans *tp, 25819c194644SDarrick J. Wong struct xfs_inode *ip, 25829c194644SDarrick J. Wong int whichfork, 25839c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 25849c194644SDarrick J. Wong { 2585d7884e6eSDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_MAP; 2586d7884e6eSDarrick J. Wong 25870f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2588bc46ac64SDarrick J. Wong return; 25899c194644SDarrick J. Wong 2590d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip)) 2591d7884e6eSDarrick J. Wong type = XFS_RMAP_MAP_SHARED; 2592d7884e6eSDarrick J. Wong 2593d7884e6eSDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV); 25949c194644SDarrick J. Wong } 25959c194644SDarrick J. Wong 25969c194644SDarrick J. Wong /* Unmap an extent out of a file. */ 2597bc46ac64SDarrick J. Wong void 25989c194644SDarrick J. Wong xfs_rmap_unmap_extent( 25990f37d178SBrian Foster struct xfs_trans *tp, 26009c194644SDarrick J. Wong struct xfs_inode *ip, 26019c194644SDarrick J. Wong int whichfork, 26029c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 26039c194644SDarrick J. Wong { 2604d7884e6eSDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP; 2605d7884e6eSDarrick J. Wong 26060f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) 2607bc46ac64SDarrick J. Wong return; 26089c194644SDarrick J. Wong 2609d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip)) 2610d7884e6eSDarrick J. Wong type = XFS_RMAP_UNMAP_SHARED; 2611d7884e6eSDarrick J. Wong 2612d7884e6eSDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV); 26139c194644SDarrick J. Wong } 26149c194644SDarrick J. Wong 26150f37d178SBrian Foster /* 26160f37d178SBrian Foster * Convert a data fork extent from unwritten to real or vice versa. 26170f37d178SBrian Foster * 26180f37d178SBrian Foster * Note that tp can be NULL here as no transaction is used for COW fork 26190f37d178SBrian Foster * unwritten conversion. 26200f37d178SBrian Foster */ 2621bc46ac64SDarrick J. Wong void 26229c194644SDarrick J. Wong xfs_rmap_convert_extent( 26239c194644SDarrick J. Wong struct xfs_mount *mp, 26240f37d178SBrian Foster struct xfs_trans *tp, 26259c194644SDarrick J. Wong struct xfs_inode *ip, 26269c194644SDarrick J. Wong int whichfork, 26279c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 26289c194644SDarrick J. Wong { 2629d7884e6eSDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT; 2630d7884e6eSDarrick J. Wong 26313993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 2632bc46ac64SDarrick J. Wong return; 26339c194644SDarrick J. Wong 2634d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip)) 2635d7884e6eSDarrick J. Wong type = XFS_RMAP_CONVERT_SHARED; 2636d7884e6eSDarrick J. Wong 2637d7884e6eSDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV); 26389c194644SDarrick J. Wong } 26399c194644SDarrick J. Wong 26409c194644SDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */ 2641bc46ac64SDarrick J. Wong void 26429c194644SDarrick J. Wong xfs_rmap_alloc_extent( 26430f37d178SBrian Foster struct xfs_trans *tp, 26449c194644SDarrick J. Wong xfs_agnumber_t agno, 26459c194644SDarrick J. Wong xfs_agblock_t bno, 26469c194644SDarrick J. Wong xfs_extlen_t len, 2647c8ce540dSDarrick J. Wong uint64_t owner) 26489c194644SDarrick J. Wong { 26499c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 26509c194644SDarrick J. Wong 26510f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2652bc46ac64SDarrick J. Wong return; 26539c194644SDarrick J. Wong 26540f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 26559c194644SDarrick J. Wong bmap.br_blockcount = len; 26569c194644SDarrick J. Wong bmap.br_startoff = 0; 26579c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 26589c194644SDarrick J. Wong 2659bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap); 26609c194644SDarrick J. Wong } 26619c194644SDarrick J. Wong 26629c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */ 2663bc46ac64SDarrick J. Wong void 26649c194644SDarrick J. Wong xfs_rmap_free_extent( 26650f37d178SBrian Foster struct xfs_trans *tp, 26669c194644SDarrick J. Wong xfs_agnumber_t agno, 26679c194644SDarrick J. Wong xfs_agblock_t bno, 26689c194644SDarrick J. Wong xfs_extlen_t len, 2669c8ce540dSDarrick J. Wong uint64_t owner) 26709c194644SDarrick J. Wong { 26719c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 26729c194644SDarrick J. Wong 26730f37d178SBrian Foster if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) 2674bc46ac64SDarrick J. Wong return; 26759c194644SDarrick J. Wong 26760f37d178SBrian Foster bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); 26779c194644SDarrick J. Wong bmap.br_blockcount = len; 26789c194644SDarrick J. Wong bmap.br_startoff = 0; 26799c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 26809c194644SDarrick J. Wong 2681bc46ac64SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap); 26829c194644SDarrick J. Wong } 2683e89c0413SDarrick J. Wong 2684e89c0413SDarrick J. Wong /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ 2685e89c0413SDarrick J. Wong int 2686e89c0413SDarrick J. Wong xfs_rmap_compare( 2687e89c0413SDarrick J. Wong const struct xfs_rmap_irec *a, 2688e89c0413SDarrick J. Wong const struct xfs_rmap_irec *b) 2689e89c0413SDarrick J. Wong { 2690e89c0413SDarrick J. Wong __u64 oa; 2691e89c0413SDarrick J. Wong __u64 ob; 2692e89c0413SDarrick J. Wong 2693e89c0413SDarrick J. Wong oa = xfs_rmap_irec_offset_pack(a); 2694e89c0413SDarrick J. Wong ob = xfs_rmap_irec_offset_pack(b); 2695e89c0413SDarrick J. Wong 2696e89c0413SDarrick J. Wong if (a->rm_startblock < b->rm_startblock) 2697e89c0413SDarrick J. Wong return -1; 2698e89c0413SDarrick J. Wong else if (a->rm_startblock > b->rm_startblock) 2699e89c0413SDarrick J. Wong return 1; 2700e89c0413SDarrick J. Wong else if (a->rm_owner < b->rm_owner) 2701e89c0413SDarrick J. Wong return -1; 2702e89c0413SDarrick J. Wong else if (a->rm_owner > b->rm_owner) 2703e89c0413SDarrick J. Wong return 1; 2704e89c0413SDarrick J. Wong else if (oa < ob) 2705e89c0413SDarrick J. Wong return -1; 2706e89c0413SDarrick J. Wong else if (oa > ob) 2707e89c0413SDarrick J. Wong return 1; 2708e89c0413SDarrick J. Wong else 2709e89c0413SDarrick J. Wong return 0; 2710e89c0413SDarrick J. Wong } 2711ed7c52d4SDarrick J. Wong 2712ed7c52d4SDarrick J. Wong /* Is there a record covering a given extent? */ 2713ed7c52d4SDarrick J. Wong int 2714ed7c52d4SDarrick J. Wong xfs_rmap_has_record( 2715ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2716ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2717ed7c52d4SDarrick J. Wong xfs_extlen_t len, 2718ed7c52d4SDarrick J. Wong bool *exists) 2719ed7c52d4SDarrick J. Wong { 2720ed7c52d4SDarrick J. Wong union xfs_btree_irec low; 2721ed7c52d4SDarrick J. Wong union xfs_btree_irec high; 2722ed7c52d4SDarrick J. Wong 2723ed7c52d4SDarrick J. Wong memset(&low, 0, sizeof(low)); 2724ed7c52d4SDarrick J. Wong low.r.rm_startblock = bno; 2725ed7c52d4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 2726ed7c52d4SDarrick J. Wong high.r.rm_startblock = bno + len - 1; 2727ed7c52d4SDarrick J. Wong 2728ed7c52d4SDarrick J. Wong return xfs_btree_has_record(cur, &low, &high, exists); 2729ed7c52d4SDarrick J. Wong } 2730ed7c52d4SDarrick J. Wong 2731ed7c52d4SDarrick J. Wong /* 2732ed7c52d4SDarrick J. Wong * Is there a record for this owner completely covering a given physical 2733ed7c52d4SDarrick J. Wong * extent? If so, *has_rmap will be set to true. If there is no record 2734ed7c52d4SDarrick J. Wong * or the record only covers part of the range, we set *has_rmap to false. 2735ed7c52d4SDarrick J. Wong * This function doesn't perform range lookups or offset checks, so it is 2736ed7c52d4SDarrick J. Wong * not suitable for checking data fork blocks. 2737ed7c52d4SDarrick J. Wong */ 2738ed7c52d4SDarrick J. Wong int 2739ed7c52d4SDarrick J. Wong xfs_rmap_record_exists( 2740ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2741ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2742ed7c52d4SDarrick J. Wong xfs_extlen_t len, 274366e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 2744ed7c52d4SDarrick J. Wong bool *has_rmap) 2745ed7c52d4SDarrick J. Wong { 2746ed7c52d4SDarrick J. Wong uint64_t owner; 2747ed7c52d4SDarrick J. Wong uint64_t offset; 2748ed7c52d4SDarrick J. Wong unsigned int flags; 2749ed7c52d4SDarrick J. Wong int has_record; 2750ed7c52d4SDarrick J. Wong struct xfs_rmap_irec irec; 2751ed7c52d4SDarrick J. Wong int error; 2752ed7c52d4SDarrick J. Wong 2753ed7c52d4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2754ed7c52d4SDarrick J. Wong ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || 2755ed7c52d4SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK)); 2756ed7c52d4SDarrick J. Wong 27575b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &irec, 2758ed7c52d4SDarrick J. Wong &has_record); 2759ed7c52d4SDarrick J. Wong if (error) 2760ed7c52d4SDarrick J. Wong return error; 2761ed7c52d4SDarrick J. Wong if (!has_record) { 2762ed7c52d4SDarrick J. Wong *has_rmap = false; 2763ed7c52d4SDarrick J. Wong return 0; 2764ed7c52d4SDarrick J. Wong } 2765ed7c52d4SDarrick J. Wong 2766ed7c52d4SDarrick J. Wong *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno && 2767ed7c52d4SDarrick J. Wong irec.rm_startblock + irec.rm_blockcount >= bno + len); 2768ed7c52d4SDarrick J. Wong return 0; 2769ed7c52d4SDarrick J. Wong } 27704d4f86b4SDarrick J. Wong 27714d4f86b4SDarrick J. Wong struct xfs_rmap_key_state { 27724d4f86b4SDarrick J. Wong uint64_t owner; 27734d4f86b4SDarrick J. Wong uint64_t offset; 27744d4f86b4SDarrick J. Wong unsigned int flags; 27754d4f86b4SDarrick J. Wong }; 27764d4f86b4SDarrick J. Wong 27774d4f86b4SDarrick J. Wong /* For each rmap given, figure out if it doesn't match the key we want. */ 27784d4f86b4SDarrick J. Wong STATIC int 27794d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper( 27804d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 2781159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec, 27824d4f86b4SDarrick J. Wong void *priv) 27834d4f86b4SDarrick J. Wong { 27844d4f86b4SDarrick J. Wong struct xfs_rmap_key_state *rks = priv; 27854d4f86b4SDarrick J. Wong 27864d4f86b4SDarrick J. Wong if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset && 27874d4f86b4SDarrick J. Wong ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags) 27884d4f86b4SDarrick J. Wong return 0; 2789e7ee96dfSDarrick J. Wong return -ECANCELED; 27904d4f86b4SDarrick J. Wong } 27914d4f86b4SDarrick J. Wong 27924d4f86b4SDarrick J. Wong /* 27934d4f86b4SDarrick J. Wong * Given an extent and some owner info, can we find records overlapping 27944d4f86b4SDarrick J. Wong * the extent whose owner info does not match the given owner? 27954d4f86b4SDarrick J. Wong */ 27964d4f86b4SDarrick J. Wong int 27974d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys( 27984d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur, 27994d4f86b4SDarrick J. Wong xfs_agblock_t bno, 28004d4f86b4SDarrick J. Wong xfs_extlen_t len, 280166e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo, 28024d4f86b4SDarrick J. Wong bool *has_rmap) 28034d4f86b4SDarrick J. Wong { 28044d4f86b4SDarrick J. Wong struct xfs_rmap_irec low = {0}; 28054d4f86b4SDarrick J. Wong struct xfs_rmap_irec high; 28064d4f86b4SDarrick J. Wong struct xfs_rmap_key_state rks; 28074d4f86b4SDarrick J. Wong int error; 28084d4f86b4SDarrick J. Wong 28094d4f86b4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags); 2810a71e4228SDarrick J. Wong *has_rmap = false; 28114d4f86b4SDarrick J. Wong 28124d4f86b4SDarrick J. Wong low.rm_startblock = bno; 28134d4f86b4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 28144d4f86b4SDarrick J. Wong high.rm_startblock = bno + len - 1; 28154d4f86b4SDarrick J. Wong 28164d4f86b4SDarrick J. Wong error = xfs_rmap_query_range(cur, &low, &high, 28174d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys_helper, &rks); 2818a71e4228SDarrick J. Wong if (error == -ECANCELED) { 2819a71e4228SDarrick J. Wong *has_rmap = true; 28207380e8feSDarrick J. Wong return 0; 28214d4f86b4SDarrick J. Wong } 28227280fedaSDarrick J. Wong 2823a71e4228SDarrick J. Wong return error; 2824a71e4228SDarrick J. Wong } 2825a71e4228SDarrick J. Wong 28267280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = { 28277280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_NULL, 28287280fedaSDarrick J. Wong }; 28297280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = { 28307280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_UNKNOWN, 28317280fedaSDarrick J. Wong }; 28327280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_FS = { 28337280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_FS, 28347280fedaSDarrick J. Wong }; 28357280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_LOG = { 28367280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_LOG, 28377280fedaSDarrick J. Wong }; 28387280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_AG = { 28397280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_AG, 28407280fedaSDarrick J. Wong }; 28417280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = { 28427280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INOBT, 28437280fedaSDarrick J. Wong }; 28447280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INODES = { 28457280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INODES, 28467280fedaSDarrick J. Wong }; 28477280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_REFC = { 28487280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_REFC, 28497280fedaSDarrick J. Wong }; 28507280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_COW = { 28517280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_COW, 28527280fedaSDarrick J. Wong }; 2853f3c799c2SDarrick J. Wong 2854f3c799c2SDarrick J. Wong int __init 2855f3c799c2SDarrick J. Wong xfs_rmap_intent_init_cache(void) 2856f3c799c2SDarrick J. Wong { 2857f3c799c2SDarrick J. Wong xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent", 2858f3c799c2SDarrick J. Wong sizeof(struct xfs_rmap_intent), 2859f3c799c2SDarrick J. Wong 0, 0, NULL); 2860f3c799c2SDarrick J. Wong 2861f3c799c2SDarrick J. Wong return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM; 2862f3c799c2SDarrick J. Wong } 2863f3c799c2SDarrick J. Wong 2864f3c799c2SDarrick J. Wong void 2865f3c799c2SDarrick J. Wong xfs_rmap_intent_destroy_cache(void) 2866f3c799c2SDarrick J. Wong { 2867f3c799c2SDarrick J. Wong kmem_cache_destroy(xfs_rmap_intent_cache); 2868f3c799c2SDarrick J. Wong xfs_rmap_intent_cache = NULL; 2869f3c799c2SDarrick J. Wong } 2870