Linux Audio

Check our new training course

Loading...
v6.2
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2014 Red Hat, Inc.
   4 * All Rights Reserved.
   5 */
   6#include "xfs.h"
   7#include "xfs_fs.h"
   8#include "xfs_shared.h"
   9#include "xfs_format.h"
  10#include "xfs_log_format.h"
  11#include "xfs_trans_resv.h"
  12#include "xfs_bit.h"
  13#include "xfs_mount.h"
  14#include "xfs_sb.h"
  15#include "xfs_defer.h"
  16#include "xfs_btree.h"
  17#include "xfs_trans.h"
  18#include "xfs_alloc.h"
  19#include "xfs_rmap.h"
  20#include "xfs_rmap_btree.h"
  21#include "xfs_trace.h"
  22#include "xfs_errortag.h"
  23#include "xfs_error.h"
  24#include "xfs_inode.h"
  25#include "xfs_ag.h"
  26
  27struct kmem_cache	*xfs_rmap_intent_cache;
  28
  29/*
  30 * Lookup the first record less than or equal to [bno, len, owner, offset]
  31 * in the btree given by cur.
  32 */
  33int
  34xfs_rmap_lookup_le(
  35	struct xfs_btree_cur	*cur,
  36	xfs_agblock_t		bno,
 
  37	uint64_t		owner,
  38	uint64_t		offset,
  39	unsigned int		flags,
  40	struct xfs_rmap_irec	*irec,
  41	int			*stat)
  42{
  43	int			get_stat = 0;
  44	int			error;
  45
  46	cur->bc_rec.r.rm_startblock = bno;
  47	cur->bc_rec.r.rm_blockcount = 0;
  48	cur->bc_rec.r.rm_owner = owner;
  49	cur->bc_rec.r.rm_offset = offset;
  50	cur->bc_rec.r.rm_flags = flags;
  51
  52	error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
  53	if (error || !(*stat) || !irec)
  54		return error;
  55
  56	error = xfs_rmap_get_rec(cur, irec, &get_stat);
  57	if (error)
  58		return error;
  59	if (!get_stat)
  60		return -EFSCORRUPTED;
  61
  62	return 0;
  63}
  64
  65/*
  66 * Lookup the record exactly matching [bno, len, owner, offset]
  67 * in the btree given by cur.
  68 */
  69int
  70xfs_rmap_lookup_eq(
  71	struct xfs_btree_cur	*cur,
  72	xfs_agblock_t		bno,
  73	xfs_extlen_t		len,
  74	uint64_t		owner,
  75	uint64_t		offset,
  76	unsigned int		flags,
  77	int			*stat)
  78{
  79	cur->bc_rec.r.rm_startblock = bno;
  80	cur->bc_rec.r.rm_blockcount = len;
  81	cur->bc_rec.r.rm_owner = owner;
  82	cur->bc_rec.r.rm_offset = offset;
  83	cur->bc_rec.r.rm_flags = flags;
  84	return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
  85}
  86
  87/*
  88 * Update the record referred to by cur to the value given
  89 * by [bno, len, owner, offset].
  90 * This either works (return 0) or gets an EFSCORRUPTED error.
  91 */
  92STATIC int
  93xfs_rmap_update(
  94	struct xfs_btree_cur	*cur,
  95	struct xfs_rmap_irec	*irec)
  96{
  97	union xfs_btree_rec	rec;
  98	int			error;
  99
 100	trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
 101			irec->rm_startblock, irec->rm_blockcount,
 102			irec->rm_owner, irec->rm_offset, irec->rm_flags);
 103
 104	rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
 105	rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
 106	rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
 107	rec.rmap.rm_offset = cpu_to_be64(
 108			xfs_rmap_irec_offset_pack(irec));
 109	error = xfs_btree_update(cur, &rec);
 110	if (error)
 111		trace_xfs_rmap_update_error(cur->bc_mp,
 112				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
 113	return error;
 114}
 115
 116int
 117xfs_rmap_insert(
 118	struct xfs_btree_cur	*rcur,
 119	xfs_agblock_t		agbno,
 120	xfs_extlen_t		len,
 121	uint64_t		owner,
 122	uint64_t		offset,
 123	unsigned int		flags)
 124{
 125	int			i;
 126	int			error;
 127
 128	trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
 129			len, owner, offset, flags);
 130
 131	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
 132	if (error)
 133		goto done;
 134	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
 135		error = -EFSCORRUPTED;
 136		goto done;
 137	}
 138
 139	rcur->bc_rec.r.rm_startblock = agbno;
 140	rcur->bc_rec.r.rm_blockcount = len;
 141	rcur->bc_rec.r.rm_owner = owner;
 142	rcur->bc_rec.r.rm_offset = offset;
 143	rcur->bc_rec.r.rm_flags = flags;
 144	error = xfs_btree_insert(rcur, &i);
 145	if (error)
 146		goto done;
 147	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 148		error = -EFSCORRUPTED;
 149		goto done;
 150	}
 151done:
 152	if (error)
 153		trace_xfs_rmap_insert_error(rcur->bc_mp,
 154				rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
 155	return error;
 156}
 157
 158STATIC int
 159xfs_rmap_delete(
 160	struct xfs_btree_cur	*rcur,
 161	xfs_agblock_t		agbno,
 162	xfs_extlen_t		len,
 163	uint64_t		owner,
 164	uint64_t		offset,
 165	unsigned int		flags)
 166{
 167	int			i;
 168	int			error;
 169
 170	trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
 171			len, owner, offset, flags);
 172
 173	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
 174	if (error)
 175		goto done;
 176	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 177		error = -EFSCORRUPTED;
 178		goto done;
 179	}
 180
 181	error = xfs_btree_delete(rcur, &i);
 182	if (error)
 183		goto done;
 184	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 185		error = -EFSCORRUPTED;
 186		goto done;
 187	}
 188done:
 189	if (error)
 190		trace_xfs_rmap_delete_error(rcur->bc_mp,
 191				rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
 192	return error;
 193}
 194
 195/* Convert an internal btree record to an rmap record. */
 196int
 197xfs_rmap_btrec_to_irec(
 198	const union xfs_btree_rec	*rec,
 199	struct xfs_rmap_irec		*irec)
 200{
 201	irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
 202	irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
 203	irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
 204	return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
 205			irec);
 206}
 207
 208/*
 209 * Get the data from the pointed-to record.
 210 */
 211int
 212xfs_rmap_get_rec(
 213	struct xfs_btree_cur	*cur,
 214	struct xfs_rmap_irec	*irec,
 215	int			*stat)
 216{
 217	struct xfs_mount	*mp = cur->bc_mp;
 218	struct xfs_perag	*pag = cur->bc_ag.pag;
 219	union xfs_btree_rec	*rec;
 220	int			error;
 221
 222	error = xfs_btree_get_rec(cur, &rec, stat);
 223	if (error || !*stat)
 224		return error;
 225
 226	if (xfs_rmap_btrec_to_irec(rec, irec))
 227		goto out_bad_rec;
 228
 229	if (irec->rm_blockcount == 0)
 230		goto out_bad_rec;
 231	if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
 232		if (irec->rm_owner != XFS_RMAP_OWN_FS)
 233			goto out_bad_rec;
 234		if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
 235			goto out_bad_rec;
 236	} else {
 237		/* check for valid extent range, including overflow */
 238		if (!xfs_verify_agbext(pag, irec->rm_startblock,
 239					    irec->rm_blockcount))
 
 
 
 
 
 240			goto out_bad_rec;
 241	}
 242
 243	if (!(xfs_verify_ino(mp, irec->rm_owner) ||
 244	      (irec->rm_owner <= XFS_RMAP_OWN_FS &&
 245	       irec->rm_owner >= XFS_RMAP_OWN_MIN)))
 246		goto out_bad_rec;
 247
 248	return 0;
 249out_bad_rec:
 250	xfs_warn(mp,
 251		"Reverse Mapping BTree record corruption in AG %d detected!",
 252		pag->pag_agno);
 253	xfs_warn(mp,
 254		"Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
 255		irec->rm_owner, irec->rm_flags, irec->rm_startblock,
 256		irec->rm_blockcount);
 257	return -EFSCORRUPTED;
 258}
 259
 260struct xfs_find_left_neighbor_info {
 261	struct xfs_rmap_irec	high;
 262	struct xfs_rmap_irec	*irec;
 
 263};
 264
 265/* For each rmap given, figure out if it matches the key we want. */
 266STATIC int
 267xfs_rmap_find_left_neighbor_helper(
 268	struct xfs_btree_cur		*cur,
 269	const struct xfs_rmap_irec	*rec,
 270	void				*priv)
 271{
 272	struct xfs_find_left_neighbor_info	*info = priv;
 273
 274	trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
 275			cur->bc_ag.pag->pag_agno, rec->rm_startblock,
 276			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 277			rec->rm_flags);
 278
 279	if (rec->rm_owner != info->high.rm_owner)
 280		return 0;
 281	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
 282	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
 283	    rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
 284		return 0;
 285
 286	*info->irec = *rec;
 
 287	return -ECANCELED;
 288}
 289
 290/*
 291 * Find the record to the left of the given extent, being careful only to
 292 * return a match with the same owner and adjacent physical and logical
 293 * block ranges.
 294 */
 295STATIC int
 296xfs_rmap_find_left_neighbor(
 297	struct xfs_btree_cur	*cur,
 298	xfs_agblock_t		bno,
 299	uint64_t		owner,
 300	uint64_t		offset,
 301	unsigned int		flags,
 302	struct xfs_rmap_irec	*irec,
 303	int			*stat)
 304{
 305	struct xfs_find_left_neighbor_info	info;
 306	int			found = 0;
 307	int			error;
 308
 309	*stat = 0;
 310	if (bno == 0)
 311		return 0;
 312	info.high.rm_startblock = bno - 1;
 313	info.high.rm_owner = owner;
 314	if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
 315	    !(flags & XFS_RMAP_BMBT_BLOCK)) {
 316		if (offset == 0)
 317			return 0;
 318		info.high.rm_offset = offset - 1;
 319	} else
 320		info.high.rm_offset = 0;
 321	info.high.rm_flags = flags;
 322	info.high.rm_blockcount = 0;
 323	info.irec = irec;
 
 324
 325	trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
 326			cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
 327
 328	/*
 329	 * Historically, we always used the range query to walk every reverse
 330	 * mapping that could possibly overlap the key that the caller asked
 331	 * for, and filter out the ones that don't.  That is very slow when
 332	 * there are a lot of records.
 333	 *
 334	 * However, there are two scenarios where the classic btree search can
 335	 * produce correct results -- if the index contains a record that is an
 336	 * exact match for the lookup key; and if there are no other records
 337	 * between the record we want and the key we supplied.
 338	 *
 339	 * As an optimization, try a non-overlapped lookup first.  This makes
 340	 * extent conversion and remap operations run a bit faster if the
 341	 * physical extents aren't being shared.  If we don't find what we
 342	 * want, we fall back to the overlapped query.
 343	 */
 344	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
 345			&found);
 346	if (error)
 347		return error;
 348	if (found)
 349		error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
 350	if (!error)
 351		error = xfs_rmap_query_range(cur, &info.high, &info.high,
 352				xfs_rmap_find_left_neighbor_helper, &info);
 353	if (error != -ECANCELED)
 354		return error;
 355
 356	*stat = 1;
 357	trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
 358			cur->bc_ag.pag->pag_agno, irec->rm_startblock,
 359			irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
 360			irec->rm_flags);
 361	return 0;
 
 
 
 
 362}
 363
 364/* For each rmap given, figure out if it matches the key we want. */
 365STATIC int
 366xfs_rmap_lookup_le_range_helper(
 367	struct xfs_btree_cur		*cur,
 368	const struct xfs_rmap_irec	*rec,
 369	void				*priv)
 370{
 371	struct xfs_find_left_neighbor_info	*info = priv;
 372
 373	trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
 374			cur->bc_ag.pag->pag_agno, rec->rm_startblock,
 375			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 376			rec->rm_flags);
 377
 378	if (rec->rm_owner != info->high.rm_owner)
 379		return 0;
 380	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
 381	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
 382	    (rec->rm_offset > info->high.rm_offset ||
 383	     rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
 384		return 0;
 385
 386	*info->irec = *rec;
 
 387	return -ECANCELED;
 388}
 389
 390/*
 391 * Find the record to the left of the given extent, being careful only to
 392 * return a match with the same owner and overlapping physical and logical
 393 * block ranges.  This is the overlapping-interval version of
 394 * xfs_rmap_lookup_le.
 395 */
 396int
 397xfs_rmap_lookup_le_range(
 398	struct xfs_btree_cur	*cur,
 399	xfs_agblock_t		bno,
 400	uint64_t		owner,
 401	uint64_t		offset,
 402	unsigned int		flags,
 403	struct xfs_rmap_irec	*irec,
 404	int			*stat)
 405{
 406	struct xfs_find_left_neighbor_info	info;
 407	int			found = 0;
 408	int			error;
 409
 410	info.high.rm_startblock = bno;
 411	info.high.rm_owner = owner;
 412	if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
 413		info.high.rm_offset = offset;
 414	else
 415		info.high.rm_offset = 0;
 416	info.high.rm_flags = flags;
 417	info.high.rm_blockcount = 0;
 418	*stat = 0;
 419	info.irec = irec;
 
 420
 421	trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
 422			bno, 0, owner, offset, flags);
 423
 424	/*
 425	 * Historically, we always used the range query to walk every reverse
 426	 * mapping that could possibly overlap the key that the caller asked
 427	 * for, and filter out the ones that don't.  That is very slow when
 428	 * there are a lot of records.
 429	 *
 430	 * However, there are two scenarios where the classic btree search can
 431	 * produce correct results -- if the index contains a record that is an
 432	 * exact match for the lookup key; and if there are no other records
 433	 * between the record we want and the key we supplied.
 434	 *
 435	 * As an optimization, try a non-overlapped lookup first.  This makes
 436	 * scrub run much faster on most filesystems because bmbt records are
 437	 * usually an exact match for rmap records.  If we don't find what we
 438	 * want, we fall back to the overlapped query.
 439	 */
 440	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
 441			&found);
 442	if (error)
 443		return error;
 444	if (found)
 445		error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
 446	if (!error)
 447		error = xfs_rmap_query_range(cur, &info.high, &info.high,
 448				xfs_rmap_lookup_le_range_helper, &info);
 449	if (error != -ECANCELED)
 450		return error;
 451
 452	*stat = 1;
 453	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 454			cur->bc_ag.pag->pag_agno, irec->rm_startblock,
 455			irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
 456			irec->rm_flags);
 457	return 0;
 458}
 459
 460/*
 461 * Perform all the relevant owner checks for a removal op.  If we're doing an
 462 * unknown-owner removal then we have no owner information to check.
 463 */
 464static int
 465xfs_rmap_free_check_owner(
 466	struct xfs_mount	*mp,
 467	uint64_t		ltoff,
 468	struct xfs_rmap_irec	*rec,
 469	xfs_filblks_t		len,
 470	uint64_t		owner,
 471	uint64_t		offset,
 472	unsigned int		flags)
 473{
 474	int			error = 0;
 475
 476	if (owner == XFS_RMAP_OWN_UNKNOWN)
 477		return 0;
 478
 479	/* Make sure the unwritten flag matches. */
 480	if (XFS_IS_CORRUPT(mp,
 481			   (flags & XFS_RMAP_UNWRITTEN) !=
 482			   (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
 483		error = -EFSCORRUPTED;
 484		goto out;
 485	}
 486
 487	/* Make sure the owner matches what we expect to find in the tree. */
 488	if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
 489		error = -EFSCORRUPTED;
 490		goto out;
 491	}
 492
 493	/* Check the offset, if necessary. */
 494	if (XFS_RMAP_NON_INODE_OWNER(owner))
 495		goto out;
 496
 497	if (flags & XFS_RMAP_BMBT_BLOCK) {
 498		if (XFS_IS_CORRUPT(mp,
 499				   !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
 500			error = -EFSCORRUPTED;
 501			goto out;
 502		}
 503	} else {
 504		if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
 505			error = -EFSCORRUPTED;
 506			goto out;
 507		}
 508		if (XFS_IS_CORRUPT(mp,
 509				   offset + len > ltoff + rec->rm_blockcount)) {
 510			error = -EFSCORRUPTED;
 511			goto out;
 512		}
 513	}
 514
 515out:
 516	return error;
 517}
 518
 519/*
 520 * Find the extent in the rmap btree and remove it.
 521 *
 522 * The record we find should always be an exact match for the extent that we're
 523 * looking for, since we insert them into the btree without modification.
 524 *
 525 * Special Case #1: when growing the filesystem, we "free" an extent when
 526 * growing the last AG. This extent is new space and so it is not tracked as
 527 * used space in the btree. The growfs code will pass in an owner of
 528 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
 529 * extent. We verify that - the extent lookup result in a record that does not
 530 * overlap.
 531 *
 532 * Special Case #2: EFIs do not record the owner of the extent, so when
 533 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
 534 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
 535 * corruption checks during log recovery.
 536 */
 537STATIC int
 538xfs_rmap_unmap(
 539	struct xfs_btree_cur		*cur,
 540	xfs_agblock_t			bno,
 541	xfs_extlen_t			len,
 542	bool				unwritten,
 543	const struct xfs_owner_info	*oinfo)
 544{
 545	struct xfs_mount		*mp = cur->bc_mp;
 546	struct xfs_rmap_irec		ltrec;
 547	uint64_t			ltoff;
 548	int				error = 0;
 549	int				i;
 550	uint64_t			owner;
 551	uint64_t			offset;
 552	unsigned int			flags;
 553	bool				ignore_off;
 554
 555	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 556	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
 557			(flags & XFS_RMAP_BMBT_BLOCK);
 558	if (unwritten)
 559		flags |= XFS_RMAP_UNWRITTEN;
 560	trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
 561			unwritten, oinfo);
 562
 563	/*
 564	 * We should always have a left record because there's a static record
 565	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
 566	 * will not ever be removed from the tree.
 567	 */
 568	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec, &i);
 569	if (error)
 570		goto out_error;
 571	if (XFS_IS_CORRUPT(mp, i != 1)) {
 572		error = -EFSCORRUPTED;
 573		goto out_error;
 574	}
 575
 
 
 
 
 
 
 
 576	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 577			cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
 578			ltrec.rm_blockcount, ltrec.rm_owner,
 579			ltrec.rm_offset, ltrec.rm_flags);
 580	ltoff = ltrec.rm_offset;
 581
 582	/*
 583	 * For growfs, the incoming extent must be beyond the left record we
 584	 * just found as it is new space and won't be used by anyone. This is
 585	 * just a corruption check as we don't actually do anything with this
 586	 * extent.  Note that we need to use >= instead of > because it might
 587	 * be the case that the "left" extent goes all the way to EOFS.
 588	 */
 589	if (owner == XFS_RMAP_OWN_NULL) {
 590		if (XFS_IS_CORRUPT(mp,
 591				   bno <
 592				   ltrec.rm_startblock + ltrec.rm_blockcount)) {
 593			error = -EFSCORRUPTED;
 594			goto out_error;
 595		}
 596		goto out_done;
 597	}
 598
 599	/*
 600	 * If we're doing an unknown-owner removal for EFI recovery, we expect
 601	 * to find the full range in the rmapbt or nothing at all.  If we
 602	 * don't find any rmaps overlapping either end of the range, we're
 603	 * done.  Hopefully this means that the EFI creator already queued
 604	 * (and finished) a RUI to remove the rmap.
 605	 */
 606	if (owner == XFS_RMAP_OWN_UNKNOWN &&
 607	    ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
 608		struct xfs_rmap_irec    rtrec;
 609
 610		error = xfs_btree_increment(cur, 0, &i);
 611		if (error)
 612			goto out_error;
 613		if (i == 0)
 614			goto out_done;
 615		error = xfs_rmap_get_rec(cur, &rtrec, &i);
 616		if (error)
 617			goto out_error;
 618		if (XFS_IS_CORRUPT(mp, i != 1)) {
 619			error = -EFSCORRUPTED;
 620			goto out_error;
 621		}
 622		if (rtrec.rm_startblock >= bno + len)
 623			goto out_done;
 624	}
 625
 626	/* Make sure the extent we found covers the entire freeing range. */
 627	if (XFS_IS_CORRUPT(mp,
 628			   ltrec.rm_startblock > bno ||
 629			   ltrec.rm_startblock + ltrec.rm_blockcount <
 630			   bno + len)) {
 631		error = -EFSCORRUPTED;
 632		goto out_error;
 633	}
 634
 635	/* Check owner information. */
 636	error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, len, owner,
 637			offset, flags);
 638	if (error)
 639		goto out_error;
 640
 641	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
 642		/* exact match, simply remove the record from rmap tree */
 643		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
 644				ltrec.rm_startblock, ltrec.rm_blockcount,
 645				ltrec.rm_owner, ltrec.rm_offset,
 646				ltrec.rm_flags);
 647		error = xfs_btree_delete(cur, &i);
 648		if (error)
 649			goto out_error;
 650		if (XFS_IS_CORRUPT(mp, i != 1)) {
 651			error = -EFSCORRUPTED;
 652			goto out_error;
 653		}
 654	} else if (ltrec.rm_startblock == bno) {
 655		/*
 656		 * overlap left hand side of extent: move the start, trim the
 657		 * length and update the current record.
 658		 *
 659		 *       ltbno                ltlen
 660		 * Orig:    |oooooooooooooooooooo|
 661		 * Freeing: |fffffffff|
 662		 * Result:            |rrrrrrrrrr|
 663		 *         bno       len
 664		 */
 665		ltrec.rm_startblock += len;
 666		ltrec.rm_blockcount -= len;
 667		if (!ignore_off)
 668			ltrec.rm_offset += len;
 669		error = xfs_rmap_update(cur, &ltrec);
 670		if (error)
 671			goto out_error;
 672	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
 673		/*
 674		 * overlap right hand side of extent: trim the length and update
 675		 * the current record.
 676		 *
 677		 *       ltbno                ltlen
 678		 * Orig:    |oooooooooooooooooooo|
 679		 * Freeing:            |fffffffff|
 680		 * Result:  |rrrrrrrrrr|
 681		 *                    bno       len
 682		 */
 683		ltrec.rm_blockcount -= len;
 684		error = xfs_rmap_update(cur, &ltrec);
 685		if (error)
 686			goto out_error;
 687	} else {
 688
 689		/*
 690		 * overlap middle of extent: trim the length of the existing
 691		 * record to the length of the new left-extent size, increment
 692		 * the insertion position so we can insert a new record
 693		 * containing the remaining right-extent space.
 694		 *
 695		 *       ltbno                ltlen
 696		 * Orig:    |oooooooooooooooooooo|
 697		 * Freeing:       |fffffffff|
 698		 * Result:  |rrrrr|         |rrrr|
 699		 *               bno       len
 700		 */
 701		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
 702
 703		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
 704		error = xfs_rmap_update(cur, &ltrec);
 705		if (error)
 706			goto out_error;
 707
 708		error = xfs_btree_increment(cur, 0, &i);
 709		if (error)
 710			goto out_error;
 711
 712		cur->bc_rec.r.rm_startblock = bno + len;
 713		cur->bc_rec.r.rm_blockcount = orig_len - len -
 714						     ltrec.rm_blockcount;
 715		cur->bc_rec.r.rm_owner = ltrec.rm_owner;
 716		if (ignore_off)
 717			cur->bc_rec.r.rm_offset = 0;
 718		else
 719			cur->bc_rec.r.rm_offset = offset + len;
 720		cur->bc_rec.r.rm_flags = flags;
 721		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
 722				cur->bc_rec.r.rm_startblock,
 723				cur->bc_rec.r.rm_blockcount,
 724				cur->bc_rec.r.rm_owner,
 725				cur->bc_rec.r.rm_offset,
 726				cur->bc_rec.r.rm_flags);
 727		error = xfs_btree_insert(cur, &i);
 728		if (error)
 729			goto out_error;
 730	}
 731
 732out_done:
 733	trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
 734			unwritten, oinfo);
 735out_error:
 736	if (error)
 737		trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
 738				error, _RET_IP_);
 739	return error;
 740}
 741
 742/*
 743 * Remove a reference to an extent in the rmap btree.
 744 */
 745int
 746xfs_rmap_free(
 747	struct xfs_trans		*tp,
 748	struct xfs_buf			*agbp,
 749	struct xfs_perag		*pag,
 750	xfs_agblock_t			bno,
 751	xfs_extlen_t			len,
 752	const struct xfs_owner_info	*oinfo)
 753{
 754	struct xfs_mount		*mp = tp->t_mountp;
 755	struct xfs_btree_cur		*cur;
 756	int				error;
 757
 758	if (!xfs_has_rmapbt(mp))
 759		return 0;
 760
 761	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
 762
 763	error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
 764
 765	xfs_btree_del_cursor(cur, error);
 766	return error;
 767}
 768
 769/*
 770 * A mergeable rmap must have the same owner and the same values for
 771 * the unwritten, attr_fork, and bmbt flags.  The startblock and
 772 * offset are checked separately.
 773 */
 774static bool
 775xfs_rmap_is_mergeable(
 776	struct xfs_rmap_irec	*irec,
 777	uint64_t		owner,
 778	unsigned int		flags)
 779{
 780	if (irec->rm_owner == XFS_RMAP_OWN_NULL)
 781		return false;
 782	if (irec->rm_owner != owner)
 783		return false;
 784	if ((flags & XFS_RMAP_UNWRITTEN) ^
 785	    (irec->rm_flags & XFS_RMAP_UNWRITTEN))
 786		return false;
 787	if ((flags & XFS_RMAP_ATTR_FORK) ^
 788	    (irec->rm_flags & XFS_RMAP_ATTR_FORK))
 789		return false;
 790	if ((flags & XFS_RMAP_BMBT_BLOCK) ^
 791	    (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
 792		return false;
 793	return true;
 794}
 795
 796/*
 797 * When we allocate a new block, the first thing we do is add a reference to
 798 * the extent in the rmap btree. This takes the form of a [agbno, length,
 799 * owner, offset] record.  Flags are encoded in the high bits of the offset
 800 * field.
 801 */
 802STATIC int
 803xfs_rmap_map(
 804	struct xfs_btree_cur		*cur,
 805	xfs_agblock_t			bno,
 806	xfs_extlen_t			len,
 807	bool				unwritten,
 808	const struct xfs_owner_info	*oinfo)
 809{
 810	struct xfs_mount		*mp = cur->bc_mp;
 811	struct xfs_rmap_irec		ltrec;
 812	struct xfs_rmap_irec		gtrec;
 813	int				have_gt;
 814	int				have_lt;
 815	int				error = 0;
 816	int				i;
 817	uint64_t			owner;
 818	uint64_t			offset;
 819	unsigned int			flags = 0;
 820	bool				ignore_off;
 821
 822	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 823	ASSERT(owner != 0);
 824	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
 825			(flags & XFS_RMAP_BMBT_BLOCK);
 826	if (unwritten)
 827		flags |= XFS_RMAP_UNWRITTEN;
 828	trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
 829			unwritten, oinfo);
 830	ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
 831
 832	/*
 833	 * For the initial lookup, look for an exact match or the left-adjacent
 834	 * record for our insertion point. This will also give us the record for
 835	 * start block contiguity tests.
 836	 */
 837	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec,
 838			&have_lt);
 839	if (error)
 840		goto out_error;
 841	if (have_lt) {
 
 
 
 
 
 
 
 842		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 843				cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
 844				ltrec.rm_blockcount, ltrec.rm_owner,
 845				ltrec.rm_offset, ltrec.rm_flags);
 846
 847		if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
 848			have_lt = 0;
 849	}
 850
 851	if (XFS_IS_CORRUPT(mp,
 852			   have_lt != 0 &&
 853			   ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
 854		error = -EFSCORRUPTED;
 855		goto out_error;
 856	}
 857
 858	/*
 859	 * Increment the cursor to see if we have a right-adjacent record to our
 860	 * insertion point. This will give us the record for end block
 861	 * contiguity tests.
 862	 */
 863	error = xfs_btree_increment(cur, 0, &have_gt);
 864	if (error)
 865		goto out_error;
 866	if (have_gt) {
 867		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
 868		if (error)
 869			goto out_error;
 870		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
 871			error = -EFSCORRUPTED;
 872			goto out_error;
 873		}
 874		if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
 875			error = -EFSCORRUPTED;
 876			goto out_error;
 877		}
 878		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
 879			cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
 880			gtrec.rm_blockcount, gtrec.rm_owner,
 881			gtrec.rm_offset, gtrec.rm_flags);
 882		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
 883			have_gt = 0;
 884	}
 885
 886	/*
 887	 * Note: cursor currently points one record to the right of ltrec, even
 888	 * if there is no record in the tree to the right.
 889	 */
 890	if (have_lt &&
 891	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
 892	    (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
 893		/*
 894		 * left edge contiguous, merge into left record.
 895		 *
 896		 *       ltbno     ltlen
 897		 * orig:   |ooooooooo|
 898		 * adding:           |aaaaaaaaa|
 899		 * result: |rrrrrrrrrrrrrrrrrrr|
 900		 *                  bno       len
 901		 */
 902		ltrec.rm_blockcount += len;
 903		if (have_gt &&
 904		    bno + len == gtrec.rm_startblock &&
 905		    (ignore_off || offset + len == gtrec.rm_offset) &&
 906		    (unsigned long)ltrec.rm_blockcount + len +
 907				gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
 908			/*
 909			 * right edge also contiguous, delete right record
 910			 * and merge into left record.
 911			 *
 912			 *       ltbno     ltlen    gtbno     gtlen
 913			 * orig:   |ooooooooo|         |ooooooooo|
 914			 * adding:           |aaaaaaaaa|
 915			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
 916			 */
 917			ltrec.rm_blockcount += gtrec.rm_blockcount;
 918			trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
 919					gtrec.rm_startblock,
 920					gtrec.rm_blockcount,
 921					gtrec.rm_owner,
 922					gtrec.rm_offset,
 923					gtrec.rm_flags);
 924			error = xfs_btree_delete(cur, &i);
 925			if (error)
 926				goto out_error;
 927			if (XFS_IS_CORRUPT(mp, i != 1)) {
 928				error = -EFSCORRUPTED;
 929				goto out_error;
 930			}
 931		}
 932
 933		/* point the cursor back to the left record and update */
 934		error = xfs_btree_decrement(cur, 0, &have_gt);
 935		if (error)
 936			goto out_error;
 937		error = xfs_rmap_update(cur, &ltrec);
 938		if (error)
 939			goto out_error;
 940	} else if (have_gt &&
 941		   bno + len == gtrec.rm_startblock &&
 942		   (ignore_off || offset + len == gtrec.rm_offset)) {
 943		/*
 944		 * right edge contiguous, merge into right record.
 945		 *
 946		 *                 gtbno     gtlen
 947		 * Orig:             |ooooooooo|
 948		 * adding: |aaaaaaaaa|
 949		 * Result: |rrrrrrrrrrrrrrrrrrr|
 950		 *        bno       len
 951		 */
 952		gtrec.rm_startblock = bno;
 953		gtrec.rm_blockcount += len;
 954		if (!ignore_off)
 955			gtrec.rm_offset = offset;
 956		error = xfs_rmap_update(cur, &gtrec);
 957		if (error)
 958			goto out_error;
 959	} else {
 960		/*
 961		 * no contiguous edge with identical owner, insert
 962		 * new record at current cursor position.
 963		 */
 964		cur->bc_rec.r.rm_startblock = bno;
 965		cur->bc_rec.r.rm_blockcount = len;
 966		cur->bc_rec.r.rm_owner = owner;
 967		cur->bc_rec.r.rm_offset = offset;
 968		cur->bc_rec.r.rm_flags = flags;
 969		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
 970			owner, offset, flags);
 971		error = xfs_btree_insert(cur, &i);
 972		if (error)
 973			goto out_error;
 974		if (XFS_IS_CORRUPT(mp, i != 1)) {
 975			error = -EFSCORRUPTED;
 976			goto out_error;
 977		}
 978	}
 979
 980	trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
 981			unwritten, oinfo);
 982out_error:
 983	if (error)
 984		trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
 985				error, _RET_IP_);
 986	return error;
 987}
 988
 989/*
 990 * Add a reference to an extent in the rmap btree.
 991 */
 992int
 993xfs_rmap_alloc(
 994	struct xfs_trans		*tp,
 995	struct xfs_buf			*agbp,
 996	struct xfs_perag		*pag,
 997	xfs_agblock_t			bno,
 998	xfs_extlen_t			len,
 999	const struct xfs_owner_info	*oinfo)
1000{
1001	struct xfs_mount		*mp = tp->t_mountp;
1002	struct xfs_btree_cur		*cur;
1003	int				error;
1004
1005	if (!xfs_has_rmapbt(mp))
1006		return 0;
1007
1008	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
1009	error = xfs_rmap_map(cur, bno, len, false, oinfo);
1010
1011	xfs_btree_del_cursor(cur, error);
1012	return error;
1013}
1014
1015#define RMAP_LEFT_CONTIG	(1 << 0)
1016#define RMAP_RIGHT_CONTIG	(1 << 1)
1017#define RMAP_LEFT_FILLING	(1 << 2)
1018#define RMAP_RIGHT_FILLING	(1 << 3)
1019#define RMAP_LEFT_VALID		(1 << 6)
1020#define RMAP_RIGHT_VALID	(1 << 7)
1021
1022#define LEFT		r[0]
1023#define RIGHT		r[1]
1024#define PREV		r[2]
1025#define NEW		r[3]
1026
1027/*
1028 * Convert an unwritten extent to a real extent or vice versa.
1029 * Does not handle overlapping extents.
1030 */
1031STATIC int
1032xfs_rmap_convert(
1033	struct xfs_btree_cur		*cur,
1034	xfs_agblock_t			bno,
1035	xfs_extlen_t			len,
1036	bool				unwritten,
1037	const struct xfs_owner_info	*oinfo)
1038{
1039	struct xfs_mount		*mp = cur->bc_mp;
1040	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
1041						/* left is 0, right is 1, */
1042						/* prev is 2, new is 3 */
1043	uint64_t		owner;
1044	uint64_t		offset;
1045	uint64_t		new_endoff;
1046	unsigned int		oldext;
1047	unsigned int		newext;
1048	unsigned int		flags = 0;
1049	int			i;
1050	int			state = 0;
1051	int			error;
1052
1053	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1054	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1055			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1056	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1057	new_endoff = offset + len;
1058	trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1059			unwritten, oinfo);
1060
1061	/*
1062	 * For the initial lookup, look for an exact match or the left-adjacent
1063	 * record for our insertion point. This will also give us the record for
1064	 * start block contiguity tests.
1065	 */
1066	error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1067	if (error)
1068		goto done;
1069	if (XFS_IS_CORRUPT(mp, i != 1)) {
1070		error = -EFSCORRUPTED;
1071		goto done;
1072	}
1073
 
 
 
 
 
 
 
1074	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1075			cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1076			PREV.rm_blockcount, PREV.rm_owner,
1077			PREV.rm_offset, PREV.rm_flags);
1078
1079	ASSERT(PREV.rm_offset <= offset);
1080	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1081	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1082	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1083
1084	/*
1085	 * Set flags determining what part of the previous oldext allocation
1086	 * extent is being replaced by a newext allocation.
1087	 */
1088	if (PREV.rm_offset == offset)
1089		state |= RMAP_LEFT_FILLING;
1090	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1091		state |= RMAP_RIGHT_FILLING;
1092
1093	/*
1094	 * Decrement the cursor to see if we have a left-adjacent record to our
1095	 * insertion point. This will give us the record for end block
1096	 * contiguity tests.
1097	 */
1098	error = xfs_btree_decrement(cur, 0, &i);
1099	if (error)
1100		goto done;
1101	if (i) {
1102		state |= RMAP_LEFT_VALID;
1103		error = xfs_rmap_get_rec(cur, &LEFT, &i);
1104		if (error)
1105			goto done;
1106		if (XFS_IS_CORRUPT(mp, i != 1)) {
1107			error = -EFSCORRUPTED;
1108			goto done;
1109		}
1110		if (XFS_IS_CORRUPT(mp,
1111				   LEFT.rm_startblock + LEFT.rm_blockcount >
1112				   bno)) {
1113			error = -EFSCORRUPTED;
1114			goto done;
1115		}
1116		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1117				cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1118				LEFT.rm_blockcount, LEFT.rm_owner,
1119				LEFT.rm_offset, LEFT.rm_flags);
1120		if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1121		    LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1122		    xfs_rmap_is_mergeable(&LEFT, owner, newext))
1123			state |= RMAP_LEFT_CONTIG;
1124	}
1125
1126	/*
1127	 * Increment the cursor to see if we have a right-adjacent record to our
1128	 * insertion point. This will give us the record for end block
1129	 * contiguity tests.
1130	 */
1131	error = xfs_btree_increment(cur, 0, &i);
1132	if (error)
1133		goto done;
1134	if (XFS_IS_CORRUPT(mp, i != 1)) {
1135		error = -EFSCORRUPTED;
1136		goto done;
1137	}
1138	error = xfs_btree_increment(cur, 0, &i);
1139	if (error)
1140		goto done;
1141	if (i) {
1142		state |= RMAP_RIGHT_VALID;
1143		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1144		if (error)
1145			goto done;
1146		if (XFS_IS_CORRUPT(mp, i != 1)) {
1147			error = -EFSCORRUPTED;
1148			goto done;
1149		}
1150		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1151			error = -EFSCORRUPTED;
1152			goto done;
1153		}
1154		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1155				cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1156				RIGHT.rm_blockcount, RIGHT.rm_owner,
1157				RIGHT.rm_offset, RIGHT.rm_flags);
1158		if (bno + len == RIGHT.rm_startblock &&
1159		    offset + len == RIGHT.rm_offset &&
1160		    xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1161			state |= RMAP_RIGHT_CONTIG;
1162	}
1163
1164	/* check that left + prev + right is not too long */
1165	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1166			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1167	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1168	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1169	    (unsigned long)LEFT.rm_blockcount + len +
1170	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1171		state &= ~RMAP_RIGHT_CONTIG;
1172
1173	trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1174			_RET_IP_);
1175
1176	/* reset the cursor back to PREV */
1177	error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1178	if (error)
1179		goto done;
1180	if (XFS_IS_CORRUPT(mp, i != 1)) {
1181		error = -EFSCORRUPTED;
1182		goto done;
1183	}
1184
1185	/*
1186	 * Switch out based on the FILLING and CONTIG state bits.
1187	 */
1188	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1189			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1190	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1191	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1192		/*
1193		 * Setting all of a previous oldext extent to newext.
1194		 * The left and right neighbors are both contiguous with new.
1195		 */
1196		error = xfs_btree_increment(cur, 0, &i);
1197		if (error)
1198			goto done;
1199		if (XFS_IS_CORRUPT(mp, i != 1)) {
1200			error = -EFSCORRUPTED;
1201			goto done;
1202		}
1203		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1204				RIGHT.rm_startblock, RIGHT.rm_blockcount,
1205				RIGHT.rm_owner, RIGHT.rm_offset,
1206				RIGHT.rm_flags);
1207		error = xfs_btree_delete(cur, &i);
1208		if (error)
1209			goto done;
1210		if (XFS_IS_CORRUPT(mp, i != 1)) {
1211			error = -EFSCORRUPTED;
1212			goto done;
1213		}
1214		error = xfs_btree_decrement(cur, 0, &i);
1215		if (error)
1216			goto done;
1217		if (XFS_IS_CORRUPT(mp, i != 1)) {
1218			error = -EFSCORRUPTED;
1219			goto done;
1220		}
1221		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1222				PREV.rm_startblock, PREV.rm_blockcount,
1223				PREV.rm_owner, PREV.rm_offset,
1224				PREV.rm_flags);
1225		error = xfs_btree_delete(cur, &i);
1226		if (error)
1227			goto done;
1228		if (XFS_IS_CORRUPT(mp, i != 1)) {
1229			error = -EFSCORRUPTED;
1230			goto done;
1231		}
1232		error = xfs_btree_decrement(cur, 0, &i);
1233		if (error)
1234			goto done;
1235		if (XFS_IS_CORRUPT(mp, i != 1)) {
1236			error = -EFSCORRUPTED;
1237			goto done;
1238		}
1239		NEW = LEFT;
1240		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1241		error = xfs_rmap_update(cur, &NEW);
1242		if (error)
1243			goto done;
1244		break;
1245
1246	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1247		/*
1248		 * Setting all of a previous oldext extent to newext.
1249		 * The left neighbor is contiguous, the right is not.
1250		 */
1251		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1252				PREV.rm_startblock, PREV.rm_blockcount,
1253				PREV.rm_owner, PREV.rm_offset,
1254				PREV.rm_flags);
1255		error = xfs_btree_delete(cur, &i);
1256		if (error)
1257			goto done;
1258		if (XFS_IS_CORRUPT(mp, i != 1)) {
1259			error = -EFSCORRUPTED;
1260			goto done;
1261		}
1262		error = xfs_btree_decrement(cur, 0, &i);
1263		if (error)
1264			goto done;
1265		if (XFS_IS_CORRUPT(mp, i != 1)) {
1266			error = -EFSCORRUPTED;
1267			goto done;
1268		}
1269		NEW = LEFT;
1270		NEW.rm_blockcount += PREV.rm_blockcount;
1271		error = xfs_rmap_update(cur, &NEW);
1272		if (error)
1273			goto done;
1274		break;
1275
1276	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1277		/*
1278		 * Setting all of a previous oldext extent to newext.
1279		 * The right neighbor is contiguous, the left is not.
1280		 */
1281		error = xfs_btree_increment(cur, 0, &i);
1282		if (error)
1283			goto done;
1284		if (XFS_IS_CORRUPT(mp, i != 1)) {
1285			error = -EFSCORRUPTED;
1286			goto done;
1287		}
1288		trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1289				RIGHT.rm_startblock, RIGHT.rm_blockcount,
1290				RIGHT.rm_owner, RIGHT.rm_offset,
1291				RIGHT.rm_flags);
1292		error = xfs_btree_delete(cur, &i);
1293		if (error)
1294			goto done;
1295		if (XFS_IS_CORRUPT(mp, i != 1)) {
1296			error = -EFSCORRUPTED;
1297			goto done;
1298		}
1299		error = xfs_btree_decrement(cur, 0, &i);
1300		if (error)
1301			goto done;
1302		if (XFS_IS_CORRUPT(mp, i != 1)) {
1303			error = -EFSCORRUPTED;
1304			goto done;
1305		}
1306		NEW = PREV;
1307		NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1308		NEW.rm_flags = newext;
1309		error = xfs_rmap_update(cur, &NEW);
1310		if (error)
1311			goto done;
1312		break;
1313
1314	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1315		/*
1316		 * Setting all of a previous oldext extent to newext.
1317		 * Neither the left nor right neighbors are contiguous with
1318		 * the new one.
1319		 */
1320		NEW = PREV;
1321		NEW.rm_flags = newext;
1322		error = xfs_rmap_update(cur, &NEW);
1323		if (error)
1324			goto done;
1325		break;
1326
1327	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1328		/*
1329		 * Setting the first part of a previous oldext extent to newext.
1330		 * The left neighbor is contiguous.
1331		 */
1332		NEW = PREV;
1333		NEW.rm_offset += len;
1334		NEW.rm_startblock += len;
1335		NEW.rm_blockcount -= len;
1336		error = xfs_rmap_update(cur, &NEW);
1337		if (error)
1338			goto done;
1339		error = xfs_btree_decrement(cur, 0, &i);
1340		if (error)
1341			goto done;
1342		NEW = LEFT;
1343		NEW.rm_blockcount += len;
1344		error = xfs_rmap_update(cur, &NEW);
1345		if (error)
1346			goto done;
1347		break;
1348
1349	case RMAP_LEFT_FILLING:
1350		/*
1351		 * Setting the first part of a previous oldext extent to newext.
1352		 * The left neighbor is not contiguous.
1353		 */
1354		NEW = PREV;
1355		NEW.rm_startblock += len;
1356		NEW.rm_offset += len;
1357		NEW.rm_blockcount -= len;
1358		error = xfs_rmap_update(cur, &NEW);
1359		if (error)
1360			goto done;
1361		NEW.rm_startblock = bno;
1362		NEW.rm_owner = owner;
1363		NEW.rm_offset = offset;
1364		NEW.rm_blockcount = len;
1365		NEW.rm_flags = newext;
1366		cur->bc_rec.r = NEW;
1367		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1368				len, owner, offset, newext);
1369		error = xfs_btree_insert(cur, &i);
1370		if (error)
1371			goto done;
1372		if (XFS_IS_CORRUPT(mp, i != 1)) {
1373			error = -EFSCORRUPTED;
1374			goto done;
1375		}
1376		break;
1377
1378	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1379		/*
1380		 * Setting the last part of a previous oldext extent to newext.
1381		 * The right neighbor is contiguous with the new allocation.
1382		 */
1383		NEW = PREV;
1384		NEW.rm_blockcount -= len;
1385		error = xfs_rmap_update(cur, &NEW);
1386		if (error)
1387			goto done;
1388		error = xfs_btree_increment(cur, 0, &i);
1389		if (error)
1390			goto done;
1391		NEW = RIGHT;
1392		NEW.rm_offset = offset;
1393		NEW.rm_startblock = bno;
1394		NEW.rm_blockcount += len;
1395		error = xfs_rmap_update(cur, &NEW);
1396		if (error)
1397			goto done;
1398		break;
1399
1400	case RMAP_RIGHT_FILLING:
1401		/*
1402		 * Setting the last part of a previous oldext extent to newext.
1403		 * The right neighbor is not contiguous.
1404		 */
1405		NEW = PREV;
1406		NEW.rm_blockcount -= len;
1407		error = xfs_rmap_update(cur, &NEW);
1408		if (error)
1409			goto done;
1410		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1411				oldext, &i);
1412		if (error)
1413			goto done;
1414		if (XFS_IS_CORRUPT(mp, i != 0)) {
1415			error = -EFSCORRUPTED;
1416			goto done;
1417		}
1418		NEW.rm_startblock = bno;
1419		NEW.rm_owner = owner;
1420		NEW.rm_offset = offset;
1421		NEW.rm_blockcount = len;
1422		NEW.rm_flags = newext;
1423		cur->bc_rec.r = NEW;
1424		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1425				len, owner, offset, newext);
1426		error = xfs_btree_insert(cur, &i);
1427		if (error)
1428			goto done;
1429		if (XFS_IS_CORRUPT(mp, i != 1)) {
1430			error = -EFSCORRUPTED;
1431			goto done;
1432		}
1433		break;
1434
1435	case 0:
1436		/*
1437		 * Setting the middle part of a previous oldext extent to
1438		 * newext.  Contiguity is impossible here.
1439		 * One extent becomes three extents.
1440		 */
1441		/* new right extent - oldext */
1442		NEW.rm_startblock = bno + len;
1443		NEW.rm_owner = owner;
1444		NEW.rm_offset = new_endoff;
1445		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1446				new_endoff;
1447		NEW.rm_flags = PREV.rm_flags;
1448		error = xfs_rmap_update(cur, &NEW);
1449		if (error)
1450			goto done;
1451		/* new left extent - oldext */
1452		NEW = PREV;
1453		NEW.rm_blockcount = offset - PREV.rm_offset;
1454		cur->bc_rec.r = NEW;
1455		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1456				NEW.rm_startblock, NEW.rm_blockcount,
1457				NEW.rm_owner, NEW.rm_offset,
1458				NEW.rm_flags);
1459		error = xfs_btree_insert(cur, &i);
1460		if (error)
1461			goto done;
1462		if (XFS_IS_CORRUPT(mp, i != 1)) {
1463			error = -EFSCORRUPTED;
1464			goto done;
1465		}
1466		/*
1467		 * Reset the cursor to the position of the new extent
1468		 * we are about to insert as we can't trust it after
1469		 * the previous insert.
1470		 */
1471		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1472				oldext, &i);
1473		if (error)
1474			goto done;
1475		if (XFS_IS_CORRUPT(mp, i != 0)) {
1476			error = -EFSCORRUPTED;
1477			goto done;
1478		}
1479		/* new middle extent - newext */
1480		cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1481		cur->bc_rec.r.rm_flags |= newext;
1482		trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1483				owner, offset, newext);
1484		error = xfs_btree_insert(cur, &i);
1485		if (error)
1486			goto done;
1487		if (XFS_IS_CORRUPT(mp, i != 1)) {
1488			error = -EFSCORRUPTED;
1489			goto done;
1490		}
1491		break;
1492
1493	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1494	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1495	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1496	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1497	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1498	case RMAP_LEFT_CONTIG:
1499	case RMAP_RIGHT_CONTIG:
1500		/*
1501		 * These cases are all impossible.
1502		 */
1503		ASSERT(0);
1504	}
1505
1506	trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1507			unwritten, oinfo);
1508done:
1509	if (error)
1510		trace_xfs_rmap_convert_error(cur->bc_mp,
1511				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1512	return error;
1513}
1514
1515/*
1516 * Convert an unwritten extent to a real extent or vice versa.  If there is no
1517 * possibility of overlapping extents, delegate to the simpler convert
1518 * function.
1519 */
1520STATIC int
1521xfs_rmap_convert_shared(
1522	struct xfs_btree_cur		*cur,
1523	xfs_agblock_t			bno,
1524	xfs_extlen_t			len,
1525	bool				unwritten,
1526	const struct xfs_owner_info	*oinfo)
1527{
1528	struct xfs_mount		*mp = cur->bc_mp;
1529	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
1530						/* left is 0, right is 1, */
1531						/* prev is 2, new is 3 */
1532	uint64_t		owner;
1533	uint64_t		offset;
1534	uint64_t		new_endoff;
1535	unsigned int		oldext;
1536	unsigned int		newext;
1537	unsigned int		flags = 0;
1538	int			i;
1539	int			state = 0;
1540	int			error;
1541
1542	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1543	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1544			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1545	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1546	new_endoff = offset + len;
1547	trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1548			unwritten, oinfo);
1549
1550	/*
1551	 * For the initial lookup, look for and exact match or the left-adjacent
1552	 * record for our insertion point. This will also give us the record for
1553	 * start block contiguity tests.
1554	 */
1555	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1556			&PREV, &i);
1557	if (error)
1558		goto done;
1559	if (XFS_IS_CORRUPT(mp, i != 1)) {
1560		error = -EFSCORRUPTED;
1561		goto done;
1562	}
1563
1564	ASSERT(PREV.rm_offset <= offset);
1565	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1566	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1567	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1568
1569	/*
1570	 * Set flags determining what part of the previous oldext allocation
1571	 * extent is being replaced by a newext allocation.
1572	 */
1573	if (PREV.rm_offset == offset)
1574		state |= RMAP_LEFT_FILLING;
1575	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1576		state |= RMAP_RIGHT_FILLING;
1577
1578	/* Is there a left record that abuts our range? */
1579	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1580			&LEFT, &i);
1581	if (error)
1582		goto done;
1583	if (i) {
1584		state |= RMAP_LEFT_VALID;
1585		if (XFS_IS_CORRUPT(mp,
1586				   LEFT.rm_startblock + LEFT.rm_blockcount >
1587				   bno)) {
1588			error = -EFSCORRUPTED;
1589			goto done;
1590		}
1591		if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1592			state |= RMAP_LEFT_CONTIG;
1593	}
1594
1595	/* Is there a right record that abuts our range? */
1596	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1597			newext, &i);
1598	if (error)
1599		goto done;
1600	if (i) {
1601		state |= RMAP_RIGHT_VALID;
1602		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1603		if (error)
1604			goto done;
1605		if (XFS_IS_CORRUPT(mp, i != 1)) {
1606			error = -EFSCORRUPTED;
1607			goto done;
1608		}
1609		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1610			error = -EFSCORRUPTED;
1611			goto done;
1612		}
1613		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1614				cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1615				RIGHT.rm_blockcount, RIGHT.rm_owner,
1616				RIGHT.rm_offset, RIGHT.rm_flags);
1617		if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1618			state |= RMAP_RIGHT_CONTIG;
1619	}
1620
1621	/* check that left + prev + right is not too long */
1622	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1623			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1624	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1625	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1626	    (unsigned long)LEFT.rm_blockcount + len +
1627	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1628		state &= ~RMAP_RIGHT_CONTIG;
1629
1630	trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1631			_RET_IP_);
1632	/*
1633	 * Switch out based on the FILLING and CONTIG state bits.
1634	 */
1635	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1636			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1637	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1638	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1639		/*
1640		 * Setting all of a previous oldext extent to newext.
1641		 * The left and right neighbors are both contiguous with new.
1642		 */
1643		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1644				RIGHT.rm_blockcount, RIGHT.rm_owner,
1645				RIGHT.rm_offset, RIGHT.rm_flags);
1646		if (error)
1647			goto done;
1648		error = xfs_rmap_delete(cur, PREV.rm_startblock,
1649				PREV.rm_blockcount, PREV.rm_owner,
1650				PREV.rm_offset, PREV.rm_flags);
1651		if (error)
1652			goto done;
1653		NEW = LEFT;
1654		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1655				NEW.rm_blockcount, NEW.rm_owner,
1656				NEW.rm_offset, NEW.rm_flags, &i);
1657		if (error)
1658			goto done;
1659		if (XFS_IS_CORRUPT(mp, i != 1)) {
1660			error = -EFSCORRUPTED;
1661			goto done;
1662		}
1663		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1664		error = xfs_rmap_update(cur, &NEW);
1665		if (error)
1666			goto done;
1667		break;
1668
1669	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1670		/*
1671		 * Setting all of a previous oldext extent to newext.
1672		 * The left neighbor is contiguous, the right is not.
1673		 */
1674		error = xfs_rmap_delete(cur, PREV.rm_startblock,
1675				PREV.rm_blockcount, PREV.rm_owner,
1676				PREV.rm_offset, PREV.rm_flags);
1677		if (error)
1678			goto done;
1679		NEW = LEFT;
1680		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1681				NEW.rm_blockcount, NEW.rm_owner,
1682				NEW.rm_offset, NEW.rm_flags, &i);
1683		if (error)
1684			goto done;
1685		if (XFS_IS_CORRUPT(mp, i != 1)) {
1686			error = -EFSCORRUPTED;
1687			goto done;
1688		}
1689		NEW.rm_blockcount += PREV.rm_blockcount;
1690		error = xfs_rmap_update(cur, &NEW);
1691		if (error)
1692			goto done;
1693		break;
1694
1695	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1696		/*
1697		 * Setting all of a previous oldext extent to newext.
1698		 * The right neighbor is contiguous, the left is not.
1699		 */
1700		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1701				RIGHT.rm_blockcount, RIGHT.rm_owner,
1702				RIGHT.rm_offset, RIGHT.rm_flags);
1703		if (error)
1704			goto done;
1705		NEW = PREV;
1706		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1707				NEW.rm_blockcount, NEW.rm_owner,
1708				NEW.rm_offset, NEW.rm_flags, &i);
1709		if (error)
1710			goto done;
1711		if (XFS_IS_CORRUPT(mp, i != 1)) {
1712			error = -EFSCORRUPTED;
1713			goto done;
1714		}
1715		NEW.rm_blockcount += RIGHT.rm_blockcount;
1716		NEW.rm_flags = RIGHT.rm_flags;
1717		error = xfs_rmap_update(cur, &NEW);
1718		if (error)
1719			goto done;
1720		break;
1721
1722	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1723		/*
1724		 * Setting all of a previous oldext extent to newext.
1725		 * Neither the left nor right neighbors are contiguous with
1726		 * the new one.
1727		 */
1728		NEW = PREV;
1729		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1730				NEW.rm_blockcount, NEW.rm_owner,
1731				NEW.rm_offset, NEW.rm_flags, &i);
1732		if (error)
1733			goto done;
1734		if (XFS_IS_CORRUPT(mp, i != 1)) {
1735			error = -EFSCORRUPTED;
1736			goto done;
1737		}
1738		NEW.rm_flags = newext;
1739		error = xfs_rmap_update(cur, &NEW);
1740		if (error)
1741			goto done;
1742		break;
1743
1744	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1745		/*
1746		 * Setting the first part of a previous oldext extent to newext.
1747		 * The left neighbor is contiguous.
1748		 */
1749		NEW = PREV;
1750		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1751				NEW.rm_blockcount, NEW.rm_owner,
1752				NEW.rm_offset, NEW.rm_flags);
1753		if (error)
1754			goto done;
1755		NEW.rm_offset += len;
1756		NEW.rm_startblock += len;
1757		NEW.rm_blockcount -= len;
1758		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1759				NEW.rm_blockcount, NEW.rm_owner,
1760				NEW.rm_offset, NEW.rm_flags);
1761		if (error)
1762			goto done;
1763		NEW = LEFT;
1764		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1765				NEW.rm_blockcount, NEW.rm_owner,
1766				NEW.rm_offset, NEW.rm_flags, &i);
1767		if (error)
1768			goto done;
1769		if (XFS_IS_CORRUPT(mp, i != 1)) {
1770			error = -EFSCORRUPTED;
1771			goto done;
1772		}
1773		NEW.rm_blockcount += len;
1774		error = xfs_rmap_update(cur, &NEW);
1775		if (error)
1776			goto done;
1777		break;
1778
1779	case RMAP_LEFT_FILLING:
1780		/*
1781		 * Setting the first part of a previous oldext extent to newext.
1782		 * The left neighbor is not contiguous.
1783		 */
1784		NEW = PREV;
1785		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1786				NEW.rm_blockcount, NEW.rm_owner,
1787				NEW.rm_offset, NEW.rm_flags);
1788		if (error)
1789			goto done;
1790		NEW.rm_offset += len;
1791		NEW.rm_startblock += len;
1792		NEW.rm_blockcount -= len;
1793		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1794				NEW.rm_blockcount, NEW.rm_owner,
1795				NEW.rm_offset, NEW.rm_flags);
1796		if (error)
1797			goto done;
1798		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1799		if (error)
1800			goto done;
1801		break;
1802
1803	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1804		/*
1805		 * Setting the last part of a previous oldext extent to newext.
1806		 * The right neighbor is contiguous with the new allocation.
1807		 */
1808		NEW = PREV;
1809		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1810				NEW.rm_blockcount, NEW.rm_owner,
1811				NEW.rm_offset, NEW.rm_flags, &i);
1812		if (error)
1813			goto done;
1814		if (XFS_IS_CORRUPT(mp, i != 1)) {
1815			error = -EFSCORRUPTED;
1816			goto done;
1817		}
1818		NEW.rm_blockcount = offset - NEW.rm_offset;
1819		error = xfs_rmap_update(cur, &NEW);
1820		if (error)
1821			goto done;
1822		NEW = RIGHT;
1823		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1824				NEW.rm_blockcount, NEW.rm_owner,
1825				NEW.rm_offset, NEW.rm_flags);
1826		if (error)
1827			goto done;
1828		NEW.rm_offset = offset;
1829		NEW.rm_startblock = bno;
1830		NEW.rm_blockcount += len;
1831		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1832				NEW.rm_blockcount, NEW.rm_owner,
1833				NEW.rm_offset, NEW.rm_flags);
1834		if (error)
1835			goto done;
1836		break;
1837
1838	case RMAP_RIGHT_FILLING:
1839		/*
1840		 * Setting the last part of a previous oldext extent to newext.
1841		 * The right neighbor is not contiguous.
1842		 */
1843		NEW = PREV;
1844		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1845				NEW.rm_blockcount, NEW.rm_owner,
1846				NEW.rm_offset, NEW.rm_flags, &i);
1847		if (error)
1848			goto done;
1849		if (XFS_IS_CORRUPT(mp, i != 1)) {
1850			error = -EFSCORRUPTED;
1851			goto done;
1852		}
1853		NEW.rm_blockcount -= len;
1854		error = xfs_rmap_update(cur, &NEW);
1855		if (error)
1856			goto done;
1857		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1858		if (error)
1859			goto done;
1860		break;
1861
1862	case 0:
1863		/*
1864		 * Setting the middle part of a previous oldext extent to
1865		 * newext.  Contiguity is impossible here.
1866		 * One extent becomes three extents.
1867		 */
1868		/* new right extent - oldext */
1869		NEW.rm_startblock = bno + len;
1870		NEW.rm_owner = owner;
1871		NEW.rm_offset = new_endoff;
1872		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1873				new_endoff;
1874		NEW.rm_flags = PREV.rm_flags;
1875		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1876				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1877				NEW.rm_flags);
1878		if (error)
1879			goto done;
1880		/* new left extent - oldext */
1881		NEW = PREV;
1882		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1883				NEW.rm_blockcount, NEW.rm_owner,
1884				NEW.rm_offset, NEW.rm_flags, &i);
1885		if (error)
1886			goto done;
1887		if (XFS_IS_CORRUPT(mp, i != 1)) {
1888			error = -EFSCORRUPTED;
1889			goto done;
1890		}
1891		NEW.rm_blockcount = offset - NEW.rm_offset;
1892		error = xfs_rmap_update(cur, &NEW);
1893		if (error)
1894			goto done;
1895		/* new middle extent - newext */
1896		NEW.rm_startblock = bno;
1897		NEW.rm_blockcount = len;
1898		NEW.rm_owner = owner;
1899		NEW.rm_offset = offset;
1900		NEW.rm_flags = newext;
1901		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1902				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1903				NEW.rm_flags);
1904		if (error)
1905			goto done;
1906		break;
1907
1908	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1909	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1910	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1911	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1912	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1913	case RMAP_LEFT_CONTIG:
1914	case RMAP_RIGHT_CONTIG:
1915		/*
1916		 * These cases are all impossible.
1917		 */
1918		ASSERT(0);
1919	}
1920
1921	trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1922			unwritten, oinfo);
1923done:
1924	if (error)
1925		trace_xfs_rmap_convert_error(cur->bc_mp,
1926				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1927	return error;
1928}
1929
1930#undef	NEW
1931#undef	LEFT
1932#undef	RIGHT
1933#undef	PREV
1934
1935/*
1936 * Find an extent in the rmap btree and unmap it.  For rmap extent types that
1937 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1938 * that the prev/next records in the btree might belong to another owner.
1939 * Therefore we must use delete+insert to alter any of the key fields.
1940 *
1941 * For every other situation there can only be one owner for a given extent,
1942 * so we can call the regular _free function.
1943 */
1944STATIC int
1945xfs_rmap_unmap_shared(
1946	struct xfs_btree_cur		*cur,
1947	xfs_agblock_t			bno,
1948	xfs_extlen_t			len,
1949	bool				unwritten,
1950	const struct xfs_owner_info	*oinfo)
1951{
1952	struct xfs_mount		*mp = cur->bc_mp;
1953	struct xfs_rmap_irec		ltrec;
1954	uint64_t			ltoff;
1955	int				error = 0;
1956	int				i;
1957	uint64_t			owner;
1958	uint64_t			offset;
1959	unsigned int			flags;
1960
1961	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1962	if (unwritten)
1963		flags |= XFS_RMAP_UNWRITTEN;
1964	trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
1965			unwritten, oinfo);
1966
1967	/*
1968	 * We should always have a left record because there's a static record
1969	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1970	 * will not ever be removed from the tree.
1971	 */
1972	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1973			&ltrec, &i);
1974	if (error)
1975		goto out_error;
1976	if (XFS_IS_CORRUPT(mp, i != 1)) {
1977		error = -EFSCORRUPTED;
1978		goto out_error;
1979	}
1980	ltoff = ltrec.rm_offset;
1981
1982	/* Make sure the extent we found covers the entire freeing range. */
1983	if (XFS_IS_CORRUPT(mp,
1984			   ltrec.rm_startblock > bno ||
1985			   ltrec.rm_startblock + ltrec.rm_blockcount <
1986			   bno + len)) {
1987		error = -EFSCORRUPTED;
1988		goto out_error;
1989	}
1990
1991	/* Make sure the owner matches what we expect to find in the tree. */
1992	if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1993		error = -EFSCORRUPTED;
1994		goto out_error;
1995	}
1996
1997	/* Make sure the unwritten flag matches. */
1998	if (XFS_IS_CORRUPT(mp,
1999			   (flags & XFS_RMAP_UNWRITTEN) !=
2000			   (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2001		error = -EFSCORRUPTED;
2002		goto out_error;
2003	}
2004
2005	/* Check the offset. */
2006	if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2007		error = -EFSCORRUPTED;
2008		goto out_error;
2009	}
2010	if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2011		error = -EFSCORRUPTED;
2012		goto out_error;
2013	}
2014
2015	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2016		/* Exact match, simply remove the record from rmap tree. */
2017		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2018				ltrec.rm_blockcount, ltrec.rm_owner,
2019				ltrec.rm_offset, ltrec.rm_flags);
2020		if (error)
2021			goto out_error;
2022	} else if (ltrec.rm_startblock == bno) {
2023		/*
2024		 * Overlap left hand side of extent: move the start, trim the
2025		 * length and update the current record.
2026		 *
2027		 *       ltbno                ltlen
2028		 * Orig:    |oooooooooooooooooooo|
2029		 * Freeing: |fffffffff|
2030		 * Result:            |rrrrrrrrrr|
2031		 *         bno       len
2032		 */
2033
2034		/* Delete prev rmap. */
2035		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2036				ltrec.rm_blockcount, ltrec.rm_owner,
2037				ltrec.rm_offset, ltrec.rm_flags);
2038		if (error)
2039			goto out_error;
2040
2041		/* Add an rmap at the new offset. */
2042		ltrec.rm_startblock += len;
2043		ltrec.rm_blockcount -= len;
2044		ltrec.rm_offset += len;
2045		error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2046				ltrec.rm_blockcount, ltrec.rm_owner,
2047				ltrec.rm_offset, ltrec.rm_flags);
2048		if (error)
2049			goto out_error;
2050	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2051		/*
2052		 * Overlap right hand side of extent: trim the length and
2053		 * update the current record.
2054		 *
2055		 *       ltbno                ltlen
2056		 * Orig:    |oooooooooooooooooooo|
2057		 * Freeing:            |fffffffff|
2058		 * Result:  |rrrrrrrrrr|
2059		 *                    bno       len
2060		 */
2061		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2062				ltrec.rm_blockcount, ltrec.rm_owner,
2063				ltrec.rm_offset, ltrec.rm_flags, &i);
2064		if (error)
2065			goto out_error;
2066		if (XFS_IS_CORRUPT(mp, i != 1)) {
2067			error = -EFSCORRUPTED;
2068			goto out_error;
2069		}
2070		ltrec.rm_blockcount -= len;
2071		error = xfs_rmap_update(cur, &ltrec);
2072		if (error)
2073			goto out_error;
2074	} else {
2075		/*
2076		 * Overlap middle of extent: trim the length of the existing
2077		 * record to the length of the new left-extent size, increment
2078		 * the insertion position so we can insert a new record
2079		 * containing the remaining right-extent space.
2080		 *
2081		 *       ltbno                ltlen
2082		 * Orig:    |oooooooooooooooooooo|
2083		 * Freeing:       |fffffffff|
2084		 * Result:  |rrrrr|         |rrrr|
2085		 *               bno       len
2086		 */
2087		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
2088
2089		/* Shrink the left side of the rmap */
2090		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2091				ltrec.rm_blockcount, ltrec.rm_owner,
2092				ltrec.rm_offset, ltrec.rm_flags, &i);
2093		if (error)
2094			goto out_error;
2095		if (XFS_IS_CORRUPT(mp, i != 1)) {
2096			error = -EFSCORRUPTED;
2097			goto out_error;
2098		}
2099		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2100		error = xfs_rmap_update(cur, &ltrec);
2101		if (error)
2102			goto out_error;
2103
2104		/* Add an rmap at the new offset */
2105		error = xfs_rmap_insert(cur, bno + len,
2106				orig_len - len - ltrec.rm_blockcount,
2107				ltrec.rm_owner, offset + len,
2108				ltrec.rm_flags);
2109		if (error)
2110			goto out_error;
2111	}
2112
2113	trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2114			unwritten, oinfo);
2115out_error:
2116	if (error)
2117		trace_xfs_rmap_unmap_error(cur->bc_mp,
2118				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2119	return error;
2120}
2121
2122/*
2123 * Find an extent in the rmap btree and map it.  For rmap extent types that
2124 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2125 * that the prev/next records in the btree might belong to another owner.
2126 * Therefore we must use delete+insert to alter any of the key fields.
2127 *
2128 * For every other situation there can only be one owner for a given extent,
2129 * so we can call the regular _alloc function.
2130 */
2131STATIC int
2132xfs_rmap_map_shared(
2133	struct xfs_btree_cur		*cur,
2134	xfs_agblock_t			bno,
2135	xfs_extlen_t			len,
2136	bool				unwritten,
2137	const struct xfs_owner_info	*oinfo)
2138{
2139	struct xfs_mount		*mp = cur->bc_mp;
2140	struct xfs_rmap_irec		ltrec;
2141	struct xfs_rmap_irec		gtrec;
2142	int				have_gt;
2143	int				have_lt;
2144	int				error = 0;
2145	int				i;
2146	uint64_t			owner;
2147	uint64_t			offset;
2148	unsigned int			flags = 0;
2149
2150	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2151	if (unwritten)
2152		flags |= XFS_RMAP_UNWRITTEN;
2153	trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2154			unwritten, oinfo);
2155
2156	/* Is there a left record that abuts our range? */
2157	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2158			&ltrec, &have_lt);
2159	if (error)
2160		goto out_error;
2161	if (have_lt &&
2162	    !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2163		have_lt = 0;
2164
2165	/* Is there a right record that abuts our range? */
2166	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2167			flags, &have_gt);
2168	if (error)
2169		goto out_error;
2170	if (have_gt) {
2171		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2172		if (error)
2173			goto out_error;
2174		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2175			error = -EFSCORRUPTED;
2176			goto out_error;
2177		}
2178		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2179			cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2180			gtrec.rm_blockcount, gtrec.rm_owner,
2181			gtrec.rm_offset, gtrec.rm_flags);
2182
2183		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2184			have_gt = 0;
2185	}
2186
2187	if (have_lt &&
2188	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2189	    ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2190		/*
2191		 * Left edge contiguous, merge into left record.
2192		 *
2193		 *       ltbno     ltlen
2194		 * orig:   |ooooooooo|
2195		 * adding:           |aaaaaaaaa|
2196		 * result: |rrrrrrrrrrrrrrrrrrr|
2197		 *                  bno       len
2198		 */
2199		ltrec.rm_blockcount += len;
2200		if (have_gt &&
2201		    bno + len == gtrec.rm_startblock &&
2202		    offset + len == gtrec.rm_offset) {
2203			/*
2204			 * Right edge also contiguous, delete right record
2205			 * and merge into left record.
2206			 *
2207			 *       ltbno     ltlen    gtbno     gtlen
2208			 * orig:   |ooooooooo|         |ooooooooo|
2209			 * adding:           |aaaaaaaaa|
2210			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2211			 */
2212			ltrec.rm_blockcount += gtrec.rm_blockcount;
2213			error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2214					gtrec.rm_blockcount, gtrec.rm_owner,
2215					gtrec.rm_offset, gtrec.rm_flags);
2216			if (error)
2217				goto out_error;
2218		}
2219
2220		/* Point the cursor back to the left record and update. */
2221		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2222				ltrec.rm_blockcount, ltrec.rm_owner,
2223				ltrec.rm_offset, ltrec.rm_flags, &i);
2224		if (error)
2225			goto out_error;
2226		if (XFS_IS_CORRUPT(mp, i != 1)) {
2227			error = -EFSCORRUPTED;
2228			goto out_error;
2229		}
2230
2231		error = xfs_rmap_update(cur, &ltrec);
2232		if (error)
2233			goto out_error;
2234	} else if (have_gt &&
2235		   bno + len == gtrec.rm_startblock &&
2236		   offset + len == gtrec.rm_offset) {
2237		/*
2238		 * Right edge contiguous, merge into right record.
2239		 *
2240		 *                 gtbno     gtlen
2241		 * Orig:             |ooooooooo|
2242		 * adding: |aaaaaaaaa|
2243		 * Result: |rrrrrrrrrrrrrrrrrrr|
2244		 *        bno       len
2245		 */
2246		/* Delete the old record. */
2247		error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2248				gtrec.rm_blockcount, gtrec.rm_owner,
2249				gtrec.rm_offset, gtrec.rm_flags);
2250		if (error)
2251			goto out_error;
2252
2253		/* Move the start and re-add it. */
2254		gtrec.rm_startblock = bno;
2255		gtrec.rm_blockcount += len;
2256		gtrec.rm_offset = offset;
2257		error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2258				gtrec.rm_blockcount, gtrec.rm_owner,
2259				gtrec.rm_offset, gtrec.rm_flags);
2260		if (error)
2261			goto out_error;
2262	} else {
2263		/*
2264		 * No contiguous edge with identical owner, insert
2265		 * new record at current cursor position.
2266		 */
2267		error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2268		if (error)
2269			goto out_error;
2270	}
2271
2272	trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2273			unwritten, oinfo);
2274out_error:
2275	if (error)
2276		trace_xfs_rmap_map_error(cur->bc_mp,
2277				cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2278	return error;
2279}
2280
2281/* Insert a raw rmap into the rmapbt. */
2282int
2283xfs_rmap_map_raw(
2284	struct xfs_btree_cur	*cur,
2285	struct xfs_rmap_irec	*rmap)
2286{
2287	struct xfs_owner_info	oinfo;
2288
2289	oinfo.oi_owner = rmap->rm_owner;
2290	oinfo.oi_offset = rmap->rm_offset;
2291	oinfo.oi_flags = 0;
2292	if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2293		oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2294	if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2295		oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2296
2297	if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2298		return xfs_rmap_map(cur, rmap->rm_startblock,
2299				rmap->rm_blockcount,
2300				rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2301				&oinfo);
2302
2303	return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2304			rmap->rm_blockcount,
2305			rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2306			&oinfo);
2307}
2308
2309struct xfs_rmap_query_range_info {
2310	xfs_rmap_query_range_fn	fn;
2311	void				*priv;
2312};
2313
2314/* Format btree record and pass to our callback. */
2315STATIC int
2316xfs_rmap_query_range_helper(
2317	struct xfs_btree_cur		*cur,
2318	const union xfs_btree_rec	*rec,
2319	void				*priv)
2320{
2321	struct xfs_rmap_query_range_info	*query = priv;
2322	struct xfs_rmap_irec			irec;
2323	int					error;
2324
2325	error = xfs_rmap_btrec_to_irec(rec, &irec);
2326	if (error)
2327		return error;
2328	return query->fn(cur, &irec, query->priv);
2329}
2330
2331/* Find all rmaps between two keys. */
2332int
2333xfs_rmap_query_range(
2334	struct xfs_btree_cur			*cur,
2335	const struct xfs_rmap_irec		*low_rec,
2336	const struct xfs_rmap_irec		*high_rec,
2337	xfs_rmap_query_range_fn			fn,
2338	void					*priv)
2339{
2340	union xfs_btree_irec			low_brec;
2341	union xfs_btree_irec			high_brec;
2342	struct xfs_rmap_query_range_info	query;
2343
2344	low_brec.r = *low_rec;
2345	high_brec.r = *high_rec;
2346	query.priv = priv;
2347	query.fn = fn;
2348	return xfs_btree_query_range(cur, &low_brec, &high_brec,
2349			xfs_rmap_query_range_helper, &query);
2350}
2351
2352/* Find all rmaps. */
2353int
2354xfs_rmap_query_all(
2355	struct xfs_btree_cur			*cur,
2356	xfs_rmap_query_range_fn			fn,
2357	void					*priv)
2358{
2359	struct xfs_rmap_query_range_info	query;
2360
2361	query.priv = priv;
2362	query.fn = fn;
2363	return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2364}
2365
2366/* Clean up after calling xfs_rmap_finish_one. */
2367void
2368xfs_rmap_finish_one_cleanup(
2369	struct xfs_trans	*tp,
2370	struct xfs_btree_cur	*rcur,
2371	int			error)
2372{
2373	struct xfs_buf		*agbp;
2374
2375	if (rcur == NULL)
2376		return;
2377	agbp = rcur->bc_ag.agbp;
2378	xfs_btree_del_cursor(rcur, error);
2379	if (error)
2380		xfs_trans_brelse(tp, agbp);
2381}
2382
2383/*
2384 * Process one of the deferred rmap operations.  We pass back the
2385 * btree cursor to maintain our lock on the rmapbt between calls.
2386 * This saves time and eliminates a buffer deadlock between the
2387 * superblock and the AGF because we'll always grab them in the same
2388 * order.
2389 */
2390int
2391xfs_rmap_finish_one(
2392	struct xfs_trans		*tp,
2393	enum xfs_rmap_intent_type	type,
2394	uint64_t			owner,
2395	int				whichfork,
2396	xfs_fileoff_t			startoff,
2397	xfs_fsblock_t			startblock,
2398	xfs_filblks_t			blockcount,
2399	xfs_exntst_t			state,
2400	struct xfs_btree_cur		**pcur)
2401{
2402	struct xfs_mount		*mp = tp->t_mountp;
2403	struct xfs_perag		*pag;
2404	struct xfs_btree_cur		*rcur;
2405	struct xfs_buf			*agbp = NULL;
2406	int				error = 0;
 
2407	struct xfs_owner_info		oinfo;
2408	xfs_agblock_t			bno;
2409	bool				unwritten;
2410
2411	pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
 
2412	bno = XFS_FSB_TO_AGBNO(mp, startblock);
2413
2414	trace_xfs_rmap_deferred(mp, pag->pag_agno, type, bno, owner, whichfork,
2415			startoff, blockcount, state);
2416
2417	if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
2418		error = -EIO;
2419		goto out_drop;
2420	}
2421
2422
2423	/*
2424	 * If we haven't gotten a cursor or the cursor AG doesn't match
2425	 * the startblock, get one now.
2426	 */
2427	rcur = *pcur;
2428	if (rcur != NULL && rcur->bc_ag.pag != pag) {
2429		xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2430		rcur = NULL;
2431		*pcur = NULL;
2432	}
2433	if (rcur == NULL) {
2434		/*
2435		 * Refresh the freelist before we start changing the
2436		 * rmapbt, because a shape change could cause us to
2437		 * allocate blocks.
2438		 */
2439		error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
2440		if (error)
2441			goto out_drop;
2442		if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2443			error = -EFSCORRUPTED;
2444			goto out_drop;
 
 
 
 
2445		}
2446
2447		rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
2448	}
2449	*pcur = rcur;
2450
2451	xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2452	unwritten = state == XFS_EXT_UNWRITTEN;
2453	bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2454
2455	switch (type) {
2456	case XFS_RMAP_ALLOC:
2457	case XFS_RMAP_MAP:
2458		error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2459		break;
2460	case XFS_RMAP_MAP_SHARED:
2461		error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2462				&oinfo);
2463		break;
2464	case XFS_RMAP_FREE:
2465	case XFS_RMAP_UNMAP:
2466		error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2467				&oinfo);
2468		break;
2469	case XFS_RMAP_UNMAP_SHARED:
2470		error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2471				&oinfo);
2472		break;
2473	case XFS_RMAP_CONVERT:
2474		error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2475				&oinfo);
2476		break;
2477	case XFS_RMAP_CONVERT_SHARED:
2478		error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2479				!unwritten, &oinfo);
2480		break;
2481	default:
2482		ASSERT(0);
2483		error = -EFSCORRUPTED;
2484	}
2485out_drop:
2486	xfs_perag_put(pag);
 
 
 
2487	return error;
2488}
2489
2490/*
2491 * Don't defer an rmap if we aren't an rmap filesystem.
2492 */
2493static bool
2494xfs_rmap_update_is_needed(
2495	struct xfs_mount	*mp,
2496	int			whichfork)
2497{
2498	return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2499}
2500
2501/*
2502 * Record a rmap intent; the list is kept sorted first by AG and then by
2503 * increasing age.
2504 */
2505static void
2506__xfs_rmap_add(
2507	struct xfs_trans		*tp,
2508	enum xfs_rmap_intent_type	type,
2509	uint64_t			owner,
2510	int				whichfork,
2511	struct xfs_bmbt_irec		*bmap)
2512{
2513	struct xfs_rmap_intent		*ri;
2514
2515	trace_xfs_rmap_defer(tp->t_mountp,
2516			XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2517			type,
2518			XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2519			owner, whichfork,
2520			bmap->br_startoff,
2521			bmap->br_blockcount,
2522			bmap->br_state);
2523
2524	ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
2525	INIT_LIST_HEAD(&ri->ri_list);
2526	ri->ri_type = type;
2527	ri->ri_owner = owner;
2528	ri->ri_whichfork = whichfork;
2529	ri->ri_bmap = *bmap;
2530
2531	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2532}
2533
2534/* Map an extent into a file. */
2535void
2536xfs_rmap_map_extent(
2537	struct xfs_trans	*tp,
2538	struct xfs_inode	*ip,
2539	int			whichfork,
2540	struct xfs_bmbt_irec	*PREV)
2541{
2542	enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2543
2544	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2545		return;
2546
2547	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2548		type = XFS_RMAP_MAP_SHARED;
2549
2550	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2551}
2552
2553/* Unmap an extent out of a file. */
2554void
2555xfs_rmap_unmap_extent(
2556	struct xfs_trans	*tp,
2557	struct xfs_inode	*ip,
2558	int			whichfork,
2559	struct xfs_bmbt_irec	*PREV)
2560{
2561	enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2562
2563	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2564		return;
2565
2566	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2567		type = XFS_RMAP_UNMAP_SHARED;
2568
2569	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2570}
2571
2572/*
2573 * Convert a data fork extent from unwritten to real or vice versa.
2574 *
2575 * Note that tp can be NULL here as no transaction is used for COW fork
2576 * unwritten conversion.
2577 */
2578void
2579xfs_rmap_convert_extent(
2580	struct xfs_mount	*mp,
2581	struct xfs_trans	*tp,
2582	struct xfs_inode	*ip,
2583	int			whichfork,
2584	struct xfs_bmbt_irec	*PREV)
2585{
2586	enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2587
2588	if (!xfs_rmap_update_is_needed(mp, whichfork))
2589		return;
2590
2591	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2592		type = XFS_RMAP_CONVERT_SHARED;
2593
2594	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2595}
2596
2597/* Schedule the creation of an rmap for non-file data. */
2598void
2599xfs_rmap_alloc_extent(
2600	struct xfs_trans	*tp,
2601	xfs_agnumber_t		agno,
2602	xfs_agblock_t		bno,
2603	xfs_extlen_t		len,
2604	uint64_t		owner)
2605{
2606	struct xfs_bmbt_irec	bmap;
2607
2608	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2609		return;
2610
2611	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2612	bmap.br_blockcount = len;
2613	bmap.br_startoff = 0;
2614	bmap.br_state = XFS_EXT_NORM;
2615
2616	__xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2617}
2618
2619/* Schedule the deletion of an rmap for non-file data. */
2620void
2621xfs_rmap_free_extent(
2622	struct xfs_trans	*tp,
2623	xfs_agnumber_t		agno,
2624	xfs_agblock_t		bno,
2625	xfs_extlen_t		len,
2626	uint64_t		owner)
2627{
2628	struct xfs_bmbt_irec	bmap;
2629
2630	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2631		return;
2632
2633	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2634	bmap.br_blockcount = len;
2635	bmap.br_startoff = 0;
2636	bmap.br_state = XFS_EXT_NORM;
2637
2638	__xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2639}
2640
2641/* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2642int
2643xfs_rmap_compare(
2644	const struct xfs_rmap_irec	*a,
2645	const struct xfs_rmap_irec	*b)
2646{
2647	__u64				oa;
2648	__u64				ob;
2649
2650	oa = xfs_rmap_irec_offset_pack(a);
2651	ob = xfs_rmap_irec_offset_pack(b);
2652
2653	if (a->rm_startblock < b->rm_startblock)
2654		return -1;
2655	else if (a->rm_startblock > b->rm_startblock)
2656		return 1;
2657	else if (a->rm_owner < b->rm_owner)
2658		return -1;
2659	else if (a->rm_owner > b->rm_owner)
2660		return 1;
2661	else if (oa < ob)
2662		return -1;
2663	else if (oa > ob)
2664		return 1;
2665	else
2666		return 0;
2667}
2668
2669/* Is there a record covering a given extent? */
2670int
2671xfs_rmap_has_record(
2672	struct xfs_btree_cur	*cur,
2673	xfs_agblock_t		bno,
2674	xfs_extlen_t		len,
2675	bool			*exists)
2676{
2677	union xfs_btree_irec	low;
2678	union xfs_btree_irec	high;
2679
2680	memset(&low, 0, sizeof(low));
2681	low.r.rm_startblock = bno;
2682	memset(&high, 0xFF, sizeof(high));
2683	high.r.rm_startblock = bno + len - 1;
2684
2685	return xfs_btree_has_record(cur, &low, &high, exists);
2686}
2687
2688/*
2689 * Is there a record for this owner completely covering a given physical
2690 * extent?  If so, *has_rmap will be set to true.  If there is no record
2691 * or the record only covers part of the range, we set *has_rmap to false.
2692 * This function doesn't perform range lookups or offset checks, so it is
2693 * not suitable for checking data fork blocks.
2694 */
2695int
2696xfs_rmap_record_exists(
2697	struct xfs_btree_cur		*cur,
2698	xfs_agblock_t			bno,
2699	xfs_extlen_t			len,
2700	const struct xfs_owner_info	*oinfo,
2701	bool				*has_rmap)
2702{
2703	uint64_t			owner;
2704	uint64_t			offset;
2705	unsigned int			flags;
2706	int				has_record;
2707	struct xfs_rmap_irec		irec;
2708	int				error;
2709
2710	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2711	ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2712	       (flags & XFS_RMAP_BMBT_BLOCK));
2713
2714	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &irec,
2715			&has_record);
2716	if (error)
2717		return error;
2718	if (!has_record) {
2719		*has_rmap = false;
2720		return 0;
2721	}
2722
 
 
 
 
 
 
 
 
2723	*has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2724		     irec.rm_startblock + irec.rm_blockcount >= bno + len);
2725	return 0;
2726}
2727
2728struct xfs_rmap_key_state {
2729	uint64_t			owner;
2730	uint64_t			offset;
2731	unsigned int			flags;
2732};
2733
2734/* For each rmap given, figure out if it doesn't match the key we want. */
2735STATIC int
2736xfs_rmap_has_other_keys_helper(
2737	struct xfs_btree_cur		*cur,
2738	const struct xfs_rmap_irec	*rec,
2739	void				*priv)
2740{
2741	struct xfs_rmap_key_state	*rks = priv;
2742
2743	if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2744	    ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2745		return 0;
2746	return -ECANCELED;
2747}
2748
2749/*
2750 * Given an extent and some owner info, can we find records overlapping
2751 * the extent whose owner info does not match the given owner?
2752 */
2753int
2754xfs_rmap_has_other_keys(
2755	struct xfs_btree_cur		*cur,
2756	xfs_agblock_t			bno,
2757	xfs_extlen_t			len,
2758	const struct xfs_owner_info	*oinfo,
2759	bool				*has_rmap)
2760{
2761	struct xfs_rmap_irec		low = {0};
2762	struct xfs_rmap_irec		high;
2763	struct xfs_rmap_key_state	rks;
2764	int				error;
2765
2766	xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2767	*has_rmap = false;
2768
2769	low.rm_startblock = bno;
2770	memset(&high, 0xFF, sizeof(high));
2771	high.rm_startblock = bno + len - 1;
2772
2773	error = xfs_rmap_query_range(cur, &low, &high,
2774			xfs_rmap_has_other_keys_helper, &rks);
2775	if (error == -ECANCELED) {
2776		*has_rmap = true;
2777		return 0;
2778	}
2779
2780	return error;
2781}
2782
2783const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2784	.oi_owner = XFS_RMAP_OWN_NULL,
2785};
2786const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2787	.oi_owner = XFS_RMAP_OWN_UNKNOWN,
2788};
2789const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2790	.oi_owner = XFS_RMAP_OWN_FS,
2791};
2792const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2793	.oi_owner = XFS_RMAP_OWN_LOG,
2794};
2795const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2796	.oi_owner = XFS_RMAP_OWN_AG,
2797};
2798const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2799	.oi_owner = XFS_RMAP_OWN_INOBT,
2800};
2801const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2802	.oi_owner = XFS_RMAP_OWN_INODES,
2803};
2804const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2805	.oi_owner = XFS_RMAP_OWN_REFC,
2806};
2807const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2808	.oi_owner = XFS_RMAP_OWN_COW,
2809};
2810
2811int __init
2812xfs_rmap_intent_init_cache(void)
2813{
2814	xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
2815			sizeof(struct xfs_rmap_intent),
2816			0, 0, NULL);
2817
2818	return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
2819}
2820
2821void
2822xfs_rmap_intent_destroy_cache(void)
2823{
2824	kmem_cache_destroy(xfs_rmap_intent_cache);
2825	xfs_rmap_intent_cache = NULL;
2826}
v5.9
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2014 Red Hat, Inc.
   4 * All Rights Reserved.
   5 */
   6#include "xfs.h"
   7#include "xfs_fs.h"
   8#include "xfs_shared.h"
   9#include "xfs_format.h"
  10#include "xfs_log_format.h"
  11#include "xfs_trans_resv.h"
  12#include "xfs_bit.h"
  13#include "xfs_mount.h"
 
  14#include "xfs_defer.h"
  15#include "xfs_btree.h"
  16#include "xfs_trans.h"
  17#include "xfs_alloc.h"
  18#include "xfs_rmap.h"
  19#include "xfs_rmap_btree.h"
  20#include "xfs_trace.h"
  21#include "xfs_errortag.h"
  22#include "xfs_error.h"
  23#include "xfs_inode.h"
 
 
 
  24
  25/*
  26 * Lookup the first record less than or equal to [bno, len, owner, offset]
  27 * in the btree given by cur.
  28 */
  29int
  30xfs_rmap_lookup_le(
  31	struct xfs_btree_cur	*cur,
  32	xfs_agblock_t		bno,
  33	xfs_extlen_t		len,
  34	uint64_t		owner,
  35	uint64_t		offset,
  36	unsigned int		flags,
 
  37	int			*stat)
  38{
 
 
 
  39	cur->bc_rec.r.rm_startblock = bno;
  40	cur->bc_rec.r.rm_blockcount = len;
  41	cur->bc_rec.r.rm_owner = owner;
  42	cur->bc_rec.r.rm_offset = offset;
  43	cur->bc_rec.r.rm_flags = flags;
  44	return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
 
 
 
 
 
 
 
 
 
 
 
  45}
  46
  47/*
  48 * Lookup the record exactly matching [bno, len, owner, offset]
  49 * in the btree given by cur.
  50 */
  51int
  52xfs_rmap_lookup_eq(
  53	struct xfs_btree_cur	*cur,
  54	xfs_agblock_t		bno,
  55	xfs_extlen_t		len,
  56	uint64_t		owner,
  57	uint64_t		offset,
  58	unsigned int		flags,
  59	int			*stat)
  60{
  61	cur->bc_rec.r.rm_startblock = bno;
  62	cur->bc_rec.r.rm_blockcount = len;
  63	cur->bc_rec.r.rm_owner = owner;
  64	cur->bc_rec.r.rm_offset = offset;
  65	cur->bc_rec.r.rm_flags = flags;
  66	return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
  67}
  68
  69/*
  70 * Update the record referred to by cur to the value given
  71 * by [bno, len, owner, offset].
  72 * This either works (return 0) or gets an EFSCORRUPTED error.
  73 */
  74STATIC int
  75xfs_rmap_update(
  76	struct xfs_btree_cur	*cur,
  77	struct xfs_rmap_irec	*irec)
  78{
  79	union xfs_btree_rec	rec;
  80	int			error;
  81
  82	trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.agno,
  83			irec->rm_startblock, irec->rm_blockcount,
  84			irec->rm_owner, irec->rm_offset, irec->rm_flags);
  85
  86	rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
  87	rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
  88	rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
  89	rec.rmap.rm_offset = cpu_to_be64(
  90			xfs_rmap_irec_offset_pack(irec));
  91	error = xfs_btree_update(cur, &rec);
  92	if (error)
  93		trace_xfs_rmap_update_error(cur->bc_mp,
  94				cur->bc_ag.agno, error, _RET_IP_);
  95	return error;
  96}
  97
  98int
  99xfs_rmap_insert(
 100	struct xfs_btree_cur	*rcur,
 101	xfs_agblock_t		agbno,
 102	xfs_extlen_t		len,
 103	uint64_t		owner,
 104	uint64_t		offset,
 105	unsigned int		flags)
 106{
 107	int			i;
 108	int			error;
 109
 110	trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.agno, agbno,
 111			len, owner, offset, flags);
 112
 113	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
 114	if (error)
 115		goto done;
 116	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
 117		error = -EFSCORRUPTED;
 118		goto done;
 119	}
 120
 121	rcur->bc_rec.r.rm_startblock = agbno;
 122	rcur->bc_rec.r.rm_blockcount = len;
 123	rcur->bc_rec.r.rm_owner = owner;
 124	rcur->bc_rec.r.rm_offset = offset;
 125	rcur->bc_rec.r.rm_flags = flags;
 126	error = xfs_btree_insert(rcur, &i);
 127	if (error)
 128		goto done;
 129	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 130		error = -EFSCORRUPTED;
 131		goto done;
 132	}
 133done:
 134	if (error)
 135		trace_xfs_rmap_insert_error(rcur->bc_mp,
 136				rcur->bc_ag.agno, error, _RET_IP_);
 137	return error;
 138}
 139
 140STATIC int
 141xfs_rmap_delete(
 142	struct xfs_btree_cur	*rcur,
 143	xfs_agblock_t		agbno,
 144	xfs_extlen_t		len,
 145	uint64_t		owner,
 146	uint64_t		offset,
 147	unsigned int		flags)
 148{
 149	int			i;
 150	int			error;
 151
 152	trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.agno, agbno,
 153			len, owner, offset, flags);
 154
 155	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
 156	if (error)
 157		goto done;
 158	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 159		error = -EFSCORRUPTED;
 160		goto done;
 161	}
 162
 163	error = xfs_btree_delete(rcur, &i);
 164	if (error)
 165		goto done;
 166	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 167		error = -EFSCORRUPTED;
 168		goto done;
 169	}
 170done:
 171	if (error)
 172		trace_xfs_rmap_delete_error(rcur->bc_mp,
 173				rcur->bc_ag.agno, error, _RET_IP_);
 174	return error;
 175}
 176
 177/* Convert an internal btree record to an rmap record. */
 178int
 179xfs_rmap_btrec_to_irec(
 180	union xfs_btree_rec	*rec,
 181	struct xfs_rmap_irec	*irec)
 182{
 183	irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
 184	irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
 185	irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
 186	return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
 187			irec);
 188}
 189
 190/*
 191 * Get the data from the pointed-to record.
 192 */
 193int
 194xfs_rmap_get_rec(
 195	struct xfs_btree_cur	*cur,
 196	struct xfs_rmap_irec	*irec,
 197	int			*stat)
 198{
 199	struct xfs_mount	*mp = cur->bc_mp;
 200	xfs_agnumber_t		agno = cur->bc_ag.agno;
 201	union xfs_btree_rec	*rec;
 202	int			error;
 203
 204	error = xfs_btree_get_rec(cur, &rec, stat);
 205	if (error || !*stat)
 206		return error;
 207
 208	if (xfs_rmap_btrec_to_irec(rec, irec))
 209		goto out_bad_rec;
 210
 211	if (irec->rm_blockcount == 0)
 212		goto out_bad_rec;
 213	if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
 214		if (irec->rm_owner != XFS_RMAP_OWN_FS)
 215			goto out_bad_rec;
 216		if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
 217			goto out_bad_rec;
 218	} else {
 219		/* check for valid extent range, including overflow */
 220		if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
 221			goto out_bad_rec;
 222		if (irec->rm_startblock >
 223				irec->rm_startblock + irec->rm_blockcount)
 224			goto out_bad_rec;
 225		if (!xfs_verify_agbno(mp, agno,
 226				irec->rm_startblock + irec->rm_blockcount - 1))
 227			goto out_bad_rec;
 228	}
 229
 230	if (!(xfs_verify_ino(mp, irec->rm_owner) ||
 231	      (irec->rm_owner <= XFS_RMAP_OWN_FS &&
 232	       irec->rm_owner >= XFS_RMAP_OWN_MIN)))
 233		goto out_bad_rec;
 234
 235	return 0;
 236out_bad_rec:
 237	xfs_warn(mp,
 238		"Reverse Mapping BTree record corruption in AG %d detected!",
 239		agno);
 240	xfs_warn(mp,
 241		"Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
 242		irec->rm_owner, irec->rm_flags, irec->rm_startblock,
 243		irec->rm_blockcount);
 244	return -EFSCORRUPTED;
 245}
 246
 247struct xfs_find_left_neighbor_info {
 248	struct xfs_rmap_irec	high;
 249	struct xfs_rmap_irec	*irec;
 250	int			*stat;
 251};
 252
 253/* For each rmap given, figure out if it matches the key we want. */
 254STATIC int
 255xfs_rmap_find_left_neighbor_helper(
 256	struct xfs_btree_cur	*cur,
 257	struct xfs_rmap_irec	*rec,
 258	void			*priv)
 259{
 260	struct xfs_find_left_neighbor_info	*info = priv;
 261
 262	trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
 263			cur->bc_ag.agno, rec->rm_startblock,
 264			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 265			rec->rm_flags);
 266
 267	if (rec->rm_owner != info->high.rm_owner)
 268		return 0;
 269	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
 270	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
 271	    rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
 272		return 0;
 273
 274	*info->irec = *rec;
 275	*info->stat = 1;
 276	return -ECANCELED;
 277}
 278
 279/*
 280 * Find the record to the left of the given extent, being careful only to
 281 * return a match with the same owner and adjacent physical and logical
 282 * block ranges.
 283 */
 284int
 285xfs_rmap_find_left_neighbor(
 286	struct xfs_btree_cur	*cur,
 287	xfs_agblock_t		bno,
 288	uint64_t		owner,
 289	uint64_t		offset,
 290	unsigned int		flags,
 291	struct xfs_rmap_irec	*irec,
 292	int			*stat)
 293{
 294	struct xfs_find_left_neighbor_info	info;
 
 295	int			error;
 296
 297	*stat = 0;
 298	if (bno == 0)
 299		return 0;
 300	info.high.rm_startblock = bno - 1;
 301	info.high.rm_owner = owner;
 302	if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
 303	    !(flags & XFS_RMAP_BMBT_BLOCK)) {
 304		if (offset == 0)
 305			return 0;
 306		info.high.rm_offset = offset - 1;
 307	} else
 308		info.high.rm_offset = 0;
 309	info.high.rm_flags = flags;
 310	info.high.rm_blockcount = 0;
 311	info.irec = irec;
 312	info.stat = stat;
 313
 314	trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
 315			cur->bc_ag.agno, bno, 0, owner, offset, flags);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 316
 317	error = xfs_rmap_query_range(cur, &info.high, &info.high,
 318			xfs_rmap_find_left_neighbor_helper, &info);
 319	if (error == -ECANCELED)
 320		error = 0;
 321	if (*stat)
 322		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
 323				cur->bc_ag.agno, irec->rm_startblock,
 324				irec->rm_blockcount, irec->rm_owner,
 325				irec->rm_offset, irec->rm_flags);
 326	return error;
 327}
 328
 329/* For each rmap given, figure out if it matches the key we want. */
 330STATIC int
 331xfs_rmap_lookup_le_range_helper(
 332	struct xfs_btree_cur	*cur,
 333	struct xfs_rmap_irec	*rec,
 334	void			*priv)
 335{
 336	struct xfs_find_left_neighbor_info	*info = priv;
 337
 338	trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
 339			cur->bc_ag.agno, rec->rm_startblock,
 340			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 341			rec->rm_flags);
 342
 343	if (rec->rm_owner != info->high.rm_owner)
 344		return 0;
 345	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
 346	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
 347	    (rec->rm_offset > info->high.rm_offset ||
 348	     rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
 349		return 0;
 350
 351	*info->irec = *rec;
 352	*info->stat = 1;
 353	return -ECANCELED;
 354}
 355
 356/*
 357 * Find the record to the left of the given extent, being careful only to
 358 * return a match with the same owner and overlapping physical and logical
 359 * block ranges.  This is the overlapping-interval version of
 360 * xfs_rmap_lookup_le.
 361 */
 362int
 363xfs_rmap_lookup_le_range(
 364	struct xfs_btree_cur	*cur,
 365	xfs_agblock_t		bno,
 366	uint64_t		owner,
 367	uint64_t		offset,
 368	unsigned int		flags,
 369	struct xfs_rmap_irec	*irec,
 370	int			*stat)
 371{
 372	struct xfs_find_left_neighbor_info	info;
 
 373	int			error;
 374
 375	info.high.rm_startblock = bno;
 376	info.high.rm_owner = owner;
 377	if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
 378		info.high.rm_offset = offset;
 379	else
 380		info.high.rm_offset = 0;
 381	info.high.rm_flags = flags;
 382	info.high.rm_blockcount = 0;
 383	*stat = 0;
 384	info.irec = irec;
 385	info.stat = stat;
 386
 387	trace_xfs_rmap_lookup_le_range(cur->bc_mp,
 388			cur->bc_ag.agno, bno, 0, owner, offset, flags);
 389	error = xfs_rmap_query_range(cur, &info.high, &info.high,
 390			xfs_rmap_lookup_le_range_helper, &info);
 391	if (error == -ECANCELED)
 392		error = 0;
 393	if (*stat)
 394		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 395				cur->bc_ag.agno, irec->rm_startblock,
 396				irec->rm_blockcount, irec->rm_owner,
 397				irec->rm_offset, irec->rm_flags);
 398	return error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 399}
 400
 401/*
 402 * Perform all the relevant owner checks for a removal op.  If we're doing an
 403 * unknown-owner removal then we have no owner information to check.
 404 */
 405static int
 406xfs_rmap_free_check_owner(
 407	struct xfs_mount	*mp,
 408	uint64_t		ltoff,
 409	struct xfs_rmap_irec	*rec,
 410	xfs_filblks_t		len,
 411	uint64_t		owner,
 412	uint64_t		offset,
 413	unsigned int		flags)
 414{
 415	int			error = 0;
 416
 417	if (owner == XFS_RMAP_OWN_UNKNOWN)
 418		return 0;
 419
 420	/* Make sure the unwritten flag matches. */
 421	if (XFS_IS_CORRUPT(mp,
 422			   (flags & XFS_RMAP_UNWRITTEN) !=
 423			   (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
 424		error = -EFSCORRUPTED;
 425		goto out;
 426	}
 427
 428	/* Make sure the owner matches what we expect to find in the tree. */
 429	if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
 430		error = -EFSCORRUPTED;
 431		goto out;
 432	}
 433
 434	/* Check the offset, if necessary. */
 435	if (XFS_RMAP_NON_INODE_OWNER(owner))
 436		goto out;
 437
 438	if (flags & XFS_RMAP_BMBT_BLOCK) {
 439		if (XFS_IS_CORRUPT(mp,
 440				   !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
 441			error = -EFSCORRUPTED;
 442			goto out;
 443		}
 444	} else {
 445		if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
 446			error = -EFSCORRUPTED;
 447			goto out;
 448		}
 449		if (XFS_IS_CORRUPT(mp,
 450				   offset + len > ltoff + rec->rm_blockcount)) {
 451			error = -EFSCORRUPTED;
 452			goto out;
 453		}
 454	}
 455
 456out:
 457	return error;
 458}
 459
 460/*
 461 * Find the extent in the rmap btree and remove it.
 462 *
 463 * The record we find should always be an exact match for the extent that we're
 464 * looking for, since we insert them into the btree without modification.
 465 *
 466 * Special Case #1: when growing the filesystem, we "free" an extent when
 467 * growing the last AG. This extent is new space and so it is not tracked as
 468 * used space in the btree. The growfs code will pass in an owner of
 469 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
 470 * extent. We verify that - the extent lookup result in a record that does not
 471 * overlap.
 472 *
 473 * Special Case #2: EFIs do not record the owner of the extent, so when
 474 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
 475 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
 476 * corruption checks during log recovery.
 477 */
 478STATIC int
 479xfs_rmap_unmap(
 480	struct xfs_btree_cur		*cur,
 481	xfs_agblock_t			bno,
 482	xfs_extlen_t			len,
 483	bool				unwritten,
 484	const struct xfs_owner_info	*oinfo)
 485{
 486	struct xfs_mount		*mp = cur->bc_mp;
 487	struct xfs_rmap_irec		ltrec;
 488	uint64_t			ltoff;
 489	int				error = 0;
 490	int				i;
 491	uint64_t			owner;
 492	uint64_t			offset;
 493	unsigned int			flags;
 494	bool				ignore_off;
 495
 496	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 497	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
 498			(flags & XFS_RMAP_BMBT_BLOCK);
 499	if (unwritten)
 500		flags |= XFS_RMAP_UNWRITTEN;
 501	trace_xfs_rmap_unmap(mp, cur->bc_ag.agno, bno, len,
 502			unwritten, oinfo);
 503
 504	/*
 505	 * We should always have a left record because there's a static record
 506	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
 507	 * will not ever be removed from the tree.
 508	 */
 509	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
 510	if (error)
 511		goto out_error;
 512	if (XFS_IS_CORRUPT(mp, i != 1)) {
 513		error = -EFSCORRUPTED;
 514		goto out_error;
 515	}
 516
 517	error = xfs_rmap_get_rec(cur, &ltrec, &i);
 518	if (error)
 519		goto out_error;
 520	if (XFS_IS_CORRUPT(mp, i != 1)) {
 521		error = -EFSCORRUPTED;
 522		goto out_error;
 523	}
 524	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 525			cur->bc_ag.agno, ltrec.rm_startblock,
 526			ltrec.rm_blockcount, ltrec.rm_owner,
 527			ltrec.rm_offset, ltrec.rm_flags);
 528	ltoff = ltrec.rm_offset;
 529
 530	/*
 531	 * For growfs, the incoming extent must be beyond the left record we
 532	 * just found as it is new space and won't be used by anyone. This is
 533	 * just a corruption check as we don't actually do anything with this
 534	 * extent.  Note that we need to use >= instead of > because it might
 535	 * be the case that the "left" extent goes all the way to EOFS.
 536	 */
 537	if (owner == XFS_RMAP_OWN_NULL) {
 538		if (XFS_IS_CORRUPT(mp,
 539				   bno <
 540				   ltrec.rm_startblock + ltrec.rm_blockcount)) {
 541			error = -EFSCORRUPTED;
 542			goto out_error;
 543		}
 544		goto out_done;
 545	}
 546
 547	/*
 548	 * If we're doing an unknown-owner removal for EFI recovery, we expect
 549	 * to find the full range in the rmapbt or nothing at all.  If we
 550	 * don't find any rmaps overlapping either end of the range, we're
 551	 * done.  Hopefully this means that the EFI creator already queued
 552	 * (and finished) a RUI to remove the rmap.
 553	 */
 554	if (owner == XFS_RMAP_OWN_UNKNOWN &&
 555	    ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
 556		struct xfs_rmap_irec    rtrec;
 557
 558		error = xfs_btree_increment(cur, 0, &i);
 559		if (error)
 560			goto out_error;
 561		if (i == 0)
 562			goto out_done;
 563		error = xfs_rmap_get_rec(cur, &rtrec, &i);
 564		if (error)
 565			goto out_error;
 566		if (XFS_IS_CORRUPT(mp, i != 1)) {
 567			error = -EFSCORRUPTED;
 568			goto out_error;
 569		}
 570		if (rtrec.rm_startblock >= bno + len)
 571			goto out_done;
 572	}
 573
 574	/* Make sure the extent we found covers the entire freeing range. */
 575	if (XFS_IS_CORRUPT(mp,
 576			   ltrec.rm_startblock > bno ||
 577			   ltrec.rm_startblock + ltrec.rm_blockcount <
 578			   bno + len)) {
 579		error = -EFSCORRUPTED;
 580		goto out_error;
 581	}
 582
 583	/* Check owner information. */
 584	error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, len, owner,
 585			offset, flags);
 586	if (error)
 587		goto out_error;
 588
 589	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
 590		/* exact match, simply remove the record from rmap tree */
 591		trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
 592				ltrec.rm_startblock, ltrec.rm_blockcount,
 593				ltrec.rm_owner, ltrec.rm_offset,
 594				ltrec.rm_flags);
 595		error = xfs_btree_delete(cur, &i);
 596		if (error)
 597			goto out_error;
 598		if (XFS_IS_CORRUPT(mp, i != 1)) {
 599			error = -EFSCORRUPTED;
 600			goto out_error;
 601		}
 602	} else if (ltrec.rm_startblock == bno) {
 603		/*
 604		 * overlap left hand side of extent: move the start, trim the
 605		 * length and update the current record.
 606		 *
 607		 *       ltbno                ltlen
 608		 * Orig:    |oooooooooooooooooooo|
 609		 * Freeing: |fffffffff|
 610		 * Result:            |rrrrrrrrrr|
 611		 *         bno       len
 612		 */
 613		ltrec.rm_startblock += len;
 614		ltrec.rm_blockcount -= len;
 615		if (!ignore_off)
 616			ltrec.rm_offset += len;
 617		error = xfs_rmap_update(cur, &ltrec);
 618		if (error)
 619			goto out_error;
 620	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
 621		/*
 622		 * overlap right hand side of extent: trim the length and update
 623		 * the current record.
 624		 *
 625		 *       ltbno                ltlen
 626		 * Orig:    |oooooooooooooooooooo|
 627		 * Freeing:            |fffffffff|
 628		 * Result:  |rrrrrrrrrr|
 629		 *                    bno       len
 630		 */
 631		ltrec.rm_blockcount -= len;
 632		error = xfs_rmap_update(cur, &ltrec);
 633		if (error)
 634			goto out_error;
 635	} else {
 636
 637		/*
 638		 * overlap middle of extent: trim the length of the existing
 639		 * record to the length of the new left-extent size, increment
 640		 * the insertion position so we can insert a new record
 641		 * containing the remaining right-extent space.
 642		 *
 643		 *       ltbno                ltlen
 644		 * Orig:    |oooooooooooooooooooo|
 645		 * Freeing:       |fffffffff|
 646		 * Result:  |rrrrr|         |rrrr|
 647		 *               bno       len
 648		 */
 649		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
 650
 651		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
 652		error = xfs_rmap_update(cur, &ltrec);
 653		if (error)
 654			goto out_error;
 655
 656		error = xfs_btree_increment(cur, 0, &i);
 657		if (error)
 658			goto out_error;
 659
 660		cur->bc_rec.r.rm_startblock = bno + len;
 661		cur->bc_rec.r.rm_blockcount = orig_len - len -
 662						     ltrec.rm_blockcount;
 663		cur->bc_rec.r.rm_owner = ltrec.rm_owner;
 664		if (ignore_off)
 665			cur->bc_rec.r.rm_offset = 0;
 666		else
 667			cur->bc_rec.r.rm_offset = offset + len;
 668		cur->bc_rec.r.rm_flags = flags;
 669		trace_xfs_rmap_insert(mp, cur->bc_ag.agno,
 670				cur->bc_rec.r.rm_startblock,
 671				cur->bc_rec.r.rm_blockcount,
 672				cur->bc_rec.r.rm_owner,
 673				cur->bc_rec.r.rm_offset,
 674				cur->bc_rec.r.rm_flags);
 675		error = xfs_btree_insert(cur, &i);
 676		if (error)
 677			goto out_error;
 678	}
 679
 680out_done:
 681	trace_xfs_rmap_unmap_done(mp, cur->bc_ag.agno, bno, len,
 682			unwritten, oinfo);
 683out_error:
 684	if (error)
 685		trace_xfs_rmap_unmap_error(mp, cur->bc_ag.agno,
 686				error, _RET_IP_);
 687	return error;
 688}
 689
 690/*
 691 * Remove a reference to an extent in the rmap btree.
 692 */
 693int
 694xfs_rmap_free(
 695	struct xfs_trans		*tp,
 696	struct xfs_buf			*agbp,
 697	xfs_agnumber_t			agno,
 698	xfs_agblock_t			bno,
 699	xfs_extlen_t			len,
 700	const struct xfs_owner_info	*oinfo)
 701{
 702	struct xfs_mount		*mp = tp->t_mountp;
 703	struct xfs_btree_cur		*cur;
 704	int				error;
 705
 706	if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
 707		return 0;
 708
 709	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
 710
 711	error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
 712
 713	xfs_btree_del_cursor(cur, error);
 714	return error;
 715}
 716
 717/*
 718 * A mergeable rmap must have the same owner and the same values for
 719 * the unwritten, attr_fork, and bmbt flags.  The startblock and
 720 * offset are checked separately.
 721 */
 722static bool
 723xfs_rmap_is_mergeable(
 724	struct xfs_rmap_irec	*irec,
 725	uint64_t		owner,
 726	unsigned int		flags)
 727{
 728	if (irec->rm_owner == XFS_RMAP_OWN_NULL)
 729		return false;
 730	if (irec->rm_owner != owner)
 731		return false;
 732	if ((flags & XFS_RMAP_UNWRITTEN) ^
 733	    (irec->rm_flags & XFS_RMAP_UNWRITTEN))
 734		return false;
 735	if ((flags & XFS_RMAP_ATTR_FORK) ^
 736	    (irec->rm_flags & XFS_RMAP_ATTR_FORK))
 737		return false;
 738	if ((flags & XFS_RMAP_BMBT_BLOCK) ^
 739	    (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
 740		return false;
 741	return true;
 742}
 743
 744/*
 745 * When we allocate a new block, the first thing we do is add a reference to
 746 * the extent in the rmap btree. This takes the form of a [agbno, length,
 747 * owner, offset] record.  Flags are encoded in the high bits of the offset
 748 * field.
 749 */
 750STATIC int
 751xfs_rmap_map(
 752	struct xfs_btree_cur		*cur,
 753	xfs_agblock_t			bno,
 754	xfs_extlen_t			len,
 755	bool				unwritten,
 756	const struct xfs_owner_info	*oinfo)
 757{
 758	struct xfs_mount		*mp = cur->bc_mp;
 759	struct xfs_rmap_irec		ltrec;
 760	struct xfs_rmap_irec		gtrec;
 761	int				have_gt;
 762	int				have_lt;
 763	int				error = 0;
 764	int				i;
 765	uint64_t			owner;
 766	uint64_t			offset;
 767	unsigned int			flags = 0;
 768	bool				ignore_off;
 769
 770	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 771	ASSERT(owner != 0);
 772	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
 773			(flags & XFS_RMAP_BMBT_BLOCK);
 774	if (unwritten)
 775		flags |= XFS_RMAP_UNWRITTEN;
 776	trace_xfs_rmap_map(mp, cur->bc_ag.agno, bno, len,
 777			unwritten, oinfo);
 778	ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
 779
 780	/*
 781	 * For the initial lookup, look for an exact match or the left-adjacent
 782	 * record for our insertion point. This will also give us the record for
 783	 * start block contiguity tests.
 784	 */
 785	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
 786			&have_lt);
 787	if (error)
 788		goto out_error;
 789	if (have_lt) {
 790		error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
 791		if (error)
 792			goto out_error;
 793		if (XFS_IS_CORRUPT(mp, have_lt != 1)) {
 794			error = -EFSCORRUPTED;
 795			goto out_error;
 796		}
 797		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 798				cur->bc_ag.agno, ltrec.rm_startblock,
 799				ltrec.rm_blockcount, ltrec.rm_owner,
 800				ltrec.rm_offset, ltrec.rm_flags);
 801
 802		if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
 803			have_lt = 0;
 804	}
 805
 806	if (XFS_IS_CORRUPT(mp,
 807			   have_lt != 0 &&
 808			   ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
 809		error = -EFSCORRUPTED;
 810		goto out_error;
 811	}
 812
 813	/*
 814	 * Increment the cursor to see if we have a right-adjacent record to our
 815	 * insertion point. This will give us the record for end block
 816	 * contiguity tests.
 817	 */
 818	error = xfs_btree_increment(cur, 0, &have_gt);
 819	if (error)
 820		goto out_error;
 821	if (have_gt) {
 822		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
 823		if (error)
 824			goto out_error;
 825		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
 826			error = -EFSCORRUPTED;
 827			goto out_error;
 828		}
 829		if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
 830			error = -EFSCORRUPTED;
 831			goto out_error;
 832		}
 833		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
 834			cur->bc_ag.agno, gtrec.rm_startblock,
 835			gtrec.rm_blockcount, gtrec.rm_owner,
 836			gtrec.rm_offset, gtrec.rm_flags);
 837		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
 838			have_gt = 0;
 839	}
 840
 841	/*
 842	 * Note: cursor currently points one record to the right of ltrec, even
 843	 * if there is no record in the tree to the right.
 844	 */
 845	if (have_lt &&
 846	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
 847	    (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
 848		/*
 849		 * left edge contiguous, merge into left record.
 850		 *
 851		 *       ltbno     ltlen
 852		 * orig:   |ooooooooo|
 853		 * adding:           |aaaaaaaaa|
 854		 * result: |rrrrrrrrrrrrrrrrrrr|
 855		 *                  bno       len
 856		 */
 857		ltrec.rm_blockcount += len;
 858		if (have_gt &&
 859		    bno + len == gtrec.rm_startblock &&
 860		    (ignore_off || offset + len == gtrec.rm_offset) &&
 861		    (unsigned long)ltrec.rm_blockcount + len +
 862				gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
 863			/*
 864			 * right edge also contiguous, delete right record
 865			 * and merge into left record.
 866			 *
 867			 *       ltbno     ltlen    gtbno     gtlen
 868			 * orig:   |ooooooooo|         |ooooooooo|
 869			 * adding:           |aaaaaaaaa|
 870			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
 871			 */
 872			ltrec.rm_blockcount += gtrec.rm_blockcount;
 873			trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
 874					gtrec.rm_startblock,
 875					gtrec.rm_blockcount,
 876					gtrec.rm_owner,
 877					gtrec.rm_offset,
 878					gtrec.rm_flags);
 879			error = xfs_btree_delete(cur, &i);
 880			if (error)
 881				goto out_error;
 882			if (XFS_IS_CORRUPT(mp, i != 1)) {
 883				error = -EFSCORRUPTED;
 884				goto out_error;
 885			}
 886		}
 887
 888		/* point the cursor back to the left record and update */
 889		error = xfs_btree_decrement(cur, 0, &have_gt);
 890		if (error)
 891			goto out_error;
 892		error = xfs_rmap_update(cur, &ltrec);
 893		if (error)
 894			goto out_error;
 895	} else if (have_gt &&
 896		   bno + len == gtrec.rm_startblock &&
 897		   (ignore_off || offset + len == gtrec.rm_offset)) {
 898		/*
 899		 * right edge contiguous, merge into right record.
 900		 *
 901		 *                 gtbno     gtlen
 902		 * Orig:             |ooooooooo|
 903		 * adding: |aaaaaaaaa|
 904		 * Result: |rrrrrrrrrrrrrrrrrrr|
 905		 *        bno       len
 906		 */
 907		gtrec.rm_startblock = bno;
 908		gtrec.rm_blockcount += len;
 909		if (!ignore_off)
 910			gtrec.rm_offset = offset;
 911		error = xfs_rmap_update(cur, &gtrec);
 912		if (error)
 913			goto out_error;
 914	} else {
 915		/*
 916		 * no contiguous edge with identical owner, insert
 917		 * new record at current cursor position.
 918		 */
 919		cur->bc_rec.r.rm_startblock = bno;
 920		cur->bc_rec.r.rm_blockcount = len;
 921		cur->bc_rec.r.rm_owner = owner;
 922		cur->bc_rec.r.rm_offset = offset;
 923		cur->bc_rec.r.rm_flags = flags;
 924		trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno, len,
 925			owner, offset, flags);
 926		error = xfs_btree_insert(cur, &i);
 927		if (error)
 928			goto out_error;
 929		if (XFS_IS_CORRUPT(mp, i != 1)) {
 930			error = -EFSCORRUPTED;
 931			goto out_error;
 932		}
 933	}
 934
 935	trace_xfs_rmap_map_done(mp, cur->bc_ag.agno, bno, len,
 936			unwritten, oinfo);
 937out_error:
 938	if (error)
 939		trace_xfs_rmap_map_error(mp, cur->bc_ag.agno,
 940				error, _RET_IP_);
 941	return error;
 942}
 943
 944/*
 945 * Add a reference to an extent in the rmap btree.
 946 */
 947int
 948xfs_rmap_alloc(
 949	struct xfs_trans		*tp,
 950	struct xfs_buf			*agbp,
 951	xfs_agnumber_t			agno,
 952	xfs_agblock_t			bno,
 953	xfs_extlen_t			len,
 954	const struct xfs_owner_info	*oinfo)
 955{
 956	struct xfs_mount		*mp = tp->t_mountp;
 957	struct xfs_btree_cur		*cur;
 958	int				error;
 959
 960	if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
 961		return 0;
 962
 963	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
 964	error = xfs_rmap_map(cur, bno, len, false, oinfo);
 965
 966	xfs_btree_del_cursor(cur, error);
 967	return error;
 968}
 969
 970#define RMAP_LEFT_CONTIG	(1 << 0)
 971#define RMAP_RIGHT_CONTIG	(1 << 1)
 972#define RMAP_LEFT_FILLING	(1 << 2)
 973#define RMAP_RIGHT_FILLING	(1 << 3)
 974#define RMAP_LEFT_VALID		(1 << 6)
 975#define RMAP_RIGHT_VALID	(1 << 7)
 976
 977#define LEFT		r[0]
 978#define RIGHT		r[1]
 979#define PREV		r[2]
 980#define NEW		r[3]
 981
 982/*
 983 * Convert an unwritten extent to a real extent or vice versa.
 984 * Does not handle overlapping extents.
 985 */
 986STATIC int
 987xfs_rmap_convert(
 988	struct xfs_btree_cur		*cur,
 989	xfs_agblock_t			bno,
 990	xfs_extlen_t			len,
 991	bool				unwritten,
 992	const struct xfs_owner_info	*oinfo)
 993{
 994	struct xfs_mount		*mp = cur->bc_mp;
 995	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
 996						/* left is 0, right is 1, */
 997						/* prev is 2, new is 3 */
 998	uint64_t		owner;
 999	uint64_t		offset;
1000	uint64_t		new_endoff;
1001	unsigned int		oldext;
1002	unsigned int		newext;
1003	unsigned int		flags = 0;
1004	int			i;
1005	int			state = 0;
1006	int			error;
1007
1008	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1009	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1010			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1011	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1012	new_endoff = offset + len;
1013	trace_xfs_rmap_convert(mp, cur->bc_ag.agno, bno, len,
1014			unwritten, oinfo);
1015
1016	/*
1017	 * For the initial lookup, look for an exact match or the left-adjacent
1018	 * record for our insertion point. This will also give us the record for
1019	 * start block contiguity tests.
1020	 */
1021	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1022	if (error)
1023		goto done;
1024	if (XFS_IS_CORRUPT(mp, i != 1)) {
1025		error = -EFSCORRUPTED;
1026		goto done;
1027	}
1028
1029	error = xfs_rmap_get_rec(cur, &PREV, &i);
1030	if (error)
1031		goto done;
1032	if (XFS_IS_CORRUPT(mp, i != 1)) {
1033		error = -EFSCORRUPTED;
1034		goto done;
1035	}
1036	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1037			cur->bc_ag.agno, PREV.rm_startblock,
1038			PREV.rm_blockcount, PREV.rm_owner,
1039			PREV.rm_offset, PREV.rm_flags);
1040
1041	ASSERT(PREV.rm_offset <= offset);
1042	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1043	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1044	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1045
1046	/*
1047	 * Set flags determining what part of the previous oldext allocation
1048	 * extent is being replaced by a newext allocation.
1049	 */
1050	if (PREV.rm_offset == offset)
1051		state |= RMAP_LEFT_FILLING;
1052	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1053		state |= RMAP_RIGHT_FILLING;
1054
1055	/*
1056	 * Decrement the cursor to see if we have a left-adjacent record to our
1057	 * insertion point. This will give us the record for end block
1058	 * contiguity tests.
1059	 */
1060	error = xfs_btree_decrement(cur, 0, &i);
1061	if (error)
1062		goto done;
1063	if (i) {
1064		state |= RMAP_LEFT_VALID;
1065		error = xfs_rmap_get_rec(cur, &LEFT, &i);
1066		if (error)
1067			goto done;
1068		if (XFS_IS_CORRUPT(mp, i != 1)) {
1069			error = -EFSCORRUPTED;
1070			goto done;
1071		}
1072		if (XFS_IS_CORRUPT(mp,
1073				   LEFT.rm_startblock + LEFT.rm_blockcount >
1074				   bno)) {
1075			error = -EFSCORRUPTED;
1076			goto done;
1077		}
1078		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1079				cur->bc_ag.agno, LEFT.rm_startblock,
1080				LEFT.rm_blockcount, LEFT.rm_owner,
1081				LEFT.rm_offset, LEFT.rm_flags);
1082		if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1083		    LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1084		    xfs_rmap_is_mergeable(&LEFT, owner, newext))
1085			state |= RMAP_LEFT_CONTIG;
1086	}
1087
1088	/*
1089	 * Increment the cursor to see if we have a right-adjacent record to our
1090	 * insertion point. This will give us the record for end block
1091	 * contiguity tests.
1092	 */
1093	error = xfs_btree_increment(cur, 0, &i);
1094	if (error)
1095		goto done;
1096	if (XFS_IS_CORRUPT(mp, i != 1)) {
1097		error = -EFSCORRUPTED;
1098		goto done;
1099	}
1100	error = xfs_btree_increment(cur, 0, &i);
1101	if (error)
1102		goto done;
1103	if (i) {
1104		state |= RMAP_RIGHT_VALID;
1105		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1106		if (error)
1107			goto done;
1108		if (XFS_IS_CORRUPT(mp, i != 1)) {
1109			error = -EFSCORRUPTED;
1110			goto done;
1111		}
1112		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1113			error = -EFSCORRUPTED;
1114			goto done;
1115		}
1116		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1117				cur->bc_ag.agno, RIGHT.rm_startblock,
1118				RIGHT.rm_blockcount, RIGHT.rm_owner,
1119				RIGHT.rm_offset, RIGHT.rm_flags);
1120		if (bno + len == RIGHT.rm_startblock &&
1121		    offset + len == RIGHT.rm_offset &&
1122		    xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1123			state |= RMAP_RIGHT_CONTIG;
1124	}
1125
1126	/* check that left + prev + right is not too long */
1127	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1128			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1129	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1130	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1131	    (unsigned long)LEFT.rm_blockcount + len +
1132	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1133		state &= ~RMAP_RIGHT_CONTIG;
1134
1135	trace_xfs_rmap_convert_state(mp, cur->bc_ag.agno, state,
1136			_RET_IP_);
1137
1138	/* reset the cursor back to PREV */
1139	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1140	if (error)
1141		goto done;
1142	if (XFS_IS_CORRUPT(mp, i != 1)) {
1143		error = -EFSCORRUPTED;
1144		goto done;
1145	}
1146
1147	/*
1148	 * Switch out based on the FILLING and CONTIG state bits.
1149	 */
1150	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1151			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1152	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1153	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1154		/*
1155		 * Setting all of a previous oldext extent to newext.
1156		 * The left and right neighbors are both contiguous with new.
1157		 */
1158		error = xfs_btree_increment(cur, 0, &i);
1159		if (error)
1160			goto done;
1161		if (XFS_IS_CORRUPT(mp, i != 1)) {
1162			error = -EFSCORRUPTED;
1163			goto done;
1164		}
1165		trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1166				RIGHT.rm_startblock, RIGHT.rm_blockcount,
1167				RIGHT.rm_owner, RIGHT.rm_offset,
1168				RIGHT.rm_flags);
1169		error = xfs_btree_delete(cur, &i);
1170		if (error)
1171			goto done;
1172		if (XFS_IS_CORRUPT(mp, i != 1)) {
1173			error = -EFSCORRUPTED;
1174			goto done;
1175		}
1176		error = xfs_btree_decrement(cur, 0, &i);
1177		if (error)
1178			goto done;
1179		if (XFS_IS_CORRUPT(mp, i != 1)) {
1180			error = -EFSCORRUPTED;
1181			goto done;
1182		}
1183		trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1184				PREV.rm_startblock, PREV.rm_blockcount,
1185				PREV.rm_owner, PREV.rm_offset,
1186				PREV.rm_flags);
1187		error = xfs_btree_delete(cur, &i);
1188		if (error)
1189			goto done;
1190		if (XFS_IS_CORRUPT(mp, i != 1)) {
1191			error = -EFSCORRUPTED;
1192			goto done;
1193		}
1194		error = xfs_btree_decrement(cur, 0, &i);
1195		if (error)
1196			goto done;
1197		if (XFS_IS_CORRUPT(mp, i != 1)) {
1198			error = -EFSCORRUPTED;
1199			goto done;
1200		}
1201		NEW = LEFT;
1202		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1203		error = xfs_rmap_update(cur, &NEW);
1204		if (error)
1205			goto done;
1206		break;
1207
1208	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1209		/*
1210		 * Setting all of a previous oldext extent to newext.
1211		 * The left neighbor is contiguous, the right is not.
1212		 */
1213		trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1214				PREV.rm_startblock, PREV.rm_blockcount,
1215				PREV.rm_owner, PREV.rm_offset,
1216				PREV.rm_flags);
1217		error = xfs_btree_delete(cur, &i);
1218		if (error)
1219			goto done;
1220		if (XFS_IS_CORRUPT(mp, i != 1)) {
1221			error = -EFSCORRUPTED;
1222			goto done;
1223		}
1224		error = xfs_btree_decrement(cur, 0, &i);
1225		if (error)
1226			goto done;
1227		if (XFS_IS_CORRUPT(mp, i != 1)) {
1228			error = -EFSCORRUPTED;
1229			goto done;
1230		}
1231		NEW = LEFT;
1232		NEW.rm_blockcount += PREV.rm_blockcount;
1233		error = xfs_rmap_update(cur, &NEW);
1234		if (error)
1235			goto done;
1236		break;
1237
1238	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1239		/*
1240		 * Setting all of a previous oldext extent to newext.
1241		 * The right neighbor is contiguous, the left is not.
1242		 */
1243		error = xfs_btree_increment(cur, 0, &i);
1244		if (error)
1245			goto done;
1246		if (XFS_IS_CORRUPT(mp, i != 1)) {
1247			error = -EFSCORRUPTED;
1248			goto done;
1249		}
1250		trace_xfs_rmap_delete(mp, cur->bc_ag.agno,
1251				RIGHT.rm_startblock, RIGHT.rm_blockcount,
1252				RIGHT.rm_owner, RIGHT.rm_offset,
1253				RIGHT.rm_flags);
1254		error = xfs_btree_delete(cur, &i);
1255		if (error)
1256			goto done;
1257		if (XFS_IS_CORRUPT(mp, i != 1)) {
1258			error = -EFSCORRUPTED;
1259			goto done;
1260		}
1261		error = xfs_btree_decrement(cur, 0, &i);
1262		if (error)
1263			goto done;
1264		if (XFS_IS_CORRUPT(mp, i != 1)) {
1265			error = -EFSCORRUPTED;
1266			goto done;
1267		}
1268		NEW = PREV;
1269		NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1270		NEW.rm_flags = newext;
1271		error = xfs_rmap_update(cur, &NEW);
1272		if (error)
1273			goto done;
1274		break;
1275
1276	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1277		/*
1278		 * Setting all of a previous oldext extent to newext.
1279		 * Neither the left nor right neighbors are contiguous with
1280		 * the new one.
1281		 */
1282		NEW = PREV;
1283		NEW.rm_flags = newext;
1284		error = xfs_rmap_update(cur, &NEW);
1285		if (error)
1286			goto done;
1287		break;
1288
1289	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1290		/*
1291		 * Setting the first part of a previous oldext extent to newext.
1292		 * The left neighbor is contiguous.
1293		 */
1294		NEW = PREV;
1295		NEW.rm_offset += len;
1296		NEW.rm_startblock += len;
1297		NEW.rm_blockcount -= len;
1298		error = xfs_rmap_update(cur, &NEW);
1299		if (error)
1300			goto done;
1301		error = xfs_btree_decrement(cur, 0, &i);
1302		if (error)
1303			goto done;
1304		NEW = LEFT;
1305		NEW.rm_blockcount += len;
1306		error = xfs_rmap_update(cur, &NEW);
1307		if (error)
1308			goto done;
1309		break;
1310
1311	case RMAP_LEFT_FILLING:
1312		/*
1313		 * Setting the first part of a previous oldext extent to newext.
1314		 * The left neighbor is not contiguous.
1315		 */
1316		NEW = PREV;
1317		NEW.rm_startblock += len;
1318		NEW.rm_offset += len;
1319		NEW.rm_blockcount -= len;
1320		error = xfs_rmap_update(cur, &NEW);
1321		if (error)
1322			goto done;
1323		NEW.rm_startblock = bno;
1324		NEW.rm_owner = owner;
1325		NEW.rm_offset = offset;
1326		NEW.rm_blockcount = len;
1327		NEW.rm_flags = newext;
1328		cur->bc_rec.r = NEW;
1329		trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno,
1330				len, owner, offset, newext);
1331		error = xfs_btree_insert(cur, &i);
1332		if (error)
1333			goto done;
1334		if (XFS_IS_CORRUPT(mp, i != 1)) {
1335			error = -EFSCORRUPTED;
1336			goto done;
1337		}
1338		break;
1339
1340	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1341		/*
1342		 * Setting the last part of a previous oldext extent to newext.
1343		 * The right neighbor is contiguous with the new allocation.
1344		 */
1345		NEW = PREV;
1346		NEW.rm_blockcount -= len;
1347		error = xfs_rmap_update(cur, &NEW);
1348		if (error)
1349			goto done;
1350		error = xfs_btree_increment(cur, 0, &i);
1351		if (error)
1352			goto done;
1353		NEW = RIGHT;
1354		NEW.rm_offset = offset;
1355		NEW.rm_startblock = bno;
1356		NEW.rm_blockcount += len;
1357		error = xfs_rmap_update(cur, &NEW);
1358		if (error)
1359			goto done;
1360		break;
1361
1362	case RMAP_RIGHT_FILLING:
1363		/*
1364		 * Setting the last part of a previous oldext extent to newext.
1365		 * The right neighbor is not contiguous.
1366		 */
1367		NEW = PREV;
1368		NEW.rm_blockcount -= len;
1369		error = xfs_rmap_update(cur, &NEW);
1370		if (error)
1371			goto done;
1372		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1373				oldext, &i);
1374		if (error)
1375			goto done;
1376		if (XFS_IS_CORRUPT(mp, i != 0)) {
1377			error = -EFSCORRUPTED;
1378			goto done;
1379		}
1380		NEW.rm_startblock = bno;
1381		NEW.rm_owner = owner;
1382		NEW.rm_offset = offset;
1383		NEW.rm_blockcount = len;
1384		NEW.rm_flags = newext;
1385		cur->bc_rec.r = NEW;
1386		trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno,
1387				len, owner, offset, newext);
1388		error = xfs_btree_insert(cur, &i);
1389		if (error)
1390			goto done;
1391		if (XFS_IS_CORRUPT(mp, i != 1)) {
1392			error = -EFSCORRUPTED;
1393			goto done;
1394		}
1395		break;
1396
1397	case 0:
1398		/*
1399		 * Setting the middle part of a previous oldext extent to
1400		 * newext.  Contiguity is impossible here.
1401		 * One extent becomes three extents.
1402		 */
1403		/* new right extent - oldext */
1404		NEW.rm_startblock = bno + len;
1405		NEW.rm_owner = owner;
1406		NEW.rm_offset = new_endoff;
1407		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1408				new_endoff;
1409		NEW.rm_flags = PREV.rm_flags;
1410		error = xfs_rmap_update(cur, &NEW);
1411		if (error)
1412			goto done;
1413		/* new left extent - oldext */
1414		NEW = PREV;
1415		NEW.rm_blockcount = offset - PREV.rm_offset;
1416		cur->bc_rec.r = NEW;
1417		trace_xfs_rmap_insert(mp, cur->bc_ag.agno,
1418				NEW.rm_startblock, NEW.rm_blockcount,
1419				NEW.rm_owner, NEW.rm_offset,
1420				NEW.rm_flags);
1421		error = xfs_btree_insert(cur, &i);
1422		if (error)
1423			goto done;
1424		if (XFS_IS_CORRUPT(mp, i != 1)) {
1425			error = -EFSCORRUPTED;
1426			goto done;
1427		}
1428		/*
1429		 * Reset the cursor to the position of the new extent
1430		 * we are about to insert as we can't trust it after
1431		 * the previous insert.
1432		 */
1433		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1434				oldext, &i);
1435		if (error)
1436			goto done;
1437		if (XFS_IS_CORRUPT(mp, i != 0)) {
1438			error = -EFSCORRUPTED;
1439			goto done;
1440		}
1441		/* new middle extent - newext */
1442		cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1443		cur->bc_rec.r.rm_flags |= newext;
1444		trace_xfs_rmap_insert(mp, cur->bc_ag.agno, bno, len,
1445				owner, offset, newext);
1446		error = xfs_btree_insert(cur, &i);
1447		if (error)
1448			goto done;
1449		if (XFS_IS_CORRUPT(mp, i != 1)) {
1450			error = -EFSCORRUPTED;
1451			goto done;
1452		}
1453		break;
1454
1455	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1456	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1457	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1458	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1459	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1460	case RMAP_LEFT_CONTIG:
1461	case RMAP_RIGHT_CONTIG:
1462		/*
1463		 * These cases are all impossible.
1464		 */
1465		ASSERT(0);
1466	}
1467
1468	trace_xfs_rmap_convert_done(mp, cur->bc_ag.agno, bno, len,
1469			unwritten, oinfo);
1470done:
1471	if (error)
1472		trace_xfs_rmap_convert_error(cur->bc_mp,
1473				cur->bc_ag.agno, error, _RET_IP_);
1474	return error;
1475}
1476
1477/*
1478 * Convert an unwritten extent to a real extent or vice versa.  If there is no
1479 * possibility of overlapping extents, delegate to the simpler convert
1480 * function.
1481 */
1482STATIC int
1483xfs_rmap_convert_shared(
1484	struct xfs_btree_cur		*cur,
1485	xfs_agblock_t			bno,
1486	xfs_extlen_t			len,
1487	bool				unwritten,
1488	const struct xfs_owner_info	*oinfo)
1489{
1490	struct xfs_mount		*mp = cur->bc_mp;
1491	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
1492						/* left is 0, right is 1, */
1493						/* prev is 2, new is 3 */
1494	uint64_t		owner;
1495	uint64_t		offset;
1496	uint64_t		new_endoff;
1497	unsigned int		oldext;
1498	unsigned int		newext;
1499	unsigned int		flags = 0;
1500	int			i;
1501	int			state = 0;
1502	int			error;
1503
1504	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1505	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1506			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1507	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1508	new_endoff = offset + len;
1509	trace_xfs_rmap_convert(mp, cur->bc_ag.agno, bno, len,
1510			unwritten, oinfo);
1511
1512	/*
1513	 * For the initial lookup, look for and exact match or the left-adjacent
1514	 * record for our insertion point. This will also give us the record for
1515	 * start block contiguity tests.
1516	 */
1517	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1518			&PREV, &i);
1519	if (error)
1520		goto done;
1521	if (XFS_IS_CORRUPT(mp, i != 1)) {
1522		error = -EFSCORRUPTED;
1523		goto done;
1524	}
1525
1526	ASSERT(PREV.rm_offset <= offset);
1527	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1528	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1529	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1530
1531	/*
1532	 * Set flags determining what part of the previous oldext allocation
1533	 * extent is being replaced by a newext allocation.
1534	 */
1535	if (PREV.rm_offset == offset)
1536		state |= RMAP_LEFT_FILLING;
1537	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1538		state |= RMAP_RIGHT_FILLING;
1539
1540	/* Is there a left record that abuts our range? */
1541	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1542			&LEFT, &i);
1543	if (error)
1544		goto done;
1545	if (i) {
1546		state |= RMAP_LEFT_VALID;
1547		if (XFS_IS_CORRUPT(mp,
1548				   LEFT.rm_startblock + LEFT.rm_blockcount >
1549				   bno)) {
1550			error = -EFSCORRUPTED;
1551			goto done;
1552		}
1553		if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1554			state |= RMAP_LEFT_CONTIG;
1555	}
1556
1557	/* Is there a right record that abuts our range? */
1558	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1559			newext, &i);
1560	if (error)
1561		goto done;
1562	if (i) {
1563		state |= RMAP_RIGHT_VALID;
1564		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1565		if (error)
1566			goto done;
1567		if (XFS_IS_CORRUPT(mp, i != 1)) {
1568			error = -EFSCORRUPTED;
1569			goto done;
1570		}
1571		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1572			error = -EFSCORRUPTED;
1573			goto done;
1574		}
1575		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1576				cur->bc_ag.agno, RIGHT.rm_startblock,
1577				RIGHT.rm_blockcount, RIGHT.rm_owner,
1578				RIGHT.rm_offset, RIGHT.rm_flags);
1579		if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1580			state |= RMAP_RIGHT_CONTIG;
1581	}
1582
1583	/* check that left + prev + right is not too long */
1584	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1585			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1586	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1587	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1588	    (unsigned long)LEFT.rm_blockcount + len +
1589	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1590		state &= ~RMAP_RIGHT_CONTIG;
1591
1592	trace_xfs_rmap_convert_state(mp, cur->bc_ag.agno, state,
1593			_RET_IP_);
1594	/*
1595	 * Switch out based on the FILLING and CONTIG state bits.
1596	 */
1597	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1598			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1599	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1600	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1601		/*
1602		 * Setting all of a previous oldext extent to newext.
1603		 * The left and right neighbors are both contiguous with new.
1604		 */
1605		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1606				RIGHT.rm_blockcount, RIGHT.rm_owner,
1607				RIGHT.rm_offset, RIGHT.rm_flags);
1608		if (error)
1609			goto done;
1610		error = xfs_rmap_delete(cur, PREV.rm_startblock,
1611				PREV.rm_blockcount, PREV.rm_owner,
1612				PREV.rm_offset, PREV.rm_flags);
1613		if (error)
1614			goto done;
1615		NEW = LEFT;
1616		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1617				NEW.rm_blockcount, NEW.rm_owner,
1618				NEW.rm_offset, NEW.rm_flags, &i);
1619		if (error)
1620			goto done;
1621		if (XFS_IS_CORRUPT(mp, i != 1)) {
1622			error = -EFSCORRUPTED;
1623			goto done;
1624		}
1625		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1626		error = xfs_rmap_update(cur, &NEW);
1627		if (error)
1628			goto done;
1629		break;
1630
1631	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1632		/*
1633		 * Setting all of a previous oldext extent to newext.
1634		 * The left neighbor is contiguous, the right is not.
1635		 */
1636		error = xfs_rmap_delete(cur, PREV.rm_startblock,
1637				PREV.rm_blockcount, PREV.rm_owner,
1638				PREV.rm_offset, PREV.rm_flags);
1639		if (error)
1640			goto done;
1641		NEW = LEFT;
1642		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1643				NEW.rm_blockcount, NEW.rm_owner,
1644				NEW.rm_offset, NEW.rm_flags, &i);
1645		if (error)
1646			goto done;
1647		if (XFS_IS_CORRUPT(mp, i != 1)) {
1648			error = -EFSCORRUPTED;
1649			goto done;
1650		}
1651		NEW.rm_blockcount += PREV.rm_blockcount;
1652		error = xfs_rmap_update(cur, &NEW);
1653		if (error)
1654			goto done;
1655		break;
1656
1657	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1658		/*
1659		 * Setting all of a previous oldext extent to newext.
1660		 * The right neighbor is contiguous, the left is not.
1661		 */
1662		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1663				RIGHT.rm_blockcount, RIGHT.rm_owner,
1664				RIGHT.rm_offset, RIGHT.rm_flags);
1665		if (error)
1666			goto done;
1667		NEW = PREV;
1668		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1669				NEW.rm_blockcount, NEW.rm_owner,
1670				NEW.rm_offset, NEW.rm_flags, &i);
1671		if (error)
1672			goto done;
1673		if (XFS_IS_CORRUPT(mp, i != 1)) {
1674			error = -EFSCORRUPTED;
1675			goto done;
1676		}
1677		NEW.rm_blockcount += RIGHT.rm_blockcount;
1678		NEW.rm_flags = RIGHT.rm_flags;
1679		error = xfs_rmap_update(cur, &NEW);
1680		if (error)
1681			goto done;
1682		break;
1683
1684	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1685		/*
1686		 * Setting all of a previous oldext extent to newext.
1687		 * Neither the left nor right neighbors are contiguous with
1688		 * the new one.
1689		 */
1690		NEW = PREV;
1691		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1692				NEW.rm_blockcount, NEW.rm_owner,
1693				NEW.rm_offset, NEW.rm_flags, &i);
1694		if (error)
1695			goto done;
1696		if (XFS_IS_CORRUPT(mp, i != 1)) {
1697			error = -EFSCORRUPTED;
1698			goto done;
1699		}
1700		NEW.rm_flags = newext;
1701		error = xfs_rmap_update(cur, &NEW);
1702		if (error)
1703			goto done;
1704		break;
1705
1706	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1707		/*
1708		 * Setting the first part of a previous oldext extent to newext.
1709		 * The left neighbor is contiguous.
1710		 */
1711		NEW = PREV;
1712		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1713				NEW.rm_blockcount, NEW.rm_owner,
1714				NEW.rm_offset, NEW.rm_flags);
1715		if (error)
1716			goto done;
1717		NEW.rm_offset += len;
1718		NEW.rm_startblock += len;
1719		NEW.rm_blockcount -= len;
1720		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1721				NEW.rm_blockcount, NEW.rm_owner,
1722				NEW.rm_offset, NEW.rm_flags);
1723		if (error)
1724			goto done;
1725		NEW = LEFT;
1726		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1727				NEW.rm_blockcount, NEW.rm_owner,
1728				NEW.rm_offset, NEW.rm_flags, &i);
1729		if (error)
1730			goto done;
1731		if (XFS_IS_CORRUPT(mp, i != 1)) {
1732			error = -EFSCORRUPTED;
1733			goto done;
1734		}
1735		NEW.rm_blockcount += len;
1736		error = xfs_rmap_update(cur, &NEW);
1737		if (error)
1738			goto done;
1739		break;
1740
1741	case RMAP_LEFT_FILLING:
1742		/*
1743		 * Setting the first part of a previous oldext extent to newext.
1744		 * The left neighbor is not contiguous.
1745		 */
1746		NEW = PREV;
1747		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1748				NEW.rm_blockcount, NEW.rm_owner,
1749				NEW.rm_offset, NEW.rm_flags);
1750		if (error)
1751			goto done;
1752		NEW.rm_offset += len;
1753		NEW.rm_startblock += len;
1754		NEW.rm_blockcount -= len;
1755		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1756				NEW.rm_blockcount, NEW.rm_owner,
1757				NEW.rm_offset, NEW.rm_flags);
1758		if (error)
1759			goto done;
1760		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1761		if (error)
1762			goto done;
1763		break;
1764
1765	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1766		/*
1767		 * Setting the last part of a previous oldext extent to newext.
1768		 * The right neighbor is contiguous with the new allocation.
1769		 */
1770		NEW = PREV;
1771		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1772				NEW.rm_blockcount, NEW.rm_owner,
1773				NEW.rm_offset, NEW.rm_flags, &i);
1774		if (error)
1775			goto done;
1776		if (XFS_IS_CORRUPT(mp, i != 1)) {
1777			error = -EFSCORRUPTED;
1778			goto done;
1779		}
1780		NEW.rm_blockcount = offset - NEW.rm_offset;
1781		error = xfs_rmap_update(cur, &NEW);
1782		if (error)
1783			goto done;
1784		NEW = RIGHT;
1785		error = xfs_rmap_delete(cur, NEW.rm_startblock,
1786				NEW.rm_blockcount, NEW.rm_owner,
1787				NEW.rm_offset, NEW.rm_flags);
1788		if (error)
1789			goto done;
1790		NEW.rm_offset = offset;
1791		NEW.rm_startblock = bno;
1792		NEW.rm_blockcount += len;
1793		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1794				NEW.rm_blockcount, NEW.rm_owner,
1795				NEW.rm_offset, NEW.rm_flags);
1796		if (error)
1797			goto done;
1798		break;
1799
1800	case RMAP_RIGHT_FILLING:
1801		/*
1802		 * Setting the last part of a previous oldext extent to newext.
1803		 * The right neighbor is not contiguous.
1804		 */
1805		NEW = PREV;
1806		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1807				NEW.rm_blockcount, NEW.rm_owner,
1808				NEW.rm_offset, NEW.rm_flags, &i);
1809		if (error)
1810			goto done;
1811		if (XFS_IS_CORRUPT(mp, i != 1)) {
1812			error = -EFSCORRUPTED;
1813			goto done;
1814		}
1815		NEW.rm_blockcount -= len;
1816		error = xfs_rmap_update(cur, &NEW);
1817		if (error)
1818			goto done;
1819		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1820		if (error)
1821			goto done;
1822		break;
1823
1824	case 0:
1825		/*
1826		 * Setting the middle part of a previous oldext extent to
1827		 * newext.  Contiguity is impossible here.
1828		 * One extent becomes three extents.
1829		 */
1830		/* new right extent - oldext */
1831		NEW.rm_startblock = bno + len;
1832		NEW.rm_owner = owner;
1833		NEW.rm_offset = new_endoff;
1834		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1835				new_endoff;
1836		NEW.rm_flags = PREV.rm_flags;
1837		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1838				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1839				NEW.rm_flags);
1840		if (error)
1841			goto done;
1842		/* new left extent - oldext */
1843		NEW = PREV;
1844		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1845				NEW.rm_blockcount, NEW.rm_owner,
1846				NEW.rm_offset, NEW.rm_flags, &i);
1847		if (error)
1848			goto done;
1849		if (XFS_IS_CORRUPT(mp, i != 1)) {
1850			error = -EFSCORRUPTED;
1851			goto done;
1852		}
1853		NEW.rm_blockcount = offset - NEW.rm_offset;
1854		error = xfs_rmap_update(cur, &NEW);
1855		if (error)
1856			goto done;
1857		/* new middle extent - newext */
1858		NEW.rm_startblock = bno;
1859		NEW.rm_blockcount = len;
1860		NEW.rm_owner = owner;
1861		NEW.rm_offset = offset;
1862		NEW.rm_flags = newext;
1863		error = xfs_rmap_insert(cur, NEW.rm_startblock,
1864				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1865				NEW.rm_flags);
1866		if (error)
1867			goto done;
1868		break;
1869
1870	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1871	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1872	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1873	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1874	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1875	case RMAP_LEFT_CONTIG:
1876	case RMAP_RIGHT_CONTIG:
1877		/*
1878		 * These cases are all impossible.
1879		 */
1880		ASSERT(0);
1881	}
1882
1883	trace_xfs_rmap_convert_done(mp, cur->bc_ag.agno, bno, len,
1884			unwritten, oinfo);
1885done:
1886	if (error)
1887		trace_xfs_rmap_convert_error(cur->bc_mp,
1888				cur->bc_ag.agno, error, _RET_IP_);
1889	return error;
1890}
1891
1892#undef	NEW
1893#undef	LEFT
1894#undef	RIGHT
1895#undef	PREV
1896
1897/*
1898 * Find an extent in the rmap btree and unmap it.  For rmap extent types that
1899 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1900 * that the prev/next records in the btree might belong to another owner.
1901 * Therefore we must use delete+insert to alter any of the key fields.
1902 *
1903 * For every other situation there can only be one owner for a given extent,
1904 * so we can call the regular _free function.
1905 */
1906STATIC int
1907xfs_rmap_unmap_shared(
1908	struct xfs_btree_cur		*cur,
1909	xfs_agblock_t			bno,
1910	xfs_extlen_t			len,
1911	bool				unwritten,
1912	const struct xfs_owner_info	*oinfo)
1913{
1914	struct xfs_mount		*mp = cur->bc_mp;
1915	struct xfs_rmap_irec		ltrec;
1916	uint64_t			ltoff;
1917	int				error = 0;
1918	int				i;
1919	uint64_t			owner;
1920	uint64_t			offset;
1921	unsigned int			flags;
1922
1923	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1924	if (unwritten)
1925		flags |= XFS_RMAP_UNWRITTEN;
1926	trace_xfs_rmap_unmap(mp, cur->bc_ag.agno, bno, len,
1927			unwritten, oinfo);
1928
1929	/*
1930	 * We should always have a left record because there's a static record
1931	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1932	 * will not ever be removed from the tree.
1933	 */
1934	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1935			&ltrec, &i);
1936	if (error)
1937		goto out_error;
1938	if (XFS_IS_CORRUPT(mp, i != 1)) {
1939		error = -EFSCORRUPTED;
1940		goto out_error;
1941	}
1942	ltoff = ltrec.rm_offset;
1943
1944	/* Make sure the extent we found covers the entire freeing range. */
1945	if (XFS_IS_CORRUPT(mp,
1946			   ltrec.rm_startblock > bno ||
1947			   ltrec.rm_startblock + ltrec.rm_blockcount <
1948			   bno + len)) {
1949		error = -EFSCORRUPTED;
1950		goto out_error;
1951	}
1952
1953	/* Make sure the owner matches what we expect to find in the tree. */
1954	if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1955		error = -EFSCORRUPTED;
1956		goto out_error;
1957	}
1958
1959	/* Make sure the unwritten flag matches. */
1960	if (XFS_IS_CORRUPT(mp,
1961			   (flags & XFS_RMAP_UNWRITTEN) !=
1962			   (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
1963		error = -EFSCORRUPTED;
1964		goto out_error;
1965	}
1966
1967	/* Check the offset. */
1968	if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
1969		error = -EFSCORRUPTED;
1970		goto out_error;
1971	}
1972	if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
1973		error = -EFSCORRUPTED;
1974		goto out_error;
1975	}
1976
1977	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1978		/* Exact match, simply remove the record from rmap tree. */
1979		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1980				ltrec.rm_blockcount, ltrec.rm_owner,
1981				ltrec.rm_offset, ltrec.rm_flags);
1982		if (error)
1983			goto out_error;
1984	} else if (ltrec.rm_startblock == bno) {
1985		/*
1986		 * Overlap left hand side of extent: move the start, trim the
1987		 * length and update the current record.
1988		 *
1989		 *       ltbno                ltlen
1990		 * Orig:    |oooooooooooooooooooo|
1991		 * Freeing: |fffffffff|
1992		 * Result:            |rrrrrrrrrr|
1993		 *         bno       len
1994		 */
1995
1996		/* Delete prev rmap. */
1997		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1998				ltrec.rm_blockcount, ltrec.rm_owner,
1999				ltrec.rm_offset, ltrec.rm_flags);
2000		if (error)
2001			goto out_error;
2002
2003		/* Add an rmap at the new offset. */
2004		ltrec.rm_startblock += len;
2005		ltrec.rm_blockcount -= len;
2006		ltrec.rm_offset += len;
2007		error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2008				ltrec.rm_blockcount, ltrec.rm_owner,
2009				ltrec.rm_offset, ltrec.rm_flags);
2010		if (error)
2011			goto out_error;
2012	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2013		/*
2014		 * Overlap right hand side of extent: trim the length and
2015		 * update the current record.
2016		 *
2017		 *       ltbno                ltlen
2018		 * Orig:    |oooooooooooooooooooo|
2019		 * Freeing:            |fffffffff|
2020		 * Result:  |rrrrrrrrrr|
2021		 *                    bno       len
2022		 */
2023		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2024				ltrec.rm_blockcount, ltrec.rm_owner,
2025				ltrec.rm_offset, ltrec.rm_flags, &i);
2026		if (error)
2027			goto out_error;
2028		if (XFS_IS_CORRUPT(mp, i != 1)) {
2029			error = -EFSCORRUPTED;
2030			goto out_error;
2031		}
2032		ltrec.rm_blockcount -= len;
2033		error = xfs_rmap_update(cur, &ltrec);
2034		if (error)
2035			goto out_error;
2036	} else {
2037		/*
2038		 * Overlap middle of extent: trim the length of the existing
2039		 * record to the length of the new left-extent size, increment
2040		 * the insertion position so we can insert a new record
2041		 * containing the remaining right-extent space.
2042		 *
2043		 *       ltbno                ltlen
2044		 * Orig:    |oooooooooooooooooooo|
2045		 * Freeing:       |fffffffff|
2046		 * Result:  |rrrrr|         |rrrr|
2047		 *               bno       len
2048		 */
2049		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
2050
2051		/* Shrink the left side of the rmap */
2052		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2053				ltrec.rm_blockcount, ltrec.rm_owner,
2054				ltrec.rm_offset, ltrec.rm_flags, &i);
2055		if (error)
2056			goto out_error;
2057		if (XFS_IS_CORRUPT(mp, i != 1)) {
2058			error = -EFSCORRUPTED;
2059			goto out_error;
2060		}
2061		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2062		error = xfs_rmap_update(cur, &ltrec);
2063		if (error)
2064			goto out_error;
2065
2066		/* Add an rmap at the new offset */
2067		error = xfs_rmap_insert(cur, bno + len,
2068				orig_len - len - ltrec.rm_blockcount,
2069				ltrec.rm_owner, offset + len,
2070				ltrec.rm_flags);
2071		if (error)
2072			goto out_error;
2073	}
2074
2075	trace_xfs_rmap_unmap_done(mp, cur->bc_ag.agno, bno, len,
2076			unwritten, oinfo);
2077out_error:
2078	if (error)
2079		trace_xfs_rmap_unmap_error(cur->bc_mp,
2080				cur->bc_ag.agno, error, _RET_IP_);
2081	return error;
2082}
2083
2084/*
2085 * Find an extent in the rmap btree and map it.  For rmap extent types that
2086 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2087 * that the prev/next records in the btree might belong to another owner.
2088 * Therefore we must use delete+insert to alter any of the key fields.
2089 *
2090 * For every other situation there can only be one owner for a given extent,
2091 * so we can call the regular _alloc function.
2092 */
2093STATIC int
2094xfs_rmap_map_shared(
2095	struct xfs_btree_cur		*cur,
2096	xfs_agblock_t			bno,
2097	xfs_extlen_t			len,
2098	bool				unwritten,
2099	const struct xfs_owner_info	*oinfo)
2100{
2101	struct xfs_mount		*mp = cur->bc_mp;
2102	struct xfs_rmap_irec		ltrec;
2103	struct xfs_rmap_irec		gtrec;
2104	int				have_gt;
2105	int				have_lt;
2106	int				error = 0;
2107	int				i;
2108	uint64_t			owner;
2109	uint64_t			offset;
2110	unsigned int			flags = 0;
2111
2112	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2113	if (unwritten)
2114		flags |= XFS_RMAP_UNWRITTEN;
2115	trace_xfs_rmap_map(mp, cur->bc_ag.agno, bno, len,
2116			unwritten, oinfo);
2117
2118	/* Is there a left record that abuts our range? */
2119	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2120			&ltrec, &have_lt);
2121	if (error)
2122		goto out_error;
2123	if (have_lt &&
2124	    !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2125		have_lt = 0;
2126
2127	/* Is there a right record that abuts our range? */
2128	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2129			flags, &have_gt);
2130	if (error)
2131		goto out_error;
2132	if (have_gt) {
2133		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2134		if (error)
2135			goto out_error;
2136		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2137			error = -EFSCORRUPTED;
2138			goto out_error;
2139		}
2140		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2141			cur->bc_ag.agno, gtrec.rm_startblock,
2142			gtrec.rm_blockcount, gtrec.rm_owner,
2143			gtrec.rm_offset, gtrec.rm_flags);
2144
2145		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2146			have_gt = 0;
2147	}
2148
2149	if (have_lt &&
2150	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2151	    ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2152		/*
2153		 * Left edge contiguous, merge into left record.
2154		 *
2155		 *       ltbno     ltlen
2156		 * orig:   |ooooooooo|
2157		 * adding:           |aaaaaaaaa|
2158		 * result: |rrrrrrrrrrrrrrrrrrr|
2159		 *                  bno       len
2160		 */
2161		ltrec.rm_blockcount += len;
2162		if (have_gt &&
2163		    bno + len == gtrec.rm_startblock &&
2164		    offset + len == gtrec.rm_offset) {
2165			/*
2166			 * Right edge also contiguous, delete right record
2167			 * and merge into left record.
2168			 *
2169			 *       ltbno     ltlen    gtbno     gtlen
2170			 * orig:   |ooooooooo|         |ooooooooo|
2171			 * adding:           |aaaaaaaaa|
2172			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2173			 */
2174			ltrec.rm_blockcount += gtrec.rm_blockcount;
2175			error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2176					gtrec.rm_blockcount, gtrec.rm_owner,
2177					gtrec.rm_offset, gtrec.rm_flags);
2178			if (error)
2179				goto out_error;
2180		}
2181
2182		/* Point the cursor back to the left record and update. */
2183		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2184				ltrec.rm_blockcount, ltrec.rm_owner,
2185				ltrec.rm_offset, ltrec.rm_flags, &i);
2186		if (error)
2187			goto out_error;
2188		if (XFS_IS_CORRUPT(mp, i != 1)) {
2189			error = -EFSCORRUPTED;
2190			goto out_error;
2191		}
2192
2193		error = xfs_rmap_update(cur, &ltrec);
2194		if (error)
2195			goto out_error;
2196	} else if (have_gt &&
2197		   bno + len == gtrec.rm_startblock &&
2198		   offset + len == gtrec.rm_offset) {
2199		/*
2200		 * Right edge contiguous, merge into right record.
2201		 *
2202		 *                 gtbno     gtlen
2203		 * Orig:             |ooooooooo|
2204		 * adding: |aaaaaaaaa|
2205		 * Result: |rrrrrrrrrrrrrrrrrrr|
2206		 *        bno       len
2207		 */
2208		/* Delete the old record. */
2209		error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2210				gtrec.rm_blockcount, gtrec.rm_owner,
2211				gtrec.rm_offset, gtrec.rm_flags);
2212		if (error)
2213			goto out_error;
2214
2215		/* Move the start and re-add it. */
2216		gtrec.rm_startblock = bno;
2217		gtrec.rm_blockcount += len;
2218		gtrec.rm_offset = offset;
2219		error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2220				gtrec.rm_blockcount, gtrec.rm_owner,
2221				gtrec.rm_offset, gtrec.rm_flags);
2222		if (error)
2223			goto out_error;
2224	} else {
2225		/*
2226		 * No contiguous edge with identical owner, insert
2227		 * new record at current cursor position.
2228		 */
2229		error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2230		if (error)
2231			goto out_error;
2232	}
2233
2234	trace_xfs_rmap_map_done(mp, cur->bc_ag.agno, bno, len,
2235			unwritten, oinfo);
2236out_error:
2237	if (error)
2238		trace_xfs_rmap_map_error(cur->bc_mp,
2239				cur->bc_ag.agno, error, _RET_IP_);
2240	return error;
2241}
2242
2243/* Insert a raw rmap into the rmapbt. */
2244int
2245xfs_rmap_map_raw(
2246	struct xfs_btree_cur	*cur,
2247	struct xfs_rmap_irec	*rmap)
2248{
2249	struct xfs_owner_info	oinfo;
2250
2251	oinfo.oi_owner = rmap->rm_owner;
2252	oinfo.oi_offset = rmap->rm_offset;
2253	oinfo.oi_flags = 0;
2254	if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2255		oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2256	if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2257		oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2258
2259	if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2260		return xfs_rmap_map(cur, rmap->rm_startblock,
2261				rmap->rm_blockcount,
2262				rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2263				&oinfo);
2264
2265	return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2266			rmap->rm_blockcount,
2267			rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2268			&oinfo);
2269}
2270
2271struct xfs_rmap_query_range_info {
2272	xfs_rmap_query_range_fn	fn;
2273	void				*priv;
2274};
2275
2276/* Format btree record and pass to our callback. */
2277STATIC int
2278xfs_rmap_query_range_helper(
2279	struct xfs_btree_cur	*cur,
2280	union xfs_btree_rec	*rec,
2281	void			*priv)
2282{
2283	struct xfs_rmap_query_range_info	*query = priv;
2284	struct xfs_rmap_irec			irec;
2285	int					error;
2286
2287	error = xfs_rmap_btrec_to_irec(rec, &irec);
2288	if (error)
2289		return error;
2290	return query->fn(cur, &irec, query->priv);
2291}
2292
2293/* Find all rmaps between two keys. */
2294int
2295xfs_rmap_query_range(
2296	struct xfs_btree_cur			*cur,
2297	struct xfs_rmap_irec			*low_rec,
2298	struct xfs_rmap_irec			*high_rec,
2299	xfs_rmap_query_range_fn			fn,
2300	void					*priv)
2301{
2302	union xfs_btree_irec			low_brec;
2303	union xfs_btree_irec			high_brec;
2304	struct xfs_rmap_query_range_info	query;
2305
2306	low_brec.r = *low_rec;
2307	high_brec.r = *high_rec;
2308	query.priv = priv;
2309	query.fn = fn;
2310	return xfs_btree_query_range(cur, &low_brec, &high_brec,
2311			xfs_rmap_query_range_helper, &query);
2312}
2313
2314/* Find all rmaps. */
2315int
2316xfs_rmap_query_all(
2317	struct xfs_btree_cur			*cur,
2318	xfs_rmap_query_range_fn			fn,
2319	void					*priv)
2320{
2321	struct xfs_rmap_query_range_info	query;
2322
2323	query.priv = priv;
2324	query.fn = fn;
2325	return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2326}
2327
2328/* Clean up after calling xfs_rmap_finish_one. */
2329void
2330xfs_rmap_finish_one_cleanup(
2331	struct xfs_trans	*tp,
2332	struct xfs_btree_cur	*rcur,
2333	int			error)
2334{
2335	struct xfs_buf		*agbp;
2336
2337	if (rcur == NULL)
2338		return;
2339	agbp = rcur->bc_ag.agbp;
2340	xfs_btree_del_cursor(rcur, error);
2341	if (error)
2342		xfs_trans_brelse(tp, agbp);
2343}
2344
2345/*
2346 * Process one of the deferred rmap operations.  We pass back the
2347 * btree cursor to maintain our lock on the rmapbt between calls.
2348 * This saves time and eliminates a buffer deadlock between the
2349 * superblock and the AGF because we'll always grab them in the same
2350 * order.
2351 */
2352int
2353xfs_rmap_finish_one(
2354	struct xfs_trans		*tp,
2355	enum xfs_rmap_intent_type	type,
2356	uint64_t			owner,
2357	int				whichfork,
2358	xfs_fileoff_t			startoff,
2359	xfs_fsblock_t			startblock,
2360	xfs_filblks_t			blockcount,
2361	xfs_exntst_t			state,
2362	struct xfs_btree_cur		**pcur)
2363{
2364	struct xfs_mount		*mp = tp->t_mountp;
 
2365	struct xfs_btree_cur		*rcur;
2366	struct xfs_buf			*agbp = NULL;
2367	int				error = 0;
2368	xfs_agnumber_t			agno;
2369	struct xfs_owner_info		oinfo;
2370	xfs_agblock_t			bno;
2371	bool				unwritten;
2372
2373	agno = XFS_FSB_TO_AGNO(mp, startblock);
2374	ASSERT(agno != NULLAGNUMBER);
2375	bno = XFS_FSB_TO_AGBNO(mp, startblock);
2376
2377	trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2378			startoff, blockcount, state);
2379
2380	if (XFS_TEST_ERROR(false, mp,
2381			XFS_ERRTAG_RMAP_FINISH_ONE))
2382		return -EIO;
 
 
2383
2384	/*
2385	 * If we haven't gotten a cursor or the cursor AG doesn't match
2386	 * the startblock, get one now.
2387	 */
2388	rcur = *pcur;
2389	if (rcur != NULL && rcur->bc_ag.agno != agno) {
2390		xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2391		rcur = NULL;
2392		*pcur = NULL;
2393	}
2394	if (rcur == NULL) {
2395		/*
2396		 * Refresh the freelist before we start changing the
2397		 * rmapbt, because a shape change could cause us to
2398		 * allocate blocks.
2399		 */
2400		error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2401		if (error)
2402			return error;
2403		if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
2404			return -EFSCORRUPTED;
2405
2406		rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2407		if (!rcur) {
2408			error = -ENOMEM;
2409			goto out_cur;
2410		}
 
 
2411	}
2412	*pcur = rcur;
2413
2414	xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2415	unwritten = state == XFS_EXT_UNWRITTEN;
2416	bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2417
2418	switch (type) {
2419	case XFS_RMAP_ALLOC:
2420	case XFS_RMAP_MAP:
2421		error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2422		break;
2423	case XFS_RMAP_MAP_SHARED:
2424		error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2425				&oinfo);
2426		break;
2427	case XFS_RMAP_FREE:
2428	case XFS_RMAP_UNMAP:
2429		error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2430				&oinfo);
2431		break;
2432	case XFS_RMAP_UNMAP_SHARED:
2433		error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2434				&oinfo);
2435		break;
2436	case XFS_RMAP_CONVERT:
2437		error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2438				&oinfo);
2439		break;
2440	case XFS_RMAP_CONVERT_SHARED:
2441		error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2442				!unwritten, &oinfo);
2443		break;
2444	default:
2445		ASSERT(0);
2446		error = -EFSCORRUPTED;
2447	}
2448	return error;
2449
2450out_cur:
2451	xfs_trans_brelse(tp, agbp);
2452
2453	return error;
2454}
2455
2456/*
2457 * Don't defer an rmap if we aren't an rmap filesystem.
2458 */
2459static bool
2460xfs_rmap_update_is_needed(
2461	struct xfs_mount	*mp,
2462	int			whichfork)
2463{
2464	return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2465}
2466
2467/*
2468 * Record a rmap intent; the list is kept sorted first by AG and then by
2469 * increasing age.
2470 */
2471static void
2472__xfs_rmap_add(
2473	struct xfs_trans		*tp,
2474	enum xfs_rmap_intent_type	type,
2475	uint64_t			owner,
2476	int				whichfork,
2477	struct xfs_bmbt_irec		*bmap)
2478{
2479	struct xfs_rmap_intent		*ri;
2480
2481	trace_xfs_rmap_defer(tp->t_mountp,
2482			XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2483			type,
2484			XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2485			owner, whichfork,
2486			bmap->br_startoff,
2487			bmap->br_blockcount,
2488			bmap->br_state);
2489
2490	ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS);
2491	INIT_LIST_HEAD(&ri->ri_list);
2492	ri->ri_type = type;
2493	ri->ri_owner = owner;
2494	ri->ri_whichfork = whichfork;
2495	ri->ri_bmap = *bmap;
2496
2497	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2498}
2499
2500/* Map an extent into a file. */
2501void
2502xfs_rmap_map_extent(
2503	struct xfs_trans	*tp,
2504	struct xfs_inode	*ip,
2505	int			whichfork,
2506	struct xfs_bmbt_irec	*PREV)
2507{
 
 
2508	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2509		return;
2510
2511	__xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2512			XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2513			whichfork, PREV);
 
2514}
2515
2516/* Unmap an extent out of a file. */
2517void
2518xfs_rmap_unmap_extent(
2519	struct xfs_trans	*tp,
2520	struct xfs_inode	*ip,
2521	int			whichfork,
2522	struct xfs_bmbt_irec	*PREV)
2523{
 
 
2524	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2525		return;
2526
2527	__xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2528			XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2529			whichfork, PREV);
 
2530}
2531
2532/*
2533 * Convert a data fork extent from unwritten to real or vice versa.
2534 *
2535 * Note that tp can be NULL here as no transaction is used for COW fork
2536 * unwritten conversion.
2537 */
2538void
2539xfs_rmap_convert_extent(
2540	struct xfs_mount	*mp,
2541	struct xfs_trans	*tp,
2542	struct xfs_inode	*ip,
2543	int			whichfork,
2544	struct xfs_bmbt_irec	*PREV)
2545{
 
 
2546	if (!xfs_rmap_update_is_needed(mp, whichfork))
2547		return;
2548
2549	__xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
2550			XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2551			whichfork, PREV);
 
2552}
2553
2554/* Schedule the creation of an rmap for non-file data. */
2555void
2556xfs_rmap_alloc_extent(
2557	struct xfs_trans	*tp,
2558	xfs_agnumber_t		agno,
2559	xfs_agblock_t		bno,
2560	xfs_extlen_t		len,
2561	uint64_t		owner)
2562{
2563	struct xfs_bmbt_irec	bmap;
2564
2565	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2566		return;
2567
2568	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2569	bmap.br_blockcount = len;
2570	bmap.br_startoff = 0;
2571	bmap.br_state = XFS_EXT_NORM;
2572
2573	__xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2574}
2575
2576/* Schedule the deletion of an rmap for non-file data. */
2577void
2578xfs_rmap_free_extent(
2579	struct xfs_trans	*tp,
2580	xfs_agnumber_t		agno,
2581	xfs_agblock_t		bno,
2582	xfs_extlen_t		len,
2583	uint64_t		owner)
2584{
2585	struct xfs_bmbt_irec	bmap;
2586
2587	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2588		return;
2589
2590	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2591	bmap.br_blockcount = len;
2592	bmap.br_startoff = 0;
2593	bmap.br_state = XFS_EXT_NORM;
2594
2595	__xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2596}
2597
2598/* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2599int
2600xfs_rmap_compare(
2601	const struct xfs_rmap_irec	*a,
2602	const struct xfs_rmap_irec	*b)
2603{
2604	__u64				oa;
2605	__u64				ob;
2606
2607	oa = xfs_rmap_irec_offset_pack(a);
2608	ob = xfs_rmap_irec_offset_pack(b);
2609
2610	if (a->rm_startblock < b->rm_startblock)
2611		return -1;
2612	else if (a->rm_startblock > b->rm_startblock)
2613		return 1;
2614	else if (a->rm_owner < b->rm_owner)
2615		return -1;
2616	else if (a->rm_owner > b->rm_owner)
2617		return 1;
2618	else if (oa < ob)
2619		return -1;
2620	else if (oa > ob)
2621		return 1;
2622	else
2623		return 0;
2624}
2625
2626/* Is there a record covering a given extent? */
2627int
2628xfs_rmap_has_record(
2629	struct xfs_btree_cur	*cur,
2630	xfs_agblock_t		bno,
2631	xfs_extlen_t		len,
2632	bool			*exists)
2633{
2634	union xfs_btree_irec	low;
2635	union xfs_btree_irec	high;
2636
2637	memset(&low, 0, sizeof(low));
2638	low.r.rm_startblock = bno;
2639	memset(&high, 0xFF, sizeof(high));
2640	high.r.rm_startblock = bno + len - 1;
2641
2642	return xfs_btree_has_record(cur, &low, &high, exists);
2643}
2644
2645/*
2646 * Is there a record for this owner completely covering a given physical
2647 * extent?  If so, *has_rmap will be set to true.  If there is no record
2648 * or the record only covers part of the range, we set *has_rmap to false.
2649 * This function doesn't perform range lookups or offset checks, so it is
2650 * not suitable for checking data fork blocks.
2651 */
2652int
2653xfs_rmap_record_exists(
2654	struct xfs_btree_cur		*cur,
2655	xfs_agblock_t			bno,
2656	xfs_extlen_t			len,
2657	const struct xfs_owner_info	*oinfo,
2658	bool				*has_rmap)
2659{
2660	uint64_t			owner;
2661	uint64_t			offset;
2662	unsigned int			flags;
2663	int				has_record;
2664	struct xfs_rmap_irec		irec;
2665	int				error;
2666
2667	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2668	ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2669	       (flags & XFS_RMAP_BMBT_BLOCK));
2670
2671	error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2672			&has_record);
2673	if (error)
2674		return error;
2675	if (!has_record) {
2676		*has_rmap = false;
2677		return 0;
2678	}
2679
2680	error = xfs_rmap_get_rec(cur, &irec, &has_record);
2681	if (error)
2682		return error;
2683	if (!has_record) {
2684		*has_rmap = false;
2685		return 0;
2686	}
2687
2688	*has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2689		     irec.rm_startblock + irec.rm_blockcount >= bno + len);
2690	return 0;
2691}
2692
2693struct xfs_rmap_key_state {
2694	uint64_t			owner;
2695	uint64_t			offset;
2696	unsigned int			flags;
2697};
2698
2699/* For each rmap given, figure out if it doesn't match the key we want. */
2700STATIC int
2701xfs_rmap_has_other_keys_helper(
2702	struct xfs_btree_cur		*cur,
2703	struct xfs_rmap_irec		*rec,
2704	void				*priv)
2705{
2706	struct xfs_rmap_key_state	*rks = priv;
2707
2708	if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2709	    ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2710		return 0;
2711	return -ECANCELED;
2712}
2713
2714/*
2715 * Given an extent and some owner info, can we find records overlapping
2716 * the extent whose owner info does not match the given owner?
2717 */
2718int
2719xfs_rmap_has_other_keys(
2720	struct xfs_btree_cur		*cur,
2721	xfs_agblock_t			bno,
2722	xfs_extlen_t			len,
2723	const struct xfs_owner_info	*oinfo,
2724	bool				*has_rmap)
2725{
2726	struct xfs_rmap_irec		low = {0};
2727	struct xfs_rmap_irec		high;
2728	struct xfs_rmap_key_state	rks;
2729	int				error;
2730
2731	xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2732	*has_rmap = false;
2733
2734	low.rm_startblock = bno;
2735	memset(&high, 0xFF, sizeof(high));
2736	high.rm_startblock = bno + len - 1;
2737
2738	error = xfs_rmap_query_range(cur, &low, &high,
2739			xfs_rmap_has_other_keys_helper, &rks);
2740	if (error == -ECANCELED) {
2741		*has_rmap = true;
2742		return 0;
2743	}
2744
2745	return error;
2746}
2747
2748const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2749	.oi_owner = XFS_RMAP_OWN_NULL,
2750};
2751const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2752	.oi_owner = XFS_RMAP_OWN_UNKNOWN,
2753};
2754const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2755	.oi_owner = XFS_RMAP_OWN_FS,
2756};
2757const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2758	.oi_owner = XFS_RMAP_OWN_LOG,
2759};
2760const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2761	.oi_owner = XFS_RMAP_OWN_AG,
2762};
2763const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2764	.oi_owner = XFS_RMAP_OWN_INOBT,
2765};
2766const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2767	.oi_owner = XFS_RMAP_OWN_INODES,
2768};
2769const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2770	.oi_owner = XFS_RMAP_OWN_REFC,
2771};
2772const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2773	.oi_owner = XFS_RMAP_OWN_COW,
2774};