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