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