1673930c3SDarrick J. Wong /* 2673930c3SDarrick J. Wong * Copyright (c) 2014 Red Hat, Inc. 3673930c3SDarrick J. Wong * All Rights Reserved. 4673930c3SDarrick J. Wong * 5673930c3SDarrick J. Wong * This program is free software; you can redistribute it and/or 6673930c3SDarrick J. Wong * modify it under the terms of the GNU General Public License as 7673930c3SDarrick J. Wong * published by the Free Software Foundation. 8673930c3SDarrick J. Wong * 9673930c3SDarrick J. Wong * This program is distributed in the hope that it would be useful, 10673930c3SDarrick J. Wong * but WITHOUT ANY WARRANTY; without even the implied warranty of 11673930c3SDarrick J. Wong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12673930c3SDarrick J. Wong * GNU General Public License for more details. 13673930c3SDarrick J. Wong * 14673930c3SDarrick J. Wong * You should have received a copy of the GNU General Public License 15673930c3SDarrick J. Wong * along with this program; if not, write the Free Software Foundation, 16673930c3SDarrick J. Wong * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17673930c3SDarrick J. Wong */ 18673930c3SDarrick J. Wong #include "xfs.h" 19673930c3SDarrick J. Wong #include "xfs_fs.h" 20673930c3SDarrick J. Wong #include "xfs_shared.h" 21673930c3SDarrick J. Wong #include "xfs_format.h" 22673930c3SDarrick J. Wong #include "xfs_log_format.h" 23673930c3SDarrick J. Wong #include "xfs_trans_resv.h" 24673930c3SDarrick J. Wong #include "xfs_bit.h" 25673930c3SDarrick J. Wong #include "xfs_sb.h" 26673930c3SDarrick J. Wong #include "xfs_mount.h" 27673930c3SDarrick J. Wong #include "xfs_defer.h" 28673930c3SDarrick J. Wong #include "xfs_da_format.h" 29673930c3SDarrick J. Wong #include "xfs_da_btree.h" 30673930c3SDarrick J. Wong #include "xfs_btree.h" 31673930c3SDarrick J. Wong #include "xfs_trans.h" 32673930c3SDarrick J. Wong #include "xfs_alloc.h" 33673930c3SDarrick J. Wong #include "xfs_rmap.h" 340a1b0b38SDarrick J. Wong #include "xfs_rmap_btree.h" 35673930c3SDarrick J. Wong #include "xfs_trans_space.h" 36673930c3SDarrick J. Wong #include "xfs_trace.h" 37e9e899a2SDarrick J. Wong #include "xfs_errortag.h" 38673930c3SDarrick J. Wong #include "xfs_error.h" 39673930c3SDarrick J. Wong #include "xfs_extent_busy.h" 409c194644SDarrick J. Wong #include "xfs_bmap.h" 419c194644SDarrick J. Wong #include "xfs_inode.h" 42673930c3SDarrick J. Wong 434b8ed677SDarrick J. Wong /* 444b8ed677SDarrick J. Wong * Lookup the first record less than or equal to [bno, len, owner, offset] 454b8ed677SDarrick J. Wong * in the btree given by cur. 464b8ed677SDarrick J. Wong */ 474b8ed677SDarrick J. Wong int 484b8ed677SDarrick J. Wong xfs_rmap_lookup_le( 494b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 504b8ed677SDarrick J. Wong xfs_agblock_t bno, 514b8ed677SDarrick J. Wong xfs_extlen_t len, 524b8ed677SDarrick J. Wong uint64_t owner, 534b8ed677SDarrick J. Wong uint64_t offset, 544b8ed677SDarrick J. Wong unsigned int flags, 554b8ed677SDarrick J. Wong int *stat) 564b8ed677SDarrick J. Wong { 574b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 584b8ed677SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 594b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 604b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 614b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 624b8ed677SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); 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 100abf09233SDarrick J. Wong trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.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, 112abf09233SDarrick J. Wong cur->bc_private.a.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 128abf09233SDarrick J. Wong trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.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; 134abf09233SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done); 135abf09233SDarrick J. Wong 136abf09233SDarrick J. Wong rcur->bc_rec.r.rm_startblock = agbno; 137abf09233SDarrick J. Wong rcur->bc_rec.r.rm_blockcount = len; 138abf09233SDarrick J. Wong rcur->bc_rec.r.rm_owner = owner; 139abf09233SDarrick J. Wong rcur->bc_rec.r.rm_offset = offset; 140abf09233SDarrick J. Wong rcur->bc_rec.r.rm_flags = flags; 141abf09233SDarrick J. Wong error = xfs_btree_insert(rcur, &i); 142abf09233SDarrick J. Wong if (error) 143abf09233SDarrick J. Wong goto done; 144abf09233SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); 145abf09233SDarrick J. Wong done: 146abf09233SDarrick J. Wong if (error) 147abf09233SDarrick J. Wong trace_xfs_rmap_insert_error(rcur->bc_mp, 148abf09233SDarrick J. Wong rcur->bc_private.a.agno, error, _RET_IP_); 149abf09233SDarrick J. Wong return error; 1504b8ed677SDarrick J. Wong } 1514b8ed677SDarrick J. Wong 152ceeb9c83SDarrick J. Wong STATIC int 153ceeb9c83SDarrick J. Wong xfs_rmap_delete( 154ceeb9c83SDarrick J. Wong struct xfs_btree_cur *rcur, 155ceeb9c83SDarrick J. Wong xfs_agblock_t agbno, 156ceeb9c83SDarrick J. Wong xfs_extlen_t len, 157ceeb9c83SDarrick J. Wong uint64_t owner, 158ceeb9c83SDarrick J. Wong uint64_t offset, 159ceeb9c83SDarrick J. Wong unsigned int flags) 160ceeb9c83SDarrick J. Wong { 161ceeb9c83SDarrick J. Wong int i; 162ceeb9c83SDarrick J. Wong int error; 163ceeb9c83SDarrick J. Wong 164ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, 165ceeb9c83SDarrick J. Wong len, owner, offset, flags); 166ceeb9c83SDarrick J. Wong 167ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); 168ceeb9c83SDarrick J. Wong if (error) 169ceeb9c83SDarrick J. Wong goto done; 170ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); 171ceeb9c83SDarrick J. Wong 172ceeb9c83SDarrick J. Wong error = xfs_btree_delete(rcur, &i); 173ceeb9c83SDarrick J. Wong if (error) 174ceeb9c83SDarrick J. Wong goto done; 175ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); 176ceeb9c83SDarrick J. Wong done: 177ceeb9c83SDarrick J. Wong if (error) 178ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete_error(rcur->bc_mp, 179ceeb9c83SDarrick J. Wong rcur->bc_private.a.agno, error, _RET_IP_); 180ceeb9c83SDarrick J. Wong return error; 181ceeb9c83SDarrick J. Wong } 182ceeb9c83SDarrick J. Wong 18326788097SDarrick J. Wong /* Convert an internal btree record to an rmap record. */ 18426788097SDarrick J. Wong int 1854b8ed677SDarrick J. Wong xfs_rmap_btrec_to_irec( 1864b8ed677SDarrick J. Wong union xfs_btree_rec *rec, 1874b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec) 1884b8ed677SDarrick J. Wong { 1894b8ed677SDarrick J. Wong irec->rm_flags = 0; 1904b8ed677SDarrick J. Wong irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); 1914b8ed677SDarrick J. Wong irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); 1924b8ed677SDarrick J. Wong irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); 1934b8ed677SDarrick J. Wong return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), 1944b8ed677SDarrick J. Wong irec); 1954b8ed677SDarrick J. Wong } 1964b8ed677SDarrick J. Wong 1974b8ed677SDarrick J. Wong /* 1984b8ed677SDarrick J. Wong * Get the data from the pointed-to record. 1994b8ed677SDarrick J. Wong */ 2004b8ed677SDarrick J. Wong int 2014b8ed677SDarrick J. Wong xfs_rmap_get_rec( 2024b8ed677SDarrick J. Wong struct xfs_btree_cur *cur, 2034b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec, 2044b8ed677SDarrick J. Wong int *stat) 2054b8ed677SDarrick J. Wong { 2064b8ed677SDarrick J. Wong union xfs_btree_rec *rec; 2074b8ed677SDarrick J. Wong int error; 2084b8ed677SDarrick J. Wong 2094b8ed677SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat); 2104b8ed677SDarrick J. Wong if (error || !*stat) 2114b8ed677SDarrick J. Wong return error; 2124b8ed677SDarrick J. Wong 2134b8ed677SDarrick J. Wong return xfs_rmap_btrec_to_irec(rec, irec); 2144b8ed677SDarrick J. Wong } 2154b8ed677SDarrick J. Wong 216ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info { 217ceeb9c83SDarrick J. Wong struct xfs_rmap_irec high; 218ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec; 219ceeb9c83SDarrick J. Wong int *stat; 220ceeb9c83SDarrick J. Wong }; 221ceeb9c83SDarrick J. Wong 222ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 223ceeb9c83SDarrick J. Wong STATIC int 224ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper( 225ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 226ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *rec, 227ceeb9c83SDarrick J. Wong void *priv) 228ceeb9c83SDarrick J. Wong { 229ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 230ceeb9c83SDarrick J. Wong 231ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, 232ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, rec->rm_startblock, 233ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 234ceeb9c83SDarrick J. Wong rec->rm_flags); 235ceeb9c83SDarrick J. Wong 236ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 237ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 238ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 239ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 240ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) 241ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 242ceeb9c83SDarrick J. Wong 243ceeb9c83SDarrick J. Wong *info->irec = *rec; 244ceeb9c83SDarrick J. Wong *info->stat = 1; 245ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_ABORT; 246ceeb9c83SDarrick J. Wong } 247ceeb9c83SDarrick J. Wong 248ceeb9c83SDarrick J. Wong /* 249ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 250ceeb9c83SDarrick J. Wong * return a match with the same owner and adjacent physical and logical 251ceeb9c83SDarrick J. Wong * block ranges. 252ceeb9c83SDarrick J. Wong */ 253ceeb9c83SDarrick J. Wong int 254ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor( 255ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 256ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 257ceeb9c83SDarrick J. Wong uint64_t owner, 258ceeb9c83SDarrick J. Wong uint64_t offset, 259ceeb9c83SDarrick J. Wong unsigned int flags, 260ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 261ceeb9c83SDarrick J. Wong int *stat) 262ceeb9c83SDarrick J. Wong { 263ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 264ceeb9c83SDarrick J. Wong int error; 265ceeb9c83SDarrick J. Wong 266ceeb9c83SDarrick J. Wong *stat = 0; 267ceeb9c83SDarrick J. Wong if (bno == 0) 268ceeb9c83SDarrick J. Wong return 0; 269ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno - 1; 270ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 271ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && 272ceeb9c83SDarrick J. Wong !(flags & XFS_RMAP_BMBT_BLOCK)) { 273ceeb9c83SDarrick J. Wong if (offset == 0) 274ceeb9c83SDarrick J. Wong return 0; 275ceeb9c83SDarrick J. Wong info.high.rm_offset = offset - 1; 276ceeb9c83SDarrick J. Wong } else 277ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 278ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 279ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 280ceeb9c83SDarrick J. Wong info.irec = irec; 281ceeb9c83SDarrick J. Wong info.stat = stat; 282ceeb9c83SDarrick J. Wong 283ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, 284ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, bno, 0, owner, offset, flags); 285ceeb9c83SDarrick J. Wong 286ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 287ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper, &info); 288ceeb9c83SDarrick J. Wong if (error == XFS_BTREE_QUERY_RANGE_ABORT) 289ceeb9c83SDarrick J. Wong error = 0; 290ceeb9c83SDarrick J. Wong if (*stat) 291ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 292ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, irec->rm_startblock, 293ceeb9c83SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, 294ceeb9c83SDarrick J. Wong irec->rm_offset, irec->rm_flags); 295ceeb9c83SDarrick J. Wong return error; 296ceeb9c83SDarrick J. Wong } 297ceeb9c83SDarrick J. Wong 298ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */ 299ceeb9c83SDarrick J. Wong STATIC int 300ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper( 301ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 302ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *rec, 303ceeb9c83SDarrick J. Wong void *priv) 304ceeb9c83SDarrick J. Wong { 305ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv; 306ceeb9c83SDarrick J. Wong 307ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, 308ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, rec->rm_startblock, 309ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset, 310ceeb9c83SDarrick J. Wong rec->rm_flags); 311ceeb9c83SDarrick J. Wong 312ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner) 313ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 314ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && 315ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && 316ceeb9c83SDarrick J. Wong (rec->rm_offset > info->high.rm_offset || 317ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) 318ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_CONTINUE; 319ceeb9c83SDarrick J. Wong 320ceeb9c83SDarrick J. Wong *info->irec = *rec; 321ceeb9c83SDarrick J. Wong *info->stat = 1; 322ceeb9c83SDarrick J. Wong return XFS_BTREE_QUERY_RANGE_ABORT; 323ceeb9c83SDarrick J. Wong } 324ceeb9c83SDarrick J. Wong 325ceeb9c83SDarrick J. Wong /* 326ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to 327ceeb9c83SDarrick J. Wong * return a match with the same owner and overlapping physical and logical 328ceeb9c83SDarrick J. Wong * block ranges. This is the overlapping-interval version of 329ceeb9c83SDarrick J. Wong * xfs_rmap_lookup_le. 330ceeb9c83SDarrick J. Wong */ 331ceeb9c83SDarrick J. Wong int 332ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range( 333ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 334ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 335ceeb9c83SDarrick J. Wong uint64_t owner, 336ceeb9c83SDarrick J. Wong uint64_t offset, 337ceeb9c83SDarrick J. Wong unsigned int flags, 338ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec, 339ceeb9c83SDarrick J. Wong int *stat) 340ceeb9c83SDarrick J. Wong { 341ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info; 342ceeb9c83SDarrick J. Wong int error; 343ceeb9c83SDarrick J. Wong 344ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno; 345ceeb9c83SDarrick J. Wong info.high.rm_owner = owner; 346ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) 347ceeb9c83SDarrick J. Wong info.high.rm_offset = offset; 348ceeb9c83SDarrick J. Wong else 349ceeb9c83SDarrick J. Wong info.high.rm_offset = 0; 350ceeb9c83SDarrick J. Wong info.high.rm_flags = flags; 351ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0; 352ceeb9c83SDarrick J. Wong *stat = 0; 353ceeb9c83SDarrick J. Wong info.irec = irec; 354ceeb9c83SDarrick J. Wong info.stat = stat; 355ceeb9c83SDarrick J. Wong 356ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range(cur->bc_mp, 357ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, bno, 0, owner, offset, flags); 358ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high, 359ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper, &info); 360ceeb9c83SDarrick J. Wong if (error == XFS_BTREE_QUERY_RANGE_ABORT) 361ceeb9c83SDarrick J. Wong error = 0; 362ceeb9c83SDarrick J. Wong if (*stat) 363ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 364ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, irec->rm_startblock, 365ceeb9c83SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, 366ceeb9c83SDarrick J. Wong irec->rm_offset, irec->rm_flags); 367ceeb9c83SDarrick J. Wong return error; 368ceeb9c83SDarrick J. Wong } 369ceeb9c83SDarrick J. Wong 370f922cd90SDarrick J. Wong /* 37168c58e9bSDarrick J. Wong * Perform all the relevant owner checks for a removal op. If we're doing an 37268c58e9bSDarrick J. Wong * unknown-owner removal then we have no owner information to check. 37368c58e9bSDarrick J. Wong */ 37468c58e9bSDarrick J. Wong static int 37568c58e9bSDarrick J. Wong xfs_rmap_free_check_owner( 37668c58e9bSDarrick J. Wong struct xfs_mount *mp, 37768c58e9bSDarrick J. Wong uint64_t ltoff, 37868c58e9bSDarrick J. Wong struct xfs_rmap_irec *rec, 37968c58e9bSDarrick J. Wong xfs_fsblock_t bno, 38068c58e9bSDarrick J. Wong xfs_filblks_t len, 38168c58e9bSDarrick J. Wong uint64_t owner, 38268c58e9bSDarrick J. Wong uint64_t offset, 38368c58e9bSDarrick J. Wong unsigned int flags) 38468c58e9bSDarrick J. Wong { 38568c58e9bSDarrick J. Wong int error = 0; 38668c58e9bSDarrick J. Wong 38768c58e9bSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN) 38868c58e9bSDarrick J. Wong return 0; 38968c58e9bSDarrick J. Wong 39068c58e9bSDarrick J. Wong /* Make sure the unwritten flag matches. */ 39168c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == 39268c58e9bSDarrick J. Wong (rec->rm_flags & XFS_RMAP_UNWRITTEN), out); 39368c58e9bSDarrick J. Wong 39468c58e9bSDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 39568c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out); 39668c58e9bSDarrick J. Wong 39768c58e9bSDarrick J. Wong /* Check the offset, if necessary. */ 39868c58e9bSDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(owner)) 39968c58e9bSDarrick J. Wong goto out; 40068c58e9bSDarrick J. Wong 40168c58e9bSDarrick J. Wong if (flags & XFS_RMAP_BMBT_BLOCK) { 40268c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK, 40368c58e9bSDarrick J. Wong out); 40468c58e9bSDarrick J. Wong } else { 40568c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out); 40668c58e9bSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 40768c58e9bSDarrick J. Wong ltoff + rec->rm_blockcount >= offset + len, 40868c58e9bSDarrick J. Wong out); 40968c58e9bSDarrick J. Wong } 41068c58e9bSDarrick J. Wong 41168c58e9bSDarrick J. Wong out: 41268c58e9bSDarrick J. Wong return error; 41368c58e9bSDarrick J. Wong } 41468c58e9bSDarrick J. Wong 41568c58e9bSDarrick J. Wong /* 416f922cd90SDarrick J. Wong * Find the extent in the rmap btree and remove it. 417f922cd90SDarrick J. Wong * 418f922cd90SDarrick J. Wong * The record we find should always be an exact match for the extent that we're 419f922cd90SDarrick J. Wong * looking for, since we insert them into the btree without modification. 420f922cd90SDarrick J. Wong * 421f922cd90SDarrick J. Wong * Special Case #1: when growing the filesystem, we "free" an extent when 422f922cd90SDarrick J. Wong * growing the last AG. This extent is new space and so it is not tracked as 423f922cd90SDarrick J. Wong * used space in the btree. The growfs code will pass in an owner of 424f922cd90SDarrick J. Wong * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this 425f922cd90SDarrick J. Wong * extent. We verify that - the extent lookup result in a record that does not 426f922cd90SDarrick J. Wong * overlap. 427f922cd90SDarrick J. Wong * 428f922cd90SDarrick J. Wong * Special Case #2: EFIs do not record the owner of the extent, so when 429f922cd90SDarrick J. Wong * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap 430f922cd90SDarrick J. Wong * btree to ignore the owner (i.e. wildcard match) so we don't trigger 431f922cd90SDarrick J. Wong * corruption checks during log recovery. 432f922cd90SDarrick J. Wong */ 433f922cd90SDarrick J. Wong STATIC int 434f922cd90SDarrick J. Wong xfs_rmap_unmap( 435f922cd90SDarrick J. Wong struct xfs_btree_cur *cur, 436f922cd90SDarrick J. Wong xfs_agblock_t bno, 437f922cd90SDarrick J. Wong xfs_extlen_t len, 438f922cd90SDarrick J. Wong bool unwritten, 439f922cd90SDarrick J. Wong struct xfs_owner_info *oinfo) 440f922cd90SDarrick J. Wong { 441f922cd90SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 442f922cd90SDarrick J. Wong struct xfs_rmap_irec ltrec; 443f922cd90SDarrick J. Wong uint64_t ltoff; 444f922cd90SDarrick J. Wong int error = 0; 445f922cd90SDarrick J. Wong int i; 446f922cd90SDarrick J. Wong uint64_t owner; 447f922cd90SDarrick J. Wong uint64_t offset; 448f922cd90SDarrick J. Wong unsigned int flags; 449f922cd90SDarrick J. Wong bool ignore_off; 450f922cd90SDarrick J. Wong 451f922cd90SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 452f922cd90SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 453f922cd90SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 454f922cd90SDarrick J. Wong if (unwritten) 455f922cd90SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 456f922cd90SDarrick J. Wong trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, 457f922cd90SDarrick J. Wong unwritten, oinfo); 458f922cd90SDarrick J. Wong 459f922cd90SDarrick J. Wong /* 460f922cd90SDarrick J. Wong * We should always have a left record because there's a static record 461f922cd90SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 462f922cd90SDarrick J. Wong * will not ever be removed from the tree. 463f922cd90SDarrick J. Wong */ 464f922cd90SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); 465f922cd90SDarrick J. Wong if (error) 466f922cd90SDarrick J. Wong goto out_error; 467f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 468f922cd90SDarrick J. Wong 469f922cd90SDarrick J. Wong error = xfs_rmap_get_rec(cur, <rec, &i); 470f922cd90SDarrick J. Wong if (error) 471f922cd90SDarrick J. Wong goto out_error; 472f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 473f922cd90SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 474f922cd90SDarrick J. Wong cur->bc_private.a.agno, ltrec.rm_startblock, 475f922cd90SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 476f922cd90SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 477f922cd90SDarrick J. Wong ltoff = ltrec.rm_offset; 478f922cd90SDarrick J. Wong 479f922cd90SDarrick J. Wong /* 480f922cd90SDarrick J. Wong * For growfs, the incoming extent must be beyond the left record we 481f922cd90SDarrick J. Wong * just found as it is new space and won't be used by anyone. This is 482f922cd90SDarrick J. Wong * just a corruption check as we don't actually do anything with this 483f922cd90SDarrick J. Wong * extent. Note that we need to use >= instead of > because it might 484f922cd90SDarrick J. Wong * be the case that the "left" extent goes all the way to EOFS. 485f922cd90SDarrick J. Wong */ 486f922cd90SDarrick J. Wong if (owner == XFS_RMAP_OWN_NULL) { 487f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock + 488f922cd90SDarrick J. Wong ltrec.rm_blockcount, out_error); 489f922cd90SDarrick J. Wong goto out_done; 490f922cd90SDarrick J. Wong } 491f922cd90SDarrick J. Wong 49233df3a9cSDarrick J. Wong /* 49333df3a9cSDarrick J. Wong * If we're doing an unknown-owner removal for EFI recovery, we expect 49433df3a9cSDarrick J. Wong * to find the full range in the rmapbt or nothing at all. If we 49533df3a9cSDarrick J. Wong * don't find any rmaps overlapping either end of the range, we're 49633df3a9cSDarrick J. Wong * done. Hopefully this means that the EFI creator already queued 49733df3a9cSDarrick J. Wong * (and finished) a RUI to remove the rmap. 49833df3a9cSDarrick J. Wong */ 49933df3a9cSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN && 50033df3a9cSDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 50133df3a9cSDarrick J. Wong struct xfs_rmap_irec rtrec; 50233df3a9cSDarrick J. Wong 50333df3a9cSDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 50433df3a9cSDarrick J. Wong if (error) 50533df3a9cSDarrick J. Wong goto out_error; 50633df3a9cSDarrick J. Wong if (i == 0) 50733df3a9cSDarrick J. Wong goto out_done; 50833df3a9cSDarrick J. Wong error = xfs_rmap_get_rec(cur, &rtrec, &i); 50933df3a9cSDarrick J. Wong if (error) 51033df3a9cSDarrick J. Wong goto out_error; 51133df3a9cSDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 51233df3a9cSDarrick J. Wong if (rtrec.rm_startblock >= bno + len) 51333df3a9cSDarrick J. Wong goto out_done; 51433df3a9cSDarrick J. Wong } 51533df3a9cSDarrick J. Wong 516f922cd90SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 517f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && 518f922cd90SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount >= 519f922cd90SDarrick J. Wong bno + len, out_error); 520f922cd90SDarrick J. Wong 52168c58e9bSDarrick J. Wong /* Check owner information. */ 52268c58e9bSDarrick J. Wong error = xfs_rmap_free_check_owner(mp, ltoff, <rec, bno, len, owner, 52368c58e9bSDarrick J. Wong offset, flags); 52468c58e9bSDarrick J. Wong if (error) 52568c58e9bSDarrick J. Wong goto out_error; 526f922cd90SDarrick J. Wong 527f922cd90SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 528f922cd90SDarrick J. Wong /* exact match, simply remove the record from rmap tree */ 529f922cd90SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 530f922cd90SDarrick J. Wong ltrec.rm_startblock, ltrec.rm_blockcount, 531f922cd90SDarrick J. Wong ltrec.rm_owner, ltrec.rm_offset, 532f922cd90SDarrick J. Wong ltrec.rm_flags); 533f922cd90SDarrick J. Wong error = xfs_btree_delete(cur, &i); 534f922cd90SDarrick J. Wong if (error) 535f922cd90SDarrick J. Wong goto out_error; 536f922cd90SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 537f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 538f922cd90SDarrick J. Wong /* 539f922cd90SDarrick J. Wong * overlap left hand side of extent: move the start, trim the 540f922cd90SDarrick J. Wong * length and update the current record. 541f922cd90SDarrick J. Wong * 542f922cd90SDarrick J. Wong * ltbno ltlen 543f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 544f922cd90SDarrick J. Wong * Freeing: |fffffffff| 545f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 546f922cd90SDarrick J. Wong * bno len 547f922cd90SDarrick J. Wong */ 548f922cd90SDarrick J. Wong ltrec.rm_startblock += len; 549f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 550f922cd90SDarrick J. Wong if (!ignore_off) 551f922cd90SDarrick J. Wong ltrec.rm_offset += len; 552f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 553f922cd90SDarrick J. Wong if (error) 554f922cd90SDarrick J. Wong goto out_error; 555f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 556f922cd90SDarrick J. Wong /* 557f922cd90SDarrick J. Wong * overlap right hand side of extent: trim the length and update 558f922cd90SDarrick J. Wong * the current record. 559f922cd90SDarrick J. Wong * 560f922cd90SDarrick J. Wong * ltbno ltlen 561f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 562f922cd90SDarrick J. Wong * Freeing: |fffffffff| 563f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr| 564f922cd90SDarrick J. Wong * bno len 565f922cd90SDarrick J. Wong */ 566f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len; 567f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 568f922cd90SDarrick J. Wong if (error) 569f922cd90SDarrick J. Wong goto out_error; 570f922cd90SDarrick J. Wong } else { 571f922cd90SDarrick J. Wong 572f922cd90SDarrick J. Wong /* 573f922cd90SDarrick J. Wong * overlap middle of extent: trim the length of the existing 574f922cd90SDarrick J. Wong * record to the length of the new left-extent size, increment 575f922cd90SDarrick J. Wong * the insertion position so we can insert a new record 576f922cd90SDarrick J. Wong * containing the remaining right-extent space. 577f922cd90SDarrick J. Wong * 578f922cd90SDarrick J. Wong * ltbno ltlen 579f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo| 580f922cd90SDarrick J. Wong * Freeing: |fffffffff| 581f922cd90SDarrick J. Wong * Result: |rrrrr| |rrrr| 582f922cd90SDarrick J. Wong * bno len 583f922cd90SDarrick J. Wong */ 584f922cd90SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 585f922cd90SDarrick J. Wong 586f922cd90SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 587f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 588f922cd90SDarrick J. Wong if (error) 589f922cd90SDarrick J. Wong goto out_error; 590f922cd90SDarrick J. Wong 591f922cd90SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 592f922cd90SDarrick J. Wong if (error) 593f922cd90SDarrick J. Wong goto out_error; 594f922cd90SDarrick J. Wong 595f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno + len; 596f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount = orig_len - len - 597f922cd90SDarrick J. Wong ltrec.rm_blockcount; 598f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner = ltrec.rm_owner; 599f922cd90SDarrick J. Wong if (ignore_off) 600f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = 0; 601f922cd90SDarrick J. Wong else 602f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = offset + len; 603f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 604f922cd90SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, 605f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock, 606f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount, 607f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner, 608f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset, 609f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags); 610f922cd90SDarrick J. Wong error = xfs_btree_insert(cur, &i); 611f922cd90SDarrick J. Wong if (error) 612f922cd90SDarrick J. Wong goto out_error; 613f922cd90SDarrick J. Wong } 614f922cd90SDarrick J. Wong 615f922cd90SDarrick J. Wong out_done: 616f922cd90SDarrick J. Wong trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, 617f922cd90SDarrick J. Wong unwritten, oinfo); 618f922cd90SDarrick J. Wong out_error: 619f922cd90SDarrick J. Wong if (error) 620f922cd90SDarrick J. Wong trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno, 621f922cd90SDarrick J. Wong error, _RET_IP_); 622f922cd90SDarrick J. Wong return error; 623f922cd90SDarrick J. Wong } 624f922cd90SDarrick J. Wong 625f922cd90SDarrick J. Wong /* 626f922cd90SDarrick J. Wong * Remove a reference to an extent in the rmap btree. 627f922cd90SDarrick J. Wong */ 628673930c3SDarrick J. Wong int 629673930c3SDarrick J. Wong xfs_rmap_free( 630673930c3SDarrick J. Wong struct xfs_trans *tp, 631673930c3SDarrick J. Wong struct xfs_buf *agbp, 632673930c3SDarrick J. Wong xfs_agnumber_t agno, 633673930c3SDarrick J. Wong xfs_agblock_t bno, 634673930c3SDarrick J. Wong xfs_extlen_t len, 635673930c3SDarrick J. Wong struct xfs_owner_info *oinfo) 636673930c3SDarrick J. Wong { 637673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 638f922cd90SDarrick J. Wong struct xfs_btree_cur *cur; 639f922cd90SDarrick J. Wong int error; 640673930c3SDarrick J. Wong 641673930c3SDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 642673930c3SDarrick J. Wong return 0; 643673930c3SDarrick J. Wong 644f922cd90SDarrick J. Wong cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 645f922cd90SDarrick J. Wong 646f922cd90SDarrick J. Wong error = xfs_rmap_unmap(cur, bno, len, false, oinfo); 647f922cd90SDarrick J. Wong if (error) 648673930c3SDarrick J. Wong goto out_error; 649f922cd90SDarrick J. Wong 650f922cd90SDarrick J. Wong xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 651673930c3SDarrick J. Wong return 0; 652673930c3SDarrick J. Wong 653673930c3SDarrick J. Wong out_error: 654f922cd90SDarrick J. Wong xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 655673930c3SDarrick J. Wong return error; 656673930c3SDarrick J. Wong } 657673930c3SDarrick J. Wong 6580a1b0b38SDarrick J. Wong /* 6590a1b0b38SDarrick J. Wong * A mergeable rmap must have the same owner and the same values for 6600a1b0b38SDarrick J. Wong * the unwritten, attr_fork, and bmbt flags. The startblock and 6610a1b0b38SDarrick J. Wong * offset are checked separately. 6620a1b0b38SDarrick J. Wong */ 6630a1b0b38SDarrick J. Wong static bool 6640a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable( 6650a1b0b38SDarrick J. Wong struct xfs_rmap_irec *irec, 6660a1b0b38SDarrick J. Wong uint64_t owner, 6670a1b0b38SDarrick J. Wong unsigned int flags) 6680a1b0b38SDarrick J. Wong { 6690a1b0b38SDarrick J. Wong if (irec->rm_owner == XFS_RMAP_OWN_NULL) 6700a1b0b38SDarrick J. Wong return false; 6710a1b0b38SDarrick J. Wong if (irec->rm_owner != owner) 6720a1b0b38SDarrick J. Wong return false; 6730a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_UNWRITTEN) ^ 6740a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_UNWRITTEN)) 6750a1b0b38SDarrick J. Wong return false; 6760a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_ATTR_FORK) ^ 6770a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_ATTR_FORK)) 6780a1b0b38SDarrick J. Wong return false; 6790a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_BMBT_BLOCK) ^ 6800a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) 6810a1b0b38SDarrick J. Wong return false; 6820a1b0b38SDarrick J. Wong return true; 6830a1b0b38SDarrick J. Wong } 6840a1b0b38SDarrick J. Wong 6850a1b0b38SDarrick J. Wong /* 6860a1b0b38SDarrick J. Wong * When we allocate a new block, the first thing we do is add a reference to 6870a1b0b38SDarrick J. Wong * the extent in the rmap btree. This takes the form of a [agbno, length, 6880a1b0b38SDarrick J. Wong * owner, offset] record. Flags are encoded in the high bits of the offset 6890a1b0b38SDarrick J. Wong * field. 6900a1b0b38SDarrick J. Wong */ 6910a1b0b38SDarrick J. Wong STATIC int 6920a1b0b38SDarrick J. Wong xfs_rmap_map( 6930a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur, 6940a1b0b38SDarrick J. Wong xfs_agblock_t bno, 6950a1b0b38SDarrick J. Wong xfs_extlen_t len, 6960a1b0b38SDarrick J. Wong bool unwritten, 6970a1b0b38SDarrick J. Wong struct xfs_owner_info *oinfo) 6980a1b0b38SDarrick J. Wong { 6990a1b0b38SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 7000a1b0b38SDarrick J. Wong struct xfs_rmap_irec ltrec; 7010a1b0b38SDarrick J. Wong struct xfs_rmap_irec gtrec; 7020a1b0b38SDarrick J. Wong int have_gt; 7030a1b0b38SDarrick J. Wong int have_lt; 7040a1b0b38SDarrick J. Wong int error = 0; 7050a1b0b38SDarrick J. Wong int i; 7060a1b0b38SDarrick J. Wong uint64_t owner; 7070a1b0b38SDarrick J. Wong uint64_t offset; 7080a1b0b38SDarrick J. Wong unsigned int flags = 0; 7090a1b0b38SDarrick J. Wong bool ignore_off; 7100a1b0b38SDarrick J. Wong 7110a1b0b38SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 7120a1b0b38SDarrick J. Wong ASSERT(owner != 0); 7130a1b0b38SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || 7140a1b0b38SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK); 7150a1b0b38SDarrick J. Wong if (unwritten) 7160a1b0b38SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 7170a1b0b38SDarrick J. Wong trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 7180a1b0b38SDarrick J. Wong unwritten, oinfo); 71933df3a9cSDarrick J. Wong ASSERT(!xfs_rmap_should_skip_owner_update(oinfo)); 7200a1b0b38SDarrick J. Wong 7210a1b0b38SDarrick J. Wong /* 7220a1b0b38SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 7230a1b0b38SDarrick J. Wong * record for our insertion point. This will also give us the record for 7240a1b0b38SDarrick J. Wong * start block contiguity tests. 7250a1b0b38SDarrick J. Wong */ 7260a1b0b38SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, 7270a1b0b38SDarrick J. Wong &have_lt); 7280a1b0b38SDarrick J. Wong if (error) 7290a1b0b38SDarrick J. Wong goto out_error; 7300a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); 7310a1b0b38SDarrick J. Wong 7320a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, <rec, &have_lt); 7330a1b0b38SDarrick J. Wong if (error) 7340a1b0b38SDarrick J. Wong goto out_error; 7350a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); 7360a1b0b38SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 7370a1b0b38SDarrick J. Wong cur->bc_private.a.agno, ltrec.rm_startblock, 7380a1b0b38SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 7390a1b0b38SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 7400a1b0b38SDarrick J. Wong 7410a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(<rec, owner, flags)) 7420a1b0b38SDarrick J. Wong have_lt = 0; 7430a1b0b38SDarrick J. Wong 7440a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 7450a1b0b38SDarrick J. Wong have_lt == 0 || 7460a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); 7470a1b0b38SDarrick J. Wong 7480a1b0b38SDarrick J. Wong /* 7490a1b0b38SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 7500a1b0b38SDarrick J. Wong * insertion point. This will give us the record for end block 7510a1b0b38SDarrick J. Wong * contiguity tests. 7520a1b0b38SDarrick J. Wong */ 7530a1b0b38SDarrick J. Wong error = xfs_btree_increment(cur, 0, &have_gt); 7540a1b0b38SDarrick J. Wong if (error) 7550a1b0b38SDarrick J. Wong goto out_error; 7560a1b0b38SDarrick J. Wong if (have_gt) { 7570a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 7580a1b0b38SDarrick J. Wong if (error) 7590a1b0b38SDarrick J. Wong goto out_error; 7600a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); 7610a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock, 7620a1b0b38SDarrick J. Wong out_error); 7630a1b0b38SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 7640a1b0b38SDarrick J. Wong cur->bc_private.a.agno, gtrec.rm_startblock, 7650a1b0b38SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 7660a1b0b38SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 7670a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 7680a1b0b38SDarrick J. Wong have_gt = 0; 7690a1b0b38SDarrick J. Wong } 7700a1b0b38SDarrick J. Wong 7710a1b0b38SDarrick J. Wong /* 7720a1b0b38SDarrick J. Wong * Note: cursor currently points one record to the right of ltrec, even 7730a1b0b38SDarrick J. Wong * if there is no record in the tree to the right. 7740a1b0b38SDarrick J. Wong */ 7750a1b0b38SDarrick J. Wong if (have_lt && 7760a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 7770a1b0b38SDarrick J. Wong (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { 7780a1b0b38SDarrick J. Wong /* 7790a1b0b38SDarrick J. Wong * left edge contiguous, merge into left record. 7800a1b0b38SDarrick J. Wong * 7810a1b0b38SDarrick J. Wong * ltbno ltlen 7820a1b0b38SDarrick J. Wong * orig: |ooooooooo| 7830a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 7840a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 7850a1b0b38SDarrick J. Wong * bno len 7860a1b0b38SDarrick J. Wong */ 7870a1b0b38SDarrick J. Wong ltrec.rm_blockcount += len; 7880a1b0b38SDarrick J. Wong if (have_gt && 7890a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 7900a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset) && 7910a1b0b38SDarrick J. Wong (unsigned long)ltrec.rm_blockcount + len + 7920a1b0b38SDarrick J. Wong gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { 7930a1b0b38SDarrick J. Wong /* 7940a1b0b38SDarrick J. Wong * right edge also contiguous, delete right record 7950a1b0b38SDarrick J. Wong * and merge into left record. 7960a1b0b38SDarrick J. Wong * 7970a1b0b38SDarrick J. Wong * ltbno ltlen gtbno gtlen 7980a1b0b38SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 7990a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8000a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 8010a1b0b38SDarrick J. Wong */ 8020a1b0b38SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 8030a1b0b38SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 8040a1b0b38SDarrick J. Wong gtrec.rm_startblock, 8050a1b0b38SDarrick J. Wong gtrec.rm_blockcount, 8060a1b0b38SDarrick J. Wong gtrec.rm_owner, 8070a1b0b38SDarrick J. Wong gtrec.rm_offset, 8080a1b0b38SDarrick J. Wong gtrec.rm_flags); 8090a1b0b38SDarrick J. Wong error = xfs_btree_delete(cur, &i); 8100a1b0b38SDarrick J. Wong if (error) 8110a1b0b38SDarrick J. Wong goto out_error; 8120a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 8130a1b0b38SDarrick J. Wong } 8140a1b0b38SDarrick J. Wong 8150a1b0b38SDarrick J. Wong /* point the cursor back to the left record and update */ 8160a1b0b38SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &have_gt); 8170a1b0b38SDarrick J. Wong if (error) 8180a1b0b38SDarrick J. Wong goto out_error; 8190a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 8200a1b0b38SDarrick J. Wong if (error) 8210a1b0b38SDarrick J. Wong goto out_error; 8220a1b0b38SDarrick J. Wong } else if (have_gt && 8230a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock && 8240a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset)) { 8250a1b0b38SDarrick J. Wong /* 8260a1b0b38SDarrick J. Wong * right edge contiguous, merge into right record. 8270a1b0b38SDarrick J. Wong * 8280a1b0b38SDarrick J. Wong * gtbno gtlen 8290a1b0b38SDarrick J. Wong * Orig: |ooooooooo| 8300a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa| 8310a1b0b38SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 8320a1b0b38SDarrick J. Wong * bno len 8330a1b0b38SDarrick J. Wong */ 8340a1b0b38SDarrick J. Wong gtrec.rm_startblock = bno; 8350a1b0b38SDarrick J. Wong gtrec.rm_blockcount += len; 8360a1b0b38SDarrick J. Wong if (!ignore_off) 8370a1b0b38SDarrick J. Wong gtrec.rm_offset = offset; 8380a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, >rec); 8390a1b0b38SDarrick J. Wong if (error) 8400a1b0b38SDarrick J. Wong goto out_error; 8410a1b0b38SDarrick J. Wong } else { 8420a1b0b38SDarrick J. Wong /* 8430a1b0b38SDarrick J. Wong * no contiguous edge with identical owner, insert 8440a1b0b38SDarrick J. Wong * new record at current cursor position. 8450a1b0b38SDarrick J. Wong */ 8460a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno; 8470a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len; 8480a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_owner = owner; 8490a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_offset = offset; 8500a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_flags = flags; 8510a1b0b38SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, 8520a1b0b38SDarrick J. Wong owner, offset, flags); 8530a1b0b38SDarrick J. Wong error = xfs_btree_insert(cur, &i); 8540a1b0b38SDarrick J. Wong if (error) 8550a1b0b38SDarrick J. Wong goto out_error; 8560a1b0b38SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 8570a1b0b38SDarrick J. Wong } 8580a1b0b38SDarrick J. Wong 8590a1b0b38SDarrick J. Wong trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, 8600a1b0b38SDarrick J. Wong unwritten, oinfo); 8610a1b0b38SDarrick J. Wong out_error: 8620a1b0b38SDarrick J. Wong if (error) 8630a1b0b38SDarrick J. Wong trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno, 8640a1b0b38SDarrick J. Wong error, _RET_IP_); 8650a1b0b38SDarrick J. Wong return error; 8660a1b0b38SDarrick J. Wong } 8670a1b0b38SDarrick J. Wong 8680a1b0b38SDarrick J. Wong /* 8690a1b0b38SDarrick J. Wong * Add a reference to an extent in the rmap btree. 8700a1b0b38SDarrick J. Wong */ 871673930c3SDarrick J. Wong int 872673930c3SDarrick J. Wong xfs_rmap_alloc( 873673930c3SDarrick J. Wong struct xfs_trans *tp, 874673930c3SDarrick J. Wong struct xfs_buf *agbp, 875673930c3SDarrick J. Wong xfs_agnumber_t agno, 876673930c3SDarrick J. Wong xfs_agblock_t bno, 877673930c3SDarrick J. Wong xfs_extlen_t len, 878673930c3SDarrick J. Wong struct xfs_owner_info *oinfo) 879673930c3SDarrick J. Wong { 880673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 8810a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur; 8820a1b0b38SDarrick J. Wong int error; 883673930c3SDarrick J. Wong 884673930c3SDarrick J. Wong if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 885673930c3SDarrick J. Wong return 0; 886673930c3SDarrick J. Wong 8870a1b0b38SDarrick J. Wong cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 8880a1b0b38SDarrick J. Wong error = xfs_rmap_map(cur, bno, len, false, oinfo); 8890a1b0b38SDarrick J. Wong if (error) 890673930c3SDarrick J. Wong goto out_error; 8910a1b0b38SDarrick J. Wong 8920a1b0b38SDarrick J. Wong xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 893673930c3SDarrick J. Wong return 0; 894673930c3SDarrick J. Wong 895673930c3SDarrick J. Wong out_error: 8960a1b0b38SDarrick J. Wong xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 897673930c3SDarrick J. Wong return error; 898673930c3SDarrick J. Wong } 899c543838aSDarrick J. Wong 900fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG (1 << 0) 901fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG (1 << 1) 902fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING (1 << 2) 903fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING (1 << 3) 904fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID (1 << 6) 905fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID (1 << 7) 906fb7d9267SDarrick J. Wong 907fb7d9267SDarrick J. Wong #define LEFT r[0] 908fb7d9267SDarrick J. Wong #define RIGHT r[1] 909fb7d9267SDarrick J. Wong #define PREV r[2] 910fb7d9267SDarrick J. Wong #define NEW r[3] 911fb7d9267SDarrick J. Wong 912fb7d9267SDarrick J. Wong /* 913fb7d9267SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. 914fb7d9267SDarrick J. Wong * Does not handle overlapping extents. 915fb7d9267SDarrick J. Wong */ 916fb7d9267SDarrick J. Wong STATIC int 917fb7d9267SDarrick J. Wong xfs_rmap_convert( 918fb7d9267SDarrick J. Wong struct xfs_btree_cur *cur, 919fb7d9267SDarrick J. Wong xfs_agblock_t bno, 920fb7d9267SDarrick J. Wong xfs_extlen_t len, 921fb7d9267SDarrick J. Wong bool unwritten, 922fb7d9267SDarrick J. Wong struct xfs_owner_info *oinfo) 923fb7d9267SDarrick J. Wong { 924fb7d9267SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 925fb7d9267SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 926fb7d9267SDarrick J. Wong /* left is 0, right is 1, prev is 2 */ 927fb7d9267SDarrick J. Wong /* new is 3 */ 928fb7d9267SDarrick J. Wong uint64_t owner; 929fb7d9267SDarrick J. Wong uint64_t offset; 930fb7d9267SDarrick J. Wong uint64_t new_endoff; 931fb7d9267SDarrick J. Wong unsigned int oldext; 932fb7d9267SDarrick J. Wong unsigned int newext; 933fb7d9267SDarrick J. Wong unsigned int flags = 0; 934fb7d9267SDarrick J. Wong int i; 935fb7d9267SDarrick J. Wong int state = 0; 936fb7d9267SDarrick J. Wong int error; 937fb7d9267SDarrick J. Wong 938fb7d9267SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 939fb7d9267SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 940fb7d9267SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 941fb7d9267SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 942fb7d9267SDarrick J. Wong new_endoff = offset + len; 943fb7d9267SDarrick J. Wong trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, 944fb7d9267SDarrick J. Wong unwritten, oinfo); 945fb7d9267SDarrick J. Wong 946fb7d9267SDarrick J. Wong /* 947fb7d9267SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent 948fb7d9267SDarrick J. Wong * record for our insertion point. This will also give us the record for 949fb7d9267SDarrick J. Wong * start block contiguity tests. 950fb7d9267SDarrick J. Wong */ 951fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); 952fb7d9267SDarrick J. Wong if (error) 953fb7d9267SDarrick J. Wong goto done; 954fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 955fb7d9267SDarrick J. Wong 956fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &PREV, &i); 957fb7d9267SDarrick J. Wong if (error) 958fb7d9267SDarrick J. Wong goto done; 959fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 960fb7d9267SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, 961fb7d9267SDarrick J. Wong cur->bc_private.a.agno, PREV.rm_startblock, 962fb7d9267SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 963fb7d9267SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 964fb7d9267SDarrick J. Wong 965fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 966fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 967fb7d9267SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 968fb7d9267SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 969fb7d9267SDarrick J. Wong 970fb7d9267SDarrick J. Wong /* 971fb7d9267SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 972fb7d9267SDarrick J. Wong * extent is being replaced by a newext allocation. 973fb7d9267SDarrick J. Wong */ 974fb7d9267SDarrick J. Wong if (PREV.rm_offset == offset) 975fb7d9267SDarrick J. Wong state |= RMAP_LEFT_FILLING; 976fb7d9267SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 977fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 978fb7d9267SDarrick J. Wong 979fb7d9267SDarrick J. Wong /* 980fb7d9267SDarrick J. Wong * Decrement the cursor to see if we have a left-adjacent record to our 981fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 982fb7d9267SDarrick J. Wong * contiguity tests. 983fb7d9267SDarrick J. Wong */ 984fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 985fb7d9267SDarrick J. Wong if (error) 986fb7d9267SDarrick J. Wong goto done; 987fb7d9267SDarrick J. Wong if (i) { 988fb7d9267SDarrick J. Wong state |= RMAP_LEFT_VALID; 989fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &LEFT, &i); 990fb7d9267SDarrick J. Wong if (error) 991fb7d9267SDarrick J. Wong goto done; 992fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 993fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 994fb7d9267SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount <= bno, 995fb7d9267SDarrick J. Wong done); 996fb7d9267SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, 997fb7d9267SDarrick J. Wong cur->bc_private.a.agno, LEFT.rm_startblock, 998fb7d9267SDarrick J. Wong LEFT.rm_blockcount, LEFT.rm_owner, 999fb7d9267SDarrick J. Wong LEFT.rm_offset, LEFT.rm_flags); 1000fb7d9267SDarrick J. Wong if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && 1001fb7d9267SDarrick J. Wong LEFT.rm_offset + LEFT.rm_blockcount == offset && 1002fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&LEFT, owner, newext)) 1003fb7d9267SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 1004fb7d9267SDarrick J. Wong } 1005fb7d9267SDarrick J. Wong 1006fb7d9267SDarrick J. Wong /* 1007fb7d9267SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our 1008fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block 1009fb7d9267SDarrick J. Wong * contiguity tests. 1010fb7d9267SDarrick J. Wong */ 1011fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1012fb7d9267SDarrick J. Wong if (error) 1013fb7d9267SDarrick J. Wong goto done; 1014fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1015fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1016fb7d9267SDarrick J. Wong if (error) 1017fb7d9267SDarrick J. Wong goto done; 1018fb7d9267SDarrick J. Wong if (i) { 1019fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_VALID; 1020fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 1021fb7d9267SDarrick J. Wong if (error) 1022fb7d9267SDarrick J. Wong goto done; 1023fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1024fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, 1025fb7d9267SDarrick J. Wong done); 1026fb7d9267SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 1027fb7d9267SDarrick J. Wong cur->bc_private.a.agno, RIGHT.rm_startblock, 1028fb7d9267SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 1029fb7d9267SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 1030fb7d9267SDarrick J. Wong if (bno + len == RIGHT.rm_startblock && 1031fb7d9267SDarrick J. Wong offset + len == RIGHT.rm_offset && 1032fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 1033fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 1034fb7d9267SDarrick J. Wong } 1035fb7d9267SDarrick J. Wong 1036fb7d9267SDarrick J. Wong /* check that left + prev + right is not too long */ 1037fb7d9267SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1038fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 1039fb7d9267SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1040fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 1041fb7d9267SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 1042fb7d9267SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 1043fb7d9267SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 1044fb7d9267SDarrick J. Wong 1045fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 1046fb7d9267SDarrick J. Wong _RET_IP_); 1047fb7d9267SDarrick J. Wong 1048fb7d9267SDarrick J. Wong /* reset the cursor back to PREV */ 1049fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); 1050fb7d9267SDarrick J. Wong if (error) 1051fb7d9267SDarrick J. Wong goto done; 1052fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1053fb7d9267SDarrick J. Wong 1054fb7d9267SDarrick J. Wong /* 1055fb7d9267SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 1056fb7d9267SDarrick J. Wong */ 1057fb7d9267SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1058fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 1059fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 1060fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1061fb7d9267SDarrick J. Wong /* 1062fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1063fb7d9267SDarrick J. Wong * The left and right neighbors are both contiguous with new. 1064fb7d9267SDarrick J. Wong */ 1065fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1066fb7d9267SDarrick J. Wong if (error) 1067fb7d9267SDarrick J. Wong goto done; 1068fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1069fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1070fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1071fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1072fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1073fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1074fb7d9267SDarrick J. Wong if (error) 1075fb7d9267SDarrick J. Wong goto done; 1076fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1077fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1078fb7d9267SDarrick J. Wong if (error) 1079fb7d9267SDarrick J. Wong goto done; 1080fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1081fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1082fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1083fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1084fb7d9267SDarrick J. Wong PREV.rm_flags); 1085fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1086fb7d9267SDarrick J. Wong if (error) 1087fb7d9267SDarrick J. Wong goto done; 1088fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1089fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1090fb7d9267SDarrick J. Wong if (error) 1091fb7d9267SDarrick J. Wong goto done; 1092fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1093fb7d9267SDarrick J. Wong NEW = LEFT; 1094fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 1095fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1096fb7d9267SDarrick J. Wong if (error) 1097fb7d9267SDarrick J. Wong goto done; 1098fb7d9267SDarrick J. Wong break; 1099fb7d9267SDarrick J. Wong 1100fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1101fb7d9267SDarrick J. Wong /* 1102fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1103fb7d9267SDarrick J. Wong * The left neighbor is contiguous, the right is not. 1104fb7d9267SDarrick J. Wong */ 1105fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1106fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount, 1107fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset, 1108fb7d9267SDarrick J. Wong PREV.rm_flags); 1109fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1110fb7d9267SDarrick J. Wong if (error) 1111fb7d9267SDarrick J. Wong goto done; 1112fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1113fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1114fb7d9267SDarrick J. Wong if (error) 1115fb7d9267SDarrick J. Wong goto done; 1116fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1117fb7d9267SDarrick J. Wong NEW = LEFT; 1118fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 1119fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1120fb7d9267SDarrick J. Wong if (error) 1121fb7d9267SDarrick J. Wong goto done; 1122fb7d9267SDarrick J. Wong break; 1123fb7d9267SDarrick J. Wong 1124fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1125fb7d9267SDarrick J. Wong /* 1126fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1127fb7d9267SDarrick J. Wong * The right neighbor is contiguous, the left is not. 1128fb7d9267SDarrick J. Wong */ 1129fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1130fb7d9267SDarrick J. Wong if (error) 1131fb7d9267SDarrick J. Wong goto done; 1132fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1133fb7d9267SDarrick J. Wong trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, 1134fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount, 1135fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset, 1136fb7d9267SDarrick J. Wong RIGHT.rm_flags); 1137fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i); 1138fb7d9267SDarrick J. Wong if (error) 1139fb7d9267SDarrick J. Wong goto done; 1140fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1141fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1142fb7d9267SDarrick J. Wong if (error) 1143fb7d9267SDarrick J. Wong goto done; 1144fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1145fb7d9267SDarrick J. Wong NEW = PREV; 1146fb7d9267SDarrick J. Wong NEW.rm_blockcount = len + RIGHT.rm_blockcount; 1147fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1148fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1149fb7d9267SDarrick J. Wong if (error) 1150fb7d9267SDarrick J. Wong goto done; 1151fb7d9267SDarrick J. Wong break; 1152fb7d9267SDarrick J. Wong 1153fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 1154fb7d9267SDarrick J. Wong /* 1155fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext. 1156fb7d9267SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 1157fb7d9267SDarrick J. Wong * the new one. 1158fb7d9267SDarrick J. Wong */ 1159fb7d9267SDarrick J. Wong NEW = PREV; 1160fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1161fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1162fb7d9267SDarrick J. Wong if (error) 1163fb7d9267SDarrick J. Wong goto done; 1164fb7d9267SDarrick J. Wong break; 1165fb7d9267SDarrick J. Wong 1166fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 1167fb7d9267SDarrick J. Wong /* 1168fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1169fb7d9267SDarrick J. Wong * The left neighbor is contiguous. 1170fb7d9267SDarrick J. Wong */ 1171fb7d9267SDarrick J. Wong NEW = PREV; 1172fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1173fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1174fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1175fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1176fb7d9267SDarrick J. Wong if (error) 1177fb7d9267SDarrick J. Wong goto done; 1178fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i); 1179fb7d9267SDarrick J. Wong if (error) 1180fb7d9267SDarrick J. Wong goto done; 1181fb7d9267SDarrick J. Wong NEW = LEFT; 1182fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1183fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1184fb7d9267SDarrick J. Wong if (error) 1185fb7d9267SDarrick J. Wong goto done; 1186fb7d9267SDarrick J. Wong break; 1187fb7d9267SDarrick J. Wong 1188fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING: 1189fb7d9267SDarrick J. Wong /* 1190fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 1191fb7d9267SDarrick J. Wong * The left neighbor is not contiguous. 1192fb7d9267SDarrick J. Wong */ 1193fb7d9267SDarrick J. Wong NEW = PREV; 1194fb7d9267SDarrick J. Wong NEW.rm_startblock += len; 1195fb7d9267SDarrick J. Wong NEW.rm_offset += len; 1196fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1197fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1198fb7d9267SDarrick J. Wong if (error) 1199fb7d9267SDarrick J. Wong goto done; 1200fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1201fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1202fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1203fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1204fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1205fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1206fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, 1207fb7d9267SDarrick J. Wong len, owner, offset, newext); 1208fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1209fb7d9267SDarrick J. Wong if (error) 1210fb7d9267SDarrick J. Wong goto done; 1211fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1212fb7d9267SDarrick J. Wong break; 1213fb7d9267SDarrick J. Wong 1214fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 1215fb7d9267SDarrick J. Wong /* 1216fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1217fb7d9267SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 1218fb7d9267SDarrick J. Wong */ 1219fb7d9267SDarrick J. Wong NEW = PREV; 1220fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1221fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1222fb7d9267SDarrick J. Wong if (error) 1223fb7d9267SDarrick J. Wong goto done; 1224fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i); 1225fb7d9267SDarrick J. Wong if (error) 1226fb7d9267SDarrick J. Wong goto done; 1227fb7d9267SDarrick J. Wong NEW = RIGHT; 1228fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1229fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1230fb7d9267SDarrick J. Wong NEW.rm_blockcount += len; 1231fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1232fb7d9267SDarrick J. Wong if (error) 1233fb7d9267SDarrick J. Wong goto done; 1234fb7d9267SDarrick J. Wong break; 1235fb7d9267SDarrick J. Wong 1236fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING: 1237fb7d9267SDarrick J. Wong /* 1238fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 1239fb7d9267SDarrick J. Wong * The right neighbor is not contiguous. 1240fb7d9267SDarrick J. Wong */ 1241fb7d9267SDarrick J. Wong NEW = PREV; 1242fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len; 1243fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1244fb7d9267SDarrick J. Wong if (error) 1245fb7d9267SDarrick J. Wong goto done; 1246fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1247fb7d9267SDarrick J. Wong oldext, &i); 1248fb7d9267SDarrick J. Wong if (error) 1249fb7d9267SDarrick J. Wong goto done; 1250fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); 1251fb7d9267SDarrick J. Wong NEW.rm_startblock = bno; 1252fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1253fb7d9267SDarrick J. Wong NEW.rm_offset = offset; 1254fb7d9267SDarrick J. Wong NEW.rm_blockcount = len; 1255fb7d9267SDarrick J. Wong NEW.rm_flags = newext; 1256fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1257fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, 1258fb7d9267SDarrick J. Wong len, owner, offset, newext); 1259fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1260fb7d9267SDarrick J. Wong if (error) 1261fb7d9267SDarrick J. Wong goto done; 1262fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1263fb7d9267SDarrick J. Wong break; 1264fb7d9267SDarrick J. Wong 1265fb7d9267SDarrick J. Wong case 0: 1266fb7d9267SDarrick J. Wong /* 1267fb7d9267SDarrick J. Wong * Setting the middle part of a previous oldext extent to 1268fb7d9267SDarrick J. Wong * newext. Contiguity is impossible here. 1269fb7d9267SDarrick J. Wong * One extent becomes three extents. 1270fb7d9267SDarrick J. Wong */ 1271fb7d9267SDarrick J. Wong /* new right extent - oldext */ 1272fb7d9267SDarrick J. Wong NEW.rm_startblock = bno + len; 1273fb7d9267SDarrick J. Wong NEW.rm_owner = owner; 1274fb7d9267SDarrick J. Wong NEW.rm_offset = new_endoff; 1275fb7d9267SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 1276fb7d9267SDarrick J. Wong new_endoff; 1277fb7d9267SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 1278fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 1279fb7d9267SDarrick J. Wong if (error) 1280fb7d9267SDarrick J. Wong goto done; 1281fb7d9267SDarrick J. Wong /* new left extent - oldext */ 1282fb7d9267SDarrick J. Wong NEW = PREV; 1283fb7d9267SDarrick J. Wong NEW.rm_blockcount = offset - PREV.rm_offset; 1284fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW; 1285fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, 1286fb7d9267SDarrick J. Wong NEW.rm_startblock, NEW.rm_blockcount, 1287fb7d9267SDarrick J. Wong NEW.rm_owner, NEW.rm_offset, 1288fb7d9267SDarrick J. Wong NEW.rm_flags); 1289fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1290fb7d9267SDarrick J. Wong if (error) 1291fb7d9267SDarrick J. Wong goto done; 1292fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1293fb7d9267SDarrick J. Wong /* 1294fb7d9267SDarrick J. Wong * Reset the cursor to the position of the new extent 1295fb7d9267SDarrick J. Wong * we are about to insert as we can't trust it after 1296fb7d9267SDarrick J. Wong * the previous insert. 1297fb7d9267SDarrick J. Wong */ 1298fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, 1299fb7d9267SDarrick J. Wong oldext, &i); 1300fb7d9267SDarrick J. Wong if (error) 1301fb7d9267SDarrick J. Wong goto done; 1302fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); 1303fb7d9267SDarrick J. Wong /* new middle extent - newext */ 1304fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; 1305fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags |= newext; 1306fb7d9267SDarrick J. Wong trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len, 1307fb7d9267SDarrick J. Wong owner, offset, newext); 1308fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i); 1309fb7d9267SDarrick J. Wong if (error) 1310fb7d9267SDarrick J. Wong goto done; 1311fb7d9267SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 1312fb7d9267SDarrick J. Wong break; 1313fb7d9267SDarrick J. Wong 1314fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1315fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1316fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 1317fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 1318fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 1319fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG: 1320fb7d9267SDarrick J. Wong case RMAP_RIGHT_CONTIG: 1321fb7d9267SDarrick J. Wong /* 1322fb7d9267SDarrick J. Wong * These cases are all impossible. 1323fb7d9267SDarrick J. Wong */ 1324fb7d9267SDarrick J. Wong ASSERT(0); 1325fb7d9267SDarrick J. Wong } 1326fb7d9267SDarrick J. Wong 1327fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, 1328fb7d9267SDarrick J. Wong unwritten, oinfo); 1329fb7d9267SDarrick J. Wong done: 1330fb7d9267SDarrick J. Wong if (error) 1331fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 1332fb7d9267SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 1333fb7d9267SDarrick J. Wong return error; 1334fb7d9267SDarrick J. Wong } 1335fb7d9267SDarrick J. Wong 13363f165b33SDarrick J. Wong /* 13373f165b33SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. If there is no 13383f165b33SDarrick J. Wong * possibility of overlapping extents, delegate to the simpler convert 13393f165b33SDarrick J. Wong * function. 13403f165b33SDarrick J. Wong */ 13413f165b33SDarrick J. Wong STATIC int 13423f165b33SDarrick J. Wong xfs_rmap_convert_shared( 13433f165b33SDarrick J. Wong struct xfs_btree_cur *cur, 13443f165b33SDarrick J. Wong xfs_agblock_t bno, 13453f165b33SDarrick J. Wong xfs_extlen_t len, 13463f165b33SDarrick J. Wong bool unwritten, 13473f165b33SDarrick J. Wong struct xfs_owner_info *oinfo) 13483f165b33SDarrick J. Wong { 13493f165b33SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 13503f165b33SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */ 13513f165b33SDarrick J. Wong /* left is 0, right is 1, prev is 2 */ 13523f165b33SDarrick J. Wong /* new is 3 */ 13533f165b33SDarrick J. Wong uint64_t owner; 13543f165b33SDarrick J. Wong uint64_t offset; 13553f165b33SDarrick J. Wong uint64_t new_endoff; 13563f165b33SDarrick J. Wong unsigned int oldext; 13573f165b33SDarrick J. Wong unsigned int newext; 13583f165b33SDarrick J. Wong unsigned int flags = 0; 13593f165b33SDarrick J. Wong int i; 13603f165b33SDarrick J. Wong int state = 0; 13613f165b33SDarrick J. Wong int error; 13623f165b33SDarrick J. Wong 13633f165b33SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 13643f165b33SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || 13653f165b33SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); 13663f165b33SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; 13673f165b33SDarrick J. Wong new_endoff = offset + len; 13683f165b33SDarrick J. Wong trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, 13693f165b33SDarrick J. Wong unwritten, oinfo); 13703f165b33SDarrick J. Wong 13713f165b33SDarrick J. Wong /* 13723f165b33SDarrick J. Wong * For the initial lookup, look for and exact match or the left-adjacent 13733f165b33SDarrick J. Wong * record for our insertion point. This will also give us the record for 13743f165b33SDarrick J. Wong * start block contiguity tests. 13753f165b33SDarrick J. Wong */ 13763f165b33SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 13773f165b33SDarrick J. Wong &PREV, &i); 13783f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 13793f165b33SDarrick J. Wong 13803f165b33SDarrick J. Wong ASSERT(PREV.rm_offset <= offset); 13813f165b33SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); 13823f165b33SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); 13833f165b33SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN; 13843f165b33SDarrick J. Wong 13853f165b33SDarrick J. Wong /* 13863f165b33SDarrick J. Wong * Set flags determining what part of the previous oldext allocation 13873f165b33SDarrick J. Wong * extent is being replaced by a newext allocation. 13883f165b33SDarrick J. Wong */ 13893f165b33SDarrick J. Wong if (PREV.rm_offset == offset) 13903f165b33SDarrick J. Wong state |= RMAP_LEFT_FILLING; 13913f165b33SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) 13923f165b33SDarrick J. Wong state |= RMAP_RIGHT_FILLING; 13933f165b33SDarrick J. Wong 13943f165b33SDarrick J. Wong /* Is there a left record that abuts our range? */ 13953f165b33SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, 13963f165b33SDarrick J. Wong &LEFT, &i); 13973f165b33SDarrick J. Wong if (error) 13983f165b33SDarrick J. Wong goto done; 13993f165b33SDarrick J. Wong if (i) { 14003f165b33SDarrick J. Wong state |= RMAP_LEFT_VALID; 14013f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, 14023f165b33SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount <= bno, 14033f165b33SDarrick J. Wong done); 14043f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) 14053f165b33SDarrick J. Wong state |= RMAP_LEFT_CONTIG; 14063f165b33SDarrick J. Wong } 14073f165b33SDarrick J. Wong 14083f165b33SDarrick J. Wong /* Is there a right record that abuts our range? */ 14093f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 14103f165b33SDarrick J. Wong newext, &i); 14113f165b33SDarrick J. Wong if (error) 14123f165b33SDarrick J. Wong goto done; 14133f165b33SDarrick J. Wong if (i) { 14143f165b33SDarrick J. Wong state |= RMAP_RIGHT_VALID; 14153f165b33SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i); 14163f165b33SDarrick J. Wong if (error) 14173f165b33SDarrick J. Wong goto done; 14183f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 14193f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, 14203f165b33SDarrick J. Wong done); 14213f165b33SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 14223f165b33SDarrick J. Wong cur->bc_private.a.agno, RIGHT.rm_startblock, 14233f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 14243f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 14253f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&RIGHT, owner, newext)) 14263f165b33SDarrick J. Wong state |= RMAP_RIGHT_CONTIG; 14273f165b33SDarrick J. Wong } 14283f165b33SDarrick J. Wong 14293f165b33SDarrick J. Wong /* check that left + prev + right is not too long */ 14303f165b33SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14313f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == 14323f165b33SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14333f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && 14343f165b33SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len + 14353f165b33SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) 14363f165b33SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG; 14373f165b33SDarrick J. Wong 14383f165b33SDarrick J. Wong trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, 14393f165b33SDarrick J. Wong _RET_IP_); 14403f165b33SDarrick J. Wong /* 14413f165b33SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits. 14423f165b33SDarrick J. Wong */ 14433f165b33SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14443f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { 14453f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | 14463f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 14473f165b33SDarrick J. Wong /* 14483f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 14493f165b33SDarrick J. Wong * The left and right neighbors are both contiguous with new. 14503f165b33SDarrick J. Wong */ 14513f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 14523f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 14533f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 14543f165b33SDarrick J. Wong if (error) 14553f165b33SDarrick J. Wong goto done; 14563f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 14573f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 14583f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 14593f165b33SDarrick J. Wong if (error) 14603f165b33SDarrick J. Wong goto done; 14613f165b33SDarrick J. Wong NEW = LEFT; 14623f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 14633f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 14643f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 14653f165b33SDarrick J. Wong if (error) 14663f165b33SDarrick J. Wong goto done; 14673f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 14683f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; 14693f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 14703f165b33SDarrick J. Wong if (error) 14713f165b33SDarrick J. Wong goto done; 14723f165b33SDarrick J. Wong break; 14733f165b33SDarrick J. Wong 14743f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 14753f165b33SDarrick J. Wong /* 14763f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 14773f165b33SDarrick J. Wong * The left neighbor is contiguous, the right is not. 14783f165b33SDarrick J. Wong */ 14793f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock, 14803f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner, 14813f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags); 14823f165b33SDarrick J. Wong if (error) 14833f165b33SDarrick J. Wong goto done; 14843f165b33SDarrick J. Wong NEW = LEFT; 14853f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 14863f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 14873f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 14883f165b33SDarrick J. Wong if (error) 14893f165b33SDarrick J. Wong goto done; 14903f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 14913f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount; 14923f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 14933f165b33SDarrick J. Wong if (error) 14943f165b33SDarrick J. Wong goto done; 14953f165b33SDarrick J. Wong break; 14963f165b33SDarrick J. Wong 14973f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 14983f165b33SDarrick J. Wong /* 14993f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 15003f165b33SDarrick J. Wong * The right neighbor is contiguous, the left is not. 15013f165b33SDarrick J. Wong */ 15023f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock, 15033f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner, 15043f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags); 15053f165b33SDarrick J. Wong if (error) 15063f165b33SDarrick J. Wong goto done; 15073f165b33SDarrick J. Wong NEW = PREV; 15083f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 15093f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15103f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 15113f165b33SDarrick J. Wong if (error) 15123f165b33SDarrick J. Wong goto done; 15133f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 15143f165b33SDarrick J. Wong NEW.rm_blockcount += RIGHT.rm_blockcount; 15153f165b33SDarrick J. Wong NEW.rm_flags = RIGHT.rm_flags; 15163f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15173f165b33SDarrick J. Wong if (error) 15183f165b33SDarrick J. Wong goto done; 15193f165b33SDarrick J. Wong break; 15203f165b33SDarrick J. Wong 15213f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: 15223f165b33SDarrick J. Wong /* 15233f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext. 15243f165b33SDarrick J. Wong * Neither the left nor right neighbors are contiguous with 15253f165b33SDarrick J. Wong * the new one. 15263f165b33SDarrick J. Wong */ 15273f165b33SDarrick J. Wong NEW = PREV; 15283f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 15293f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15303f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 15313f165b33SDarrick J. Wong if (error) 15323f165b33SDarrick J. Wong goto done; 15333f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 15343f165b33SDarrick J. Wong NEW.rm_flags = newext; 15353f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15363f165b33SDarrick J. Wong if (error) 15373f165b33SDarrick J. Wong goto done; 15383f165b33SDarrick J. Wong break; 15393f165b33SDarrick J. Wong 15403f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: 15413f165b33SDarrick J. Wong /* 15423f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 15433f165b33SDarrick J. Wong * The left neighbor is contiguous. 15443f165b33SDarrick J. Wong */ 15453f165b33SDarrick J. Wong NEW = PREV; 15463f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 15473f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15483f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15493f165b33SDarrick J. Wong if (error) 15503f165b33SDarrick J. Wong goto done; 15513f165b33SDarrick J. Wong NEW.rm_offset += len; 15523f165b33SDarrick J. Wong NEW.rm_startblock += len; 15533f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 15543f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 15553f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15563f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15573f165b33SDarrick J. Wong if (error) 15583f165b33SDarrick J. Wong goto done; 15593f165b33SDarrick J. Wong NEW = LEFT; 15603f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 15613f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15623f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 15633f165b33SDarrick J. Wong if (error) 15643f165b33SDarrick J. Wong goto done; 15653f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 15663f165b33SDarrick J. Wong NEW.rm_blockcount += len; 15673f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 15683f165b33SDarrick J. Wong if (error) 15693f165b33SDarrick J. Wong goto done; 15703f165b33SDarrick J. Wong break; 15713f165b33SDarrick J. Wong 15723f165b33SDarrick J. Wong case RMAP_LEFT_FILLING: 15733f165b33SDarrick J. Wong /* 15743f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext. 15753f165b33SDarrick J. Wong * The left neighbor is not contiguous. 15763f165b33SDarrick J. Wong */ 15773f165b33SDarrick J. Wong NEW = PREV; 15783f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 15793f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15803f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15813f165b33SDarrick J. Wong if (error) 15823f165b33SDarrick J. Wong goto done; 15833f165b33SDarrick J. Wong NEW.rm_offset += len; 15843f165b33SDarrick J. Wong NEW.rm_startblock += len; 15853f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 15863f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 15873f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 15883f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 15893f165b33SDarrick J. Wong if (error) 15903f165b33SDarrick J. Wong goto done; 15913f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 15923f165b33SDarrick J. Wong if (error) 15933f165b33SDarrick J. Wong goto done; 15943f165b33SDarrick J. Wong break; 15953f165b33SDarrick J. Wong 15963f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: 15973f165b33SDarrick J. Wong /* 15983f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 15993f165b33SDarrick J. Wong * The right neighbor is contiguous with the new allocation. 16003f165b33SDarrick J. Wong */ 16013f165b33SDarrick J. Wong NEW = PREV; 16023f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16033f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16043f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16053f165b33SDarrick J. Wong if (error) 16063f165b33SDarrick J. Wong goto done; 16073f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 16083f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 16093f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16103f165b33SDarrick J. Wong if (error) 16113f165b33SDarrick J. Wong goto done; 16123f165b33SDarrick J. Wong NEW = RIGHT; 16133f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock, 16143f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16153f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 16163f165b33SDarrick J. Wong if (error) 16173f165b33SDarrick J. Wong goto done; 16183f165b33SDarrick J. Wong NEW.rm_offset = offset; 16193f165b33SDarrick J. Wong NEW.rm_startblock = bno; 16203f165b33SDarrick J. Wong NEW.rm_blockcount += len; 16213f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 16223f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16233f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags); 16243f165b33SDarrick J. Wong if (error) 16253f165b33SDarrick J. Wong goto done; 16263f165b33SDarrick J. Wong break; 16273f165b33SDarrick J. Wong 16283f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING: 16293f165b33SDarrick J. Wong /* 16303f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext. 16313f165b33SDarrick J. Wong * The right neighbor is not contiguous. 16323f165b33SDarrick J. Wong */ 16333f165b33SDarrick J. Wong NEW = PREV; 16343f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16353f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16363f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16373f165b33SDarrick J. Wong if (error) 16383f165b33SDarrick J. Wong goto done; 16393f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 16403f165b33SDarrick J. Wong NEW.rm_blockcount -= len; 16413f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16423f165b33SDarrick J. Wong if (error) 16433f165b33SDarrick J. Wong goto done; 16443f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext); 16453f165b33SDarrick J. Wong if (error) 16463f165b33SDarrick J. Wong goto done; 16473f165b33SDarrick J. Wong break; 16483f165b33SDarrick J. Wong 16493f165b33SDarrick J. Wong case 0: 16503f165b33SDarrick J. Wong /* 16513f165b33SDarrick J. Wong * Setting the middle part of a previous oldext extent to 16523f165b33SDarrick J. Wong * newext. Contiguity is impossible here. 16533f165b33SDarrick J. Wong * One extent becomes three extents. 16543f165b33SDarrick J. Wong */ 16553f165b33SDarrick J. Wong /* new right extent - oldext */ 16563f165b33SDarrick J. Wong NEW.rm_startblock = bno + len; 16573f165b33SDarrick J. Wong NEW.rm_owner = owner; 16583f165b33SDarrick J. Wong NEW.rm_offset = new_endoff; 16593f165b33SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - 16603f165b33SDarrick J. Wong new_endoff; 16613f165b33SDarrick J. Wong NEW.rm_flags = PREV.rm_flags; 16623f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 16633f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 16643f165b33SDarrick J. Wong NEW.rm_flags); 16653f165b33SDarrick J. Wong if (error) 16663f165b33SDarrick J. Wong goto done; 16673f165b33SDarrick J. Wong /* new left extent - oldext */ 16683f165b33SDarrick J. Wong NEW = PREV; 16693f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, 16703f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, 16713f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i); 16723f165b33SDarrick J. Wong if (error) 16733f165b33SDarrick J. Wong goto done; 16743f165b33SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); 16753f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset; 16763f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW); 16773f165b33SDarrick J. Wong if (error) 16783f165b33SDarrick J. Wong goto done; 16793f165b33SDarrick J. Wong /* new middle extent - newext */ 16803f165b33SDarrick J. Wong NEW.rm_startblock = bno; 16813f165b33SDarrick J. Wong NEW.rm_blockcount = len; 16823f165b33SDarrick J. Wong NEW.rm_owner = owner; 16833f165b33SDarrick J. Wong NEW.rm_offset = offset; 16843f165b33SDarrick J. Wong NEW.rm_flags = newext; 16853f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock, 16863f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, 16873f165b33SDarrick J. Wong NEW.rm_flags); 16883f165b33SDarrick J. Wong if (error) 16893f165b33SDarrick J. Wong goto done; 16903f165b33SDarrick J. Wong break; 16913f165b33SDarrick J. Wong 16923f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 16933f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 16943f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: 16953f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: 16963f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: 16973f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG: 16983f165b33SDarrick J. Wong case RMAP_RIGHT_CONTIG: 16993f165b33SDarrick J. Wong /* 17003f165b33SDarrick J. Wong * These cases are all impossible. 17013f165b33SDarrick J. Wong */ 17023f165b33SDarrick J. Wong ASSERT(0); 17033f165b33SDarrick J. Wong } 17043f165b33SDarrick J. Wong 17053f165b33SDarrick J. Wong trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, 17063f165b33SDarrick J. Wong unwritten, oinfo); 17073f165b33SDarrick J. Wong done: 17083f165b33SDarrick J. Wong if (error) 17093f165b33SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp, 17103f165b33SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 17113f165b33SDarrick J. Wong return error; 17123f165b33SDarrick J. Wong } 17133f165b33SDarrick J. Wong 1714fb7d9267SDarrick J. Wong #undef NEW 1715fb7d9267SDarrick J. Wong #undef LEFT 1716fb7d9267SDarrick J. Wong #undef RIGHT 1717fb7d9267SDarrick J. Wong #undef PREV 1718fb7d9267SDarrick J. Wong 1719ceeb9c83SDarrick J. Wong /* 1720ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and unmap it. For rmap extent types that 1721ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1722ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1723ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1724ceeb9c83SDarrick J. Wong * 1725ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1726ceeb9c83SDarrick J. Wong * so we can call the regular _free function. 1727ceeb9c83SDarrick J. Wong */ 1728ceeb9c83SDarrick J. Wong STATIC int 1729ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared( 1730ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1731ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1732ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1733ceeb9c83SDarrick J. Wong bool unwritten, 1734ceeb9c83SDarrick J. Wong struct xfs_owner_info *oinfo) 1735ceeb9c83SDarrick J. Wong { 1736ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1737ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 1738ceeb9c83SDarrick J. Wong uint64_t ltoff; 1739ceeb9c83SDarrick J. Wong int error = 0; 1740ceeb9c83SDarrick J. Wong int i; 1741ceeb9c83SDarrick J. Wong uint64_t owner; 1742ceeb9c83SDarrick J. Wong uint64_t offset; 1743ceeb9c83SDarrick J. Wong unsigned int flags; 1744ceeb9c83SDarrick J. Wong 1745ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1746ceeb9c83SDarrick J. Wong if (unwritten) 1747ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 1748ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, 1749ceeb9c83SDarrick J. Wong unwritten, oinfo); 1750ceeb9c83SDarrick J. Wong 1751ceeb9c83SDarrick J. Wong /* 1752ceeb9c83SDarrick J. Wong * We should always have a left record because there's a static record 1753ceeb9c83SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that 1754ceeb9c83SDarrick J. Wong * will not ever be removed from the tree. 1755ceeb9c83SDarrick J. Wong */ 1756ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, 1757ceeb9c83SDarrick J. Wong <rec, &i); 1758ceeb9c83SDarrick J. Wong if (error) 1759ceeb9c83SDarrick J. Wong goto out_error; 1760ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1761ceeb9c83SDarrick J. Wong ltoff = ltrec.rm_offset; 1762ceeb9c83SDarrick J. Wong 1763ceeb9c83SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */ 1764ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && 1765ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount >= 1766ceeb9c83SDarrick J. Wong bno + len, out_error); 1767ceeb9c83SDarrick J. Wong 1768ceeb9c83SDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */ 1769ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error); 1770ceeb9c83SDarrick J. Wong 1771ceeb9c83SDarrick J. Wong /* Make sure the unwritten flag matches. */ 1772ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == 1773ceeb9c83SDarrick J. Wong (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); 1774ceeb9c83SDarrick J. Wong 1775ceeb9c83SDarrick J. Wong /* Check the offset. */ 1776ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); 1777ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount, 1778ceeb9c83SDarrick J. Wong out_error); 1779ceeb9c83SDarrick J. Wong 1780ceeb9c83SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { 1781ceeb9c83SDarrick J. Wong /* Exact match, simply remove the record from rmap tree. */ 1782ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 1783ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1784ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1785ceeb9c83SDarrick J. Wong if (error) 1786ceeb9c83SDarrick J. Wong goto out_error; 1787ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock == bno) { 1788ceeb9c83SDarrick J. Wong /* 1789ceeb9c83SDarrick J. Wong * Overlap left hand side of extent: move the start, trim the 1790ceeb9c83SDarrick J. Wong * length and update the current record. 1791ceeb9c83SDarrick J. Wong * 1792ceeb9c83SDarrick J. Wong * ltbno ltlen 1793ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1794ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1795ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 1796ceeb9c83SDarrick J. Wong * bno len 1797ceeb9c83SDarrick J. Wong */ 1798ceeb9c83SDarrick J. Wong 1799ceeb9c83SDarrick J. Wong /* Delete prev rmap. */ 1800ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock, 1801ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1802ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1803ceeb9c83SDarrick J. Wong if (error) 1804ceeb9c83SDarrick J. Wong goto out_error; 1805ceeb9c83SDarrick J. Wong 1806ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset. */ 1807ceeb9c83SDarrick J. Wong ltrec.rm_startblock += len; 1808ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 1809ceeb9c83SDarrick J. Wong ltrec.rm_offset += len; 1810ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, ltrec.rm_startblock, 1811ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1812ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags); 1813ceeb9c83SDarrick J. Wong if (error) 1814ceeb9c83SDarrick J. Wong goto out_error; 1815ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { 1816ceeb9c83SDarrick J. Wong /* 1817ceeb9c83SDarrick J. Wong * Overlap right hand side of extent: trim the length and 1818ceeb9c83SDarrick J. Wong * update the current record. 1819ceeb9c83SDarrick J. Wong * 1820ceeb9c83SDarrick J. Wong * ltbno ltlen 1821ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1822ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1823ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr| 1824ceeb9c83SDarrick J. Wong * bno len 1825ceeb9c83SDarrick J. Wong */ 1826ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 1827ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1828ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 1829ceeb9c83SDarrick J. Wong if (error) 1830ceeb9c83SDarrick J. Wong goto out_error; 1831ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1832ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len; 1833ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 1834ceeb9c83SDarrick J. Wong if (error) 1835ceeb9c83SDarrick J. Wong goto out_error; 1836ceeb9c83SDarrick J. Wong } else { 1837ceeb9c83SDarrick J. Wong /* 1838ceeb9c83SDarrick J. Wong * Overlap middle of extent: trim the length of the existing 1839ceeb9c83SDarrick J. Wong * record to the length of the new left-extent size, increment 1840ceeb9c83SDarrick J. Wong * the insertion position so we can insert a new record 1841ceeb9c83SDarrick J. Wong * containing the remaining right-extent space. 1842ceeb9c83SDarrick J. Wong * 1843ceeb9c83SDarrick J. Wong * ltbno ltlen 1844ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo| 1845ceeb9c83SDarrick J. Wong * Freeing: |fffffffff| 1846ceeb9c83SDarrick J. Wong * Result: |rrrrr| |rrrr| 1847ceeb9c83SDarrick J. Wong * bno len 1848ceeb9c83SDarrick J. Wong */ 1849ceeb9c83SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount; 1850ceeb9c83SDarrick J. Wong 1851ceeb9c83SDarrick J. Wong /* Shrink the left side of the rmap */ 1852ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 1853ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1854ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 1855ceeb9c83SDarrick J. Wong if (error) 1856ceeb9c83SDarrick J. Wong goto out_error; 1857ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1858ceeb9c83SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock; 1859ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 1860ceeb9c83SDarrick J. Wong if (error) 1861ceeb9c83SDarrick J. Wong goto out_error; 1862ceeb9c83SDarrick J. Wong 1863ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset */ 1864ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno + len, 1865ceeb9c83SDarrick J. Wong orig_len - len - ltrec.rm_blockcount, 1866ceeb9c83SDarrick J. Wong ltrec.rm_owner, offset + len, 1867ceeb9c83SDarrick J. Wong ltrec.rm_flags); 1868ceeb9c83SDarrick J. Wong if (error) 1869ceeb9c83SDarrick J. Wong goto out_error; 1870ceeb9c83SDarrick J. Wong } 1871ceeb9c83SDarrick J. Wong 1872ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, 1873ceeb9c83SDarrick J. Wong unwritten, oinfo); 1874ceeb9c83SDarrick J. Wong out_error: 1875ceeb9c83SDarrick J. Wong if (error) 1876ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_error(cur->bc_mp, 1877ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 1878ceeb9c83SDarrick J. Wong return error; 1879ceeb9c83SDarrick J. Wong } 1880ceeb9c83SDarrick J. Wong 1881ceeb9c83SDarrick J. Wong /* 1882ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and map it. For rmap extent types that 1883ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful 1884ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner. 1885ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields. 1886ceeb9c83SDarrick J. Wong * 1887ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent, 1888ceeb9c83SDarrick J. Wong * so we can call the regular _alloc function. 1889ceeb9c83SDarrick J. Wong */ 1890ceeb9c83SDarrick J. Wong STATIC int 1891ceeb9c83SDarrick J. Wong xfs_rmap_map_shared( 1892ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur, 1893ceeb9c83SDarrick J. Wong xfs_agblock_t bno, 1894ceeb9c83SDarrick J. Wong xfs_extlen_t len, 1895ceeb9c83SDarrick J. Wong bool unwritten, 1896ceeb9c83SDarrick J. Wong struct xfs_owner_info *oinfo) 1897ceeb9c83SDarrick J. Wong { 1898ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 1899ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec; 1900ceeb9c83SDarrick J. Wong struct xfs_rmap_irec gtrec; 1901ceeb9c83SDarrick J. Wong int have_gt; 1902ceeb9c83SDarrick J. Wong int have_lt; 1903ceeb9c83SDarrick J. Wong int error = 0; 1904ceeb9c83SDarrick J. Wong int i; 1905ceeb9c83SDarrick J. Wong uint64_t owner; 1906ceeb9c83SDarrick J. Wong uint64_t offset; 1907ceeb9c83SDarrick J. Wong unsigned int flags = 0; 1908ceeb9c83SDarrick J. Wong 1909ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 1910ceeb9c83SDarrick J. Wong if (unwritten) 1911ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN; 1912ceeb9c83SDarrick J. Wong trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 1913ceeb9c83SDarrick J. Wong unwritten, oinfo); 1914ceeb9c83SDarrick J. Wong 1915ceeb9c83SDarrick J. Wong /* Is there a left record that abuts our range? */ 1916ceeb9c83SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, 1917ceeb9c83SDarrick J. Wong <rec, &have_lt); 1918ceeb9c83SDarrick J. Wong if (error) 1919ceeb9c83SDarrick J. Wong goto out_error; 1920ceeb9c83SDarrick J. Wong if (have_lt && 1921ceeb9c83SDarrick J. Wong !xfs_rmap_is_mergeable(<rec, owner, flags)) 1922ceeb9c83SDarrick J. Wong have_lt = 0; 1923ceeb9c83SDarrick J. Wong 1924ceeb9c83SDarrick J. Wong /* Is there a right record that abuts our range? */ 1925ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, 1926ceeb9c83SDarrick J. Wong flags, &have_gt); 1927ceeb9c83SDarrick J. Wong if (error) 1928ceeb9c83SDarrick J. Wong goto out_error; 1929ceeb9c83SDarrick J. Wong if (have_gt) { 1930ceeb9c83SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt); 1931ceeb9c83SDarrick J. Wong if (error) 1932ceeb9c83SDarrick J. Wong goto out_error; 1933ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); 1934ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, 1935ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, gtrec.rm_startblock, 1936ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 1937ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 1938ceeb9c83SDarrick J. Wong 1939ceeb9c83SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags)) 1940ceeb9c83SDarrick J. Wong have_gt = 0; 1941ceeb9c83SDarrick J. Wong } 1942ceeb9c83SDarrick J. Wong 1943ceeb9c83SDarrick J. Wong if (have_lt && 1944ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno && 1945ceeb9c83SDarrick J. Wong ltrec.rm_offset + ltrec.rm_blockcount == offset) { 1946ceeb9c83SDarrick J. Wong /* 1947ceeb9c83SDarrick J. Wong * Left edge contiguous, merge into left record. 1948ceeb9c83SDarrick J. Wong * 1949ceeb9c83SDarrick J. Wong * ltbno ltlen 1950ceeb9c83SDarrick J. Wong * orig: |ooooooooo| 1951ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 1952ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr| 1953ceeb9c83SDarrick J. Wong * bno len 1954ceeb9c83SDarrick J. Wong */ 1955ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += len; 1956ceeb9c83SDarrick J. Wong if (have_gt && 1957ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 1958ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 1959ceeb9c83SDarrick J. Wong /* 1960ceeb9c83SDarrick J. Wong * Right edge also contiguous, delete right record 1961ceeb9c83SDarrick J. Wong * and merge into left record. 1962ceeb9c83SDarrick J. Wong * 1963ceeb9c83SDarrick J. Wong * ltbno ltlen gtbno gtlen 1964ceeb9c83SDarrick J. Wong * orig: |ooooooooo| |ooooooooo| 1965ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 1966ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| 1967ceeb9c83SDarrick J. Wong */ 1968ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount; 1969ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 1970ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 1971ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 1972ceeb9c83SDarrick J. Wong if (error) 1973ceeb9c83SDarrick J. Wong goto out_error; 1974ceeb9c83SDarrick J. Wong } 1975ceeb9c83SDarrick J. Wong 1976ceeb9c83SDarrick J. Wong /* Point the cursor back to the left record and update. */ 1977ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, 1978ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner, 1979ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i); 1980ceeb9c83SDarrick J. Wong if (error) 1981ceeb9c83SDarrick J. Wong goto out_error; 1982ceeb9c83SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 1983ceeb9c83SDarrick J. Wong 1984ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec); 1985ceeb9c83SDarrick J. Wong if (error) 1986ceeb9c83SDarrick J. Wong goto out_error; 1987ceeb9c83SDarrick J. Wong } else if (have_gt && 1988ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock && 1989ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) { 1990ceeb9c83SDarrick J. Wong /* 1991ceeb9c83SDarrick J. Wong * Right edge contiguous, merge into right record. 1992ceeb9c83SDarrick J. Wong * 1993ceeb9c83SDarrick J. Wong * gtbno gtlen 1994ceeb9c83SDarrick J. Wong * Orig: |ooooooooo| 1995ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa| 1996ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr| 1997ceeb9c83SDarrick J. Wong * bno len 1998ceeb9c83SDarrick J. Wong */ 1999ceeb9c83SDarrick J. Wong /* Delete the old record. */ 2000ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock, 2001ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2002ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2003ceeb9c83SDarrick J. Wong if (error) 2004ceeb9c83SDarrick J. Wong goto out_error; 2005ceeb9c83SDarrick J. Wong 2006ceeb9c83SDarrick J. Wong /* Move the start and re-add it. */ 2007ceeb9c83SDarrick J. Wong gtrec.rm_startblock = bno; 2008ceeb9c83SDarrick J. Wong gtrec.rm_blockcount += len; 2009ceeb9c83SDarrick J. Wong gtrec.rm_offset = offset; 2010ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, gtrec.rm_startblock, 2011ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner, 2012ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags); 2013ceeb9c83SDarrick J. Wong if (error) 2014ceeb9c83SDarrick J. Wong goto out_error; 2015ceeb9c83SDarrick J. Wong } else { 2016ceeb9c83SDarrick J. Wong /* 2017ceeb9c83SDarrick J. Wong * No contiguous edge with identical owner, insert 2018ceeb9c83SDarrick J. Wong * new record at current cursor position. 2019ceeb9c83SDarrick J. Wong */ 2020ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, flags); 2021ceeb9c83SDarrick J. Wong if (error) 2022ceeb9c83SDarrick J. Wong goto out_error; 2023ceeb9c83SDarrick J. Wong } 2024ceeb9c83SDarrick J. Wong 2025ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, 2026ceeb9c83SDarrick J. Wong unwritten, oinfo); 2027ceeb9c83SDarrick J. Wong out_error: 2028ceeb9c83SDarrick J. Wong if (error) 2029ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_error(cur->bc_mp, 2030ceeb9c83SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 2031ceeb9c83SDarrick J. Wong return error; 2032ceeb9c83SDarrick J. Wong } 2033ceeb9c83SDarrick J. Wong 2034c543838aSDarrick J. Wong struct xfs_rmap_query_range_info { 2035c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn; 2036c543838aSDarrick J. Wong void *priv; 2037c543838aSDarrick J. Wong }; 2038c543838aSDarrick J. Wong 2039c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */ 2040c543838aSDarrick J. Wong STATIC int 2041c543838aSDarrick J. Wong xfs_rmap_query_range_helper( 2042c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2043c543838aSDarrick J. Wong union xfs_btree_rec *rec, 2044c543838aSDarrick J. Wong void *priv) 2045c543838aSDarrick J. Wong { 2046c543838aSDarrick J. Wong struct xfs_rmap_query_range_info *query = priv; 2047c543838aSDarrick J. Wong struct xfs_rmap_irec irec; 2048c543838aSDarrick J. Wong int error; 2049c543838aSDarrick J. Wong 2050c543838aSDarrick J. Wong error = xfs_rmap_btrec_to_irec(rec, &irec); 2051c543838aSDarrick J. Wong if (error) 2052c543838aSDarrick J. Wong return error; 2053c543838aSDarrick J. Wong return query->fn(cur, &irec, query->priv); 2054c543838aSDarrick J. Wong } 2055c543838aSDarrick J. Wong 2056c543838aSDarrick J. Wong /* Find all rmaps between two keys. */ 2057c543838aSDarrick J. Wong int 2058c543838aSDarrick J. Wong xfs_rmap_query_range( 2059c543838aSDarrick J. Wong struct xfs_btree_cur *cur, 2060c543838aSDarrick J. Wong struct xfs_rmap_irec *low_rec, 2061c543838aSDarrick J. Wong struct xfs_rmap_irec *high_rec, 2062c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2063c543838aSDarrick J. Wong void *priv) 2064c543838aSDarrick J. Wong { 2065c543838aSDarrick J. Wong union xfs_btree_irec low_brec; 2066c543838aSDarrick J. Wong union xfs_btree_irec high_brec; 2067c543838aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2068c543838aSDarrick J. Wong 2069c543838aSDarrick J. Wong low_brec.r = *low_rec; 2070c543838aSDarrick J. Wong high_brec.r = *high_rec; 2071c543838aSDarrick J. Wong query.priv = priv; 2072c543838aSDarrick J. Wong query.fn = fn; 2073c543838aSDarrick J. Wong return xfs_btree_query_range(cur, &low_brec, &high_brec, 2074c543838aSDarrick J. Wong xfs_rmap_query_range_helper, &query); 2075e9a2599aSDarrick J. Wong } 2076e9a2599aSDarrick J. Wong 2077e9a2599aSDarrick J. Wong /* Find all rmaps. */ 2078e9a2599aSDarrick J. Wong int 2079e9a2599aSDarrick J. Wong xfs_rmap_query_all( 2080e9a2599aSDarrick J. Wong struct xfs_btree_cur *cur, 2081e9a2599aSDarrick J. Wong xfs_rmap_query_range_fn fn, 2082e9a2599aSDarrick J. Wong void *priv) 2083e9a2599aSDarrick J. Wong { 2084e9a2599aSDarrick J. Wong struct xfs_rmap_query_range_info query; 2085e9a2599aSDarrick J. Wong 2086e9a2599aSDarrick J. Wong query.priv = priv; 2087e9a2599aSDarrick J. Wong query.fn = fn; 2088e9a2599aSDarrick J. Wong return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query); 2089c543838aSDarrick J. Wong } 20909c194644SDarrick J. Wong 20919c194644SDarrick J. Wong /* Clean up after calling xfs_rmap_finish_one. */ 20929c194644SDarrick J. Wong void 20939c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup( 20949c194644SDarrick J. Wong struct xfs_trans *tp, 20959c194644SDarrick J. Wong struct xfs_btree_cur *rcur, 20969c194644SDarrick J. Wong int error) 20979c194644SDarrick J. Wong { 20989c194644SDarrick J. Wong struct xfs_buf *agbp; 20999c194644SDarrick J. Wong 21009c194644SDarrick J. Wong if (rcur == NULL) 21019c194644SDarrick J. Wong return; 21029c194644SDarrick J. Wong agbp = rcur->bc_private.a.agbp; 21039c194644SDarrick J. Wong xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); 21049c194644SDarrick J. Wong if (error) 21059c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 21069c194644SDarrick J. Wong } 21079c194644SDarrick J. Wong 21089c194644SDarrick J. Wong /* 21099c194644SDarrick J. Wong * Process one of the deferred rmap operations. We pass back the 21109c194644SDarrick J. Wong * btree cursor to maintain our lock on the rmapbt between calls. 21119c194644SDarrick J. Wong * This saves time and eliminates a buffer deadlock between the 21129c194644SDarrick J. Wong * superblock and the AGF because we'll always grab them in the same 21139c194644SDarrick J. Wong * order. 21149c194644SDarrick J. Wong */ 21159c194644SDarrick J. Wong int 21169c194644SDarrick J. Wong xfs_rmap_finish_one( 21179c194644SDarrick J. Wong struct xfs_trans *tp, 21189c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2119c8ce540dSDarrick J. Wong uint64_t owner, 21209c194644SDarrick J. Wong int whichfork, 21219c194644SDarrick J. Wong xfs_fileoff_t startoff, 21229c194644SDarrick J. Wong xfs_fsblock_t startblock, 21239c194644SDarrick J. Wong xfs_filblks_t blockcount, 21249c194644SDarrick J. Wong xfs_exntst_t state, 21259c194644SDarrick J. Wong struct xfs_btree_cur **pcur) 21269c194644SDarrick J. Wong { 21279c194644SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp; 21289c194644SDarrick J. Wong struct xfs_btree_cur *rcur; 21299c194644SDarrick J. Wong struct xfs_buf *agbp = NULL; 21309c194644SDarrick J. Wong int error = 0; 21319c194644SDarrick J. Wong xfs_agnumber_t agno; 21329c194644SDarrick J. Wong struct xfs_owner_info oinfo; 21339c194644SDarrick J. Wong xfs_agblock_t bno; 21349c194644SDarrick J. Wong bool unwritten; 21359c194644SDarrick J. Wong 21369c194644SDarrick J. Wong agno = XFS_FSB_TO_AGNO(mp, startblock); 21379c194644SDarrick J. Wong ASSERT(agno != NULLAGNUMBER); 21389c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(mp, startblock); 21399c194644SDarrick J. Wong 21409c194644SDarrick J. Wong trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, 21419c194644SDarrick J. Wong startoff, blockcount, state); 21429c194644SDarrick J. Wong 21439c194644SDarrick J. Wong if (XFS_TEST_ERROR(false, mp, 21449e24cfd0SDarrick J. Wong XFS_ERRTAG_RMAP_FINISH_ONE)) 21459c194644SDarrick J. Wong return -EIO; 21469c194644SDarrick J. Wong 21479c194644SDarrick J. Wong /* 21489c194644SDarrick J. Wong * If we haven't gotten a cursor or the cursor AG doesn't match 21499c194644SDarrick J. Wong * the startblock, get one now. 21509c194644SDarrick J. Wong */ 21519c194644SDarrick J. Wong rcur = *pcur; 21529c194644SDarrick J. Wong if (rcur != NULL && rcur->bc_private.a.agno != agno) { 21539c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup(tp, rcur, 0); 21549c194644SDarrick J. Wong rcur = NULL; 21559c194644SDarrick J. Wong *pcur = NULL; 21569c194644SDarrick J. Wong } 21579c194644SDarrick J. Wong if (rcur == NULL) { 21589c194644SDarrick J. Wong /* 21599c194644SDarrick J. Wong * Refresh the freelist before we start changing the 21609c194644SDarrick J. Wong * rmapbt, because a shape change could cause us to 21619c194644SDarrick J. Wong * allocate blocks. 21629c194644SDarrick J. Wong */ 21639c194644SDarrick J. Wong error = xfs_free_extent_fix_freelist(tp, agno, &agbp); 21649c194644SDarrick J. Wong if (error) 21659c194644SDarrick J. Wong return error; 21669c194644SDarrick J. Wong if (!agbp) 21679c194644SDarrick J. Wong return -EFSCORRUPTED; 21689c194644SDarrick J. Wong 21699c194644SDarrick J. Wong rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); 21709c194644SDarrick J. Wong if (!rcur) { 21719c194644SDarrick J. Wong error = -ENOMEM; 21729c194644SDarrick J. Wong goto out_cur; 21739c194644SDarrick J. Wong } 21749c194644SDarrick J. Wong } 21759c194644SDarrick J. Wong *pcur = rcur; 21769c194644SDarrick J. Wong 21779c194644SDarrick J. Wong xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff); 21789c194644SDarrick J. Wong unwritten = state == XFS_EXT_UNWRITTEN; 21799c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock); 21809c194644SDarrick J. Wong 21819c194644SDarrick J. Wong switch (type) { 21829c194644SDarrick J. Wong case XFS_RMAP_ALLOC: 21839c194644SDarrick J. Wong case XFS_RMAP_MAP: 21849c194644SDarrick J. Wong error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); 21859c194644SDarrick J. Wong break; 2186ceeb9c83SDarrick J. Wong case XFS_RMAP_MAP_SHARED: 2187ceeb9c83SDarrick J. Wong error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten, 2188ceeb9c83SDarrick J. Wong &oinfo); 2189ceeb9c83SDarrick J. Wong break; 21909c194644SDarrick J. Wong case XFS_RMAP_FREE: 21919c194644SDarrick J. Wong case XFS_RMAP_UNMAP: 21929c194644SDarrick J. Wong error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, 21939c194644SDarrick J. Wong &oinfo); 21949c194644SDarrick J. Wong break; 2195ceeb9c83SDarrick J. Wong case XFS_RMAP_UNMAP_SHARED: 2196ceeb9c83SDarrick J. Wong error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten, 2197ceeb9c83SDarrick J. Wong &oinfo); 2198ceeb9c83SDarrick J. Wong break; 21999c194644SDarrick J. Wong case XFS_RMAP_CONVERT: 22009c194644SDarrick J. Wong error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, 22019c194644SDarrick J. Wong &oinfo); 22029c194644SDarrick J. Wong break; 22033f165b33SDarrick J. Wong case XFS_RMAP_CONVERT_SHARED: 22043f165b33SDarrick J. Wong error = xfs_rmap_convert_shared(rcur, bno, blockcount, 22053f165b33SDarrick J. Wong !unwritten, &oinfo); 22063f165b33SDarrick J. Wong break; 22079c194644SDarrick J. Wong default: 22089c194644SDarrick J. Wong ASSERT(0); 22099c194644SDarrick J. Wong error = -EFSCORRUPTED; 22109c194644SDarrick J. Wong } 22119c194644SDarrick J. Wong return error; 22129c194644SDarrick J. Wong 22139c194644SDarrick J. Wong out_cur: 22149c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp); 22159c194644SDarrick J. Wong 22169c194644SDarrick J. Wong return error; 22179c194644SDarrick J. Wong } 22189c194644SDarrick J. Wong 22199c194644SDarrick J. Wong /* 22209c194644SDarrick J. Wong * Don't defer an rmap if we aren't an rmap filesystem. 22219c194644SDarrick J. Wong */ 22229c194644SDarrick J. Wong static bool 22239c194644SDarrick J. Wong xfs_rmap_update_is_needed( 22243993baebSDarrick J. Wong struct xfs_mount *mp, 22253993baebSDarrick J. Wong int whichfork) 22269c194644SDarrick J. Wong { 22273993baebSDarrick J. Wong return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK; 22289c194644SDarrick J. Wong } 22299c194644SDarrick J. Wong 22309c194644SDarrick J. Wong /* 22319c194644SDarrick J. Wong * Record a rmap intent; the list is kept sorted first by AG and then by 22329c194644SDarrick J. Wong * increasing age. 22339c194644SDarrick J. Wong */ 22349c194644SDarrick J. Wong static int 22359c194644SDarrick J. Wong __xfs_rmap_add( 22369c194644SDarrick J. Wong struct xfs_mount *mp, 22379c194644SDarrick J. Wong struct xfs_defer_ops *dfops, 22389c194644SDarrick J. Wong enum xfs_rmap_intent_type type, 2239c8ce540dSDarrick J. Wong uint64_t owner, 22409c194644SDarrick J. Wong int whichfork, 22419c194644SDarrick J. Wong struct xfs_bmbt_irec *bmap) 22429c194644SDarrick J. Wong { 22439c194644SDarrick J. Wong struct xfs_rmap_intent *ri; 22449c194644SDarrick J. Wong 22459c194644SDarrick J. Wong trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock), 22469c194644SDarrick J. Wong type, 22479c194644SDarrick J. Wong XFS_FSB_TO_AGBNO(mp, bmap->br_startblock), 22489c194644SDarrick J. Wong owner, whichfork, 22499c194644SDarrick J. Wong bmap->br_startoff, 22509c194644SDarrick J. Wong bmap->br_blockcount, 22519c194644SDarrick J. Wong bmap->br_state); 22529c194644SDarrick J. Wong 22539c194644SDarrick J. Wong ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS); 22549c194644SDarrick J. Wong INIT_LIST_HEAD(&ri->ri_list); 22559c194644SDarrick J. Wong ri->ri_type = type; 22569c194644SDarrick J. Wong ri->ri_owner = owner; 22579c194644SDarrick J. Wong ri->ri_whichfork = whichfork; 22589c194644SDarrick J. Wong ri->ri_bmap = *bmap; 22599c194644SDarrick J. Wong 22609c194644SDarrick J. Wong xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); 22619c194644SDarrick J. Wong return 0; 22629c194644SDarrick J. Wong } 22639c194644SDarrick J. Wong 22649c194644SDarrick J. Wong /* Map an extent into a file. */ 22659c194644SDarrick J. Wong int 22669c194644SDarrick J. Wong xfs_rmap_map_extent( 22679c194644SDarrick J. Wong struct xfs_mount *mp, 22689c194644SDarrick J. Wong struct xfs_defer_ops *dfops, 22699c194644SDarrick J. Wong struct xfs_inode *ip, 22709c194644SDarrick J. Wong int whichfork, 22719c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 22729c194644SDarrick J. Wong { 22733993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 22749c194644SDarrick J. Wong return 0; 22759c194644SDarrick J. Wong 2276ceeb9c83SDarrick J. Wong return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? 2277ceeb9c83SDarrick J. Wong XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino, 22789c194644SDarrick J. Wong whichfork, PREV); 22799c194644SDarrick J. Wong } 22809c194644SDarrick J. Wong 22819c194644SDarrick J. Wong /* Unmap an extent out of a file. */ 22829c194644SDarrick J. Wong int 22839c194644SDarrick J. Wong xfs_rmap_unmap_extent( 22849c194644SDarrick J. Wong struct xfs_mount *mp, 22859c194644SDarrick J. Wong struct xfs_defer_ops *dfops, 22869c194644SDarrick J. Wong struct xfs_inode *ip, 22879c194644SDarrick J. Wong int whichfork, 22889c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 22899c194644SDarrick J. Wong { 22903993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 22919c194644SDarrick J. Wong return 0; 22929c194644SDarrick J. Wong 2293ceeb9c83SDarrick J. Wong return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? 2294ceeb9c83SDarrick J. Wong XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino, 22959c194644SDarrick J. Wong whichfork, PREV); 22969c194644SDarrick J. Wong } 22979c194644SDarrick J. Wong 22989c194644SDarrick J. Wong /* Convert a data fork extent from unwritten to real or vice versa. */ 22999c194644SDarrick J. Wong int 23009c194644SDarrick J. Wong xfs_rmap_convert_extent( 23019c194644SDarrick J. Wong struct xfs_mount *mp, 23029c194644SDarrick J. Wong struct xfs_defer_ops *dfops, 23039c194644SDarrick J. Wong struct xfs_inode *ip, 23049c194644SDarrick J. Wong int whichfork, 23059c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV) 23069c194644SDarrick J. Wong { 23073993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork)) 23089c194644SDarrick J. Wong return 0; 23099c194644SDarrick J. Wong 23103f165b33SDarrick J. Wong return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? 23113f165b33SDarrick J. Wong XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino, 23129c194644SDarrick J. Wong whichfork, PREV); 23139c194644SDarrick J. Wong } 23149c194644SDarrick J. Wong 23159c194644SDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */ 23169c194644SDarrick J. Wong int 23179c194644SDarrick J. Wong xfs_rmap_alloc_extent( 23189c194644SDarrick J. Wong struct xfs_mount *mp, 23199c194644SDarrick J. Wong struct xfs_defer_ops *dfops, 23209c194644SDarrick J. Wong xfs_agnumber_t agno, 23219c194644SDarrick J. Wong xfs_agblock_t bno, 23229c194644SDarrick J. Wong xfs_extlen_t len, 2323c8ce540dSDarrick J. Wong uint64_t owner) 23249c194644SDarrick J. Wong { 23259c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 23269c194644SDarrick J. Wong 23273993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) 23289c194644SDarrick J. Wong return 0; 23299c194644SDarrick J. Wong 23309c194644SDarrick J. Wong bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); 23319c194644SDarrick J. Wong bmap.br_blockcount = len; 23329c194644SDarrick J. Wong bmap.br_startoff = 0; 23339c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 23349c194644SDarrick J. Wong 23359c194644SDarrick J. Wong return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner, 23369c194644SDarrick J. Wong XFS_DATA_FORK, &bmap); 23379c194644SDarrick J. Wong } 23389c194644SDarrick J. Wong 23399c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */ 23409c194644SDarrick J. Wong int 23419c194644SDarrick J. Wong xfs_rmap_free_extent( 23429c194644SDarrick J. Wong struct xfs_mount *mp, 23439c194644SDarrick J. Wong struct xfs_defer_ops *dfops, 23449c194644SDarrick J. Wong xfs_agnumber_t agno, 23459c194644SDarrick J. Wong xfs_agblock_t bno, 23469c194644SDarrick J. Wong xfs_extlen_t len, 2347c8ce540dSDarrick J. Wong uint64_t owner) 23489c194644SDarrick J. Wong { 23499c194644SDarrick J. Wong struct xfs_bmbt_irec bmap; 23509c194644SDarrick J. Wong 23513993baebSDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) 23529c194644SDarrick J. Wong return 0; 23539c194644SDarrick J. Wong 23549c194644SDarrick J. Wong bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); 23559c194644SDarrick J. Wong bmap.br_blockcount = len; 23569c194644SDarrick J. Wong bmap.br_startoff = 0; 23579c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM; 23589c194644SDarrick J. Wong 23599c194644SDarrick J. Wong return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner, 23609c194644SDarrick J. Wong XFS_DATA_FORK, &bmap); 23619c194644SDarrick J. Wong } 2362e89c0413SDarrick J. Wong 2363e89c0413SDarrick J. Wong /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ 2364e89c0413SDarrick J. Wong int 2365e89c0413SDarrick J. Wong xfs_rmap_compare( 2366e89c0413SDarrick J. Wong const struct xfs_rmap_irec *a, 2367e89c0413SDarrick J. Wong const struct xfs_rmap_irec *b) 2368e89c0413SDarrick J. Wong { 2369e89c0413SDarrick J. Wong __u64 oa; 2370e89c0413SDarrick J. Wong __u64 ob; 2371e89c0413SDarrick J. Wong 2372e89c0413SDarrick J. Wong oa = xfs_rmap_irec_offset_pack(a); 2373e89c0413SDarrick J. Wong ob = xfs_rmap_irec_offset_pack(b); 2374e89c0413SDarrick J. Wong 2375e89c0413SDarrick J. Wong if (a->rm_startblock < b->rm_startblock) 2376e89c0413SDarrick J. Wong return -1; 2377e89c0413SDarrick J. Wong else if (a->rm_startblock > b->rm_startblock) 2378e89c0413SDarrick J. Wong return 1; 2379e89c0413SDarrick J. Wong else if (a->rm_owner < b->rm_owner) 2380e89c0413SDarrick J. Wong return -1; 2381e89c0413SDarrick J. Wong else if (a->rm_owner > b->rm_owner) 2382e89c0413SDarrick J. Wong return 1; 2383e89c0413SDarrick J. Wong else if (oa < ob) 2384e89c0413SDarrick J. Wong return -1; 2385e89c0413SDarrick J. Wong else if (oa > ob) 2386e89c0413SDarrick J. Wong return 1; 2387e89c0413SDarrick J. Wong else 2388e89c0413SDarrick J. Wong return 0; 2389e89c0413SDarrick J. Wong } 2390ed7c52d4SDarrick J. Wong 2391ed7c52d4SDarrick J. Wong /* Is there a record covering a given extent? */ 2392ed7c52d4SDarrick J. Wong int 2393ed7c52d4SDarrick J. Wong xfs_rmap_has_record( 2394ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2395ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2396ed7c52d4SDarrick J. Wong xfs_extlen_t len, 2397ed7c52d4SDarrick J. Wong bool *exists) 2398ed7c52d4SDarrick J. Wong { 2399ed7c52d4SDarrick J. Wong union xfs_btree_irec low; 2400ed7c52d4SDarrick J. Wong union xfs_btree_irec high; 2401ed7c52d4SDarrick J. Wong 2402ed7c52d4SDarrick J. Wong memset(&low, 0, sizeof(low)); 2403ed7c52d4SDarrick J. Wong low.r.rm_startblock = bno; 2404ed7c52d4SDarrick J. Wong memset(&high, 0xFF, sizeof(high)); 2405ed7c52d4SDarrick J. Wong high.r.rm_startblock = bno + len - 1; 2406ed7c52d4SDarrick J. Wong 2407ed7c52d4SDarrick J. Wong return xfs_btree_has_record(cur, &low, &high, exists); 2408ed7c52d4SDarrick J. Wong } 2409ed7c52d4SDarrick J. Wong 2410ed7c52d4SDarrick J. Wong /* 2411ed7c52d4SDarrick J. Wong * Is there a record for this owner completely covering a given physical 2412ed7c52d4SDarrick J. Wong * extent? If so, *has_rmap will be set to true. If there is no record 2413ed7c52d4SDarrick J. Wong * or the record only covers part of the range, we set *has_rmap to false. 2414ed7c52d4SDarrick J. Wong * This function doesn't perform range lookups or offset checks, so it is 2415ed7c52d4SDarrick J. Wong * not suitable for checking data fork blocks. 2416ed7c52d4SDarrick J. Wong */ 2417ed7c52d4SDarrick J. Wong int 2418ed7c52d4SDarrick J. Wong xfs_rmap_record_exists( 2419ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur, 2420ed7c52d4SDarrick J. Wong xfs_agblock_t bno, 2421ed7c52d4SDarrick J. Wong xfs_extlen_t len, 2422ed7c52d4SDarrick J. Wong struct xfs_owner_info *oinfo, 2423ed7c52d4SDarrick J. Wong bool *has_rmap) 2424ed7c52d4SDarrick J. Wong { 2425ed7c52d4SDarrick J. Wong uint64_t owner; 2426ed7c52d4SDarrick J. Wong uint64_t offset; 2427ed7c52d4SDarrick J. Wong unsigned int flags; 2428ed7c52d4SDarrick J. Wong int has_record; 2429ed7c52d4SDarrick J. Wong struct xfs_rmap_irec irec; 2430ed7c52d4SDarrick J. Wong int error; 2431ed7c52d4SDarrick J. Wong 2432ed7c52d4SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); 2433ed7c52d4SDarrick J. Wong ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || 2434ed7c52d4SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK)); 2435ed7c52d4SDarrick J. Wong 2436ed7c52d4SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, 2437ed7c52d4SDarrick J. Wong &has_record); 2438ed7c52d4SDarrick J. Wong if (error) 2439ed7c52d4SDarrick J. Wong return error; 2440ed7c52d4SDarrick J. Wong if (!has_record) { 2441ed7c52d4SDarrick J. Wong *has_rmap = false; 2442ed7c52d4SDarrick J. Wong return 0; 2443ed7c52d4SDarrick J. Wong } 2444ed7c52d4SDarrick J. Wong 2445ed7c52d4SDarrick J. Wong error = xfs_rmap_get_rec(cur, &irec, &has_record); 2446ed7c52d4SDarrick J. Wong if (error) 2447ed7c52d4SDarrick J. Wong return error; 2448ed7c52d4SDarrick J. Wong if (!has_record) { 2449ed7c52d4SDarrick J. Wong *has_rmap = false; 2450ed7c52d4SDarrick J. Wong return 0; 2451ed7c52d4SDarrick J. Wong } 2452ed7c52d4SDarrick J. Wong 2453ed7c52d4SDarrick J. Wong *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno && 2454ed7c52d4SDarrick J. Wong irec.rm_startblock + irec.rm_blockcount >= bno + len); 2455ed7c52d4SDarrick J. Wong return 0; 2456ed7c52d4SDarrick J. Wong } 2457