xref: /linux/fs/xfs/libxfs/xfs_rmap.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0
2673930c3SDarrick J. Wong /*
3673930c3SDarrick J. Wong  * Copyright (c) 2014 Red Hat, Inc.
4673930c3SDarrick J. Wong  * All Rights Reserved.
5673930c3SDarrick J. Wong  */
6673930c3SDarrick J. Wong #include "xfs.h"
7673930c3SDarrick J. Wong #include "xfs_fs.h"
8673930c3SDarrick J. Wong #include "xfs_shared.h"
9673930c3SDarrick J. Wong #include "xfs_format.h"
10673930c3SDarrick J. Wong #include "xfs_log_format.h"
11673930c3SDarrick J. Wong #include "xfs_trans_resv.h"
12673930c3SDarrick J. Wong #include "xfs_bit.h"
13673930c3SDarrick J. Wong #include "xfs_mount.h"
1445d06621SDave Chinner #include "xfs_sb.h"
15673930c3SDarrick J. Wong #include "xfs_defer.h"
16673930c3SDarrick J. Wong #include "xfs_btree.h"
17673930c3SDarrick J. Wong #include "xfs_trans.h"
18673930c3SDarrick J. Wong #include "xfs_alloc.h"
19673930c3SDarrick J. Wong #include "xfs_rmap.h"
200a1b0b38SDarrick J. Wong #include "xfs_rmap_btree.h"
21673930c3SDarrick J. Wong #include "xfs_trace.h"
22e9e899a2SDarrick J. Wong #include "xfs_errortag.h"
23673930c3SDarrick J. Wong #include "xfs_error.h"
249c194644SDarrick J. Wong #include "xfs_inode.h"
259bbafc71SDave Chinner #include "xfs_ag.h"
26a78d10f4SDarrick J. Wong #include "xfs_health.h"
27*ea7b0820SDarrick J. Wong #include "xfs_rmap_item.h"
28673930c3SDarrick J. Wong 
29f3c799c2SDarrick J. Wong struct kmem_cache	*xfs_rmap_intent_cache;
30f3c799c2SDarrick J. Wong 
314b8ed677SDarrick J. Wong /*
324b8ed677SDarrick J. Wong  * Lookup the first record less than or equal to [bno, len, owner, offset]
334b8ed677SDarrick J. Wong  * in the btree given by cur.
344b8ed677SDarrick J. Wong  */
354b8ed677SDarrick J. Wong int
xfs_rmap_lookup_le(struct xfs_btree_cur * cur,xfs_agblock_t bno,uint64_t owner,uint64_t offset,unsigned int flags,struct xfs_rmap_irec * irec,int * stat)364b8ed677SDarrick J. Wong xfs_rmap_lookup_le(
374b8ed677SDarrick J. Wong 	struct xfs_btree_cur	*cur,
384b8ed677SDarrick J. Wong 	xfs_agblock_t		bno,
394b8ed677SDarrick J. Wong 	uint64_t		owner,
404b8ed677SDarrick J. Wong 	uint64_t		offset,
414b8ed677SDarrick J. Wong 	unsigned int		flags,
425b7ca8b3SDarrick J. Wong 	struct xfs_rmap_irec	*irec,
434b8ed677SDarrick J. Wong 	int			*stat)
444b8ed677SDarrick J. Wong {
455b7ca8b3SDarrick J. Wong 	int			get_stat = 0;
465b7ca8b3SDarrick J. Wong 	int			error;
475b7ca8b3SDarrick J. Wong 
484b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_startblock = bno;
495b7ca8b3SDarrick J. Wong 	cur->bc_rec.r.rm_blockcount = 0;
504b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_owner = owner;
514b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_offset = offset;
524b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_flags = flags;
535b7ca8b3SDarrick J. Wong 
545b7ca8b3SDarrick J. Wong 	error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
555b7ca8b3SDarrick J. Wong 	if (error || !(*stat) || !irec)
565b7ca8b3SDarrick J. Wong 		return error;
575b7ca8b3SDarrick J. Wong 
585b7ca8b3SDarrick J. Wong 	error = xfs_rmap_get_rec(cur, irec, &get_stat);
595b7ca8b3SDarrick J. Wong 	if (error)
605b7ca8b3SDarrick J. Wong 		return error;
61a78d10f4SDarrick J. Wong 	if (!get_stat) {
62a78d10f4SDarrick J. Wong 		xfs_btree_mark_sick(cur);
635b7ca8b3SDarrick J. Wong 		return -EFSCORRUPTED;
64a78d10f4SDarrick J. Wong 	}
655b7ca8b3SDarrick J. Wong 
665b7ca8b3SDarrick J. Wong 	return 0;
674b8ed677SDarrick J. Wong }
684b8ed677SDarrick J. Wong 
694b8ed677SDarrick J. Wong /*
704b8ed677SDarrick J. Wong  * Lookup the record exactly matching [bno, len, owner, offset]
714b8ed677SDarrick J. Wong  * in the btree given by cur.
724b8ed677SDarrick J. Wong  */
734b8ed677SDarrick J. Wong int
xfs_rmap_lookup_eq(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags,int * stat)744b8ed677SDarrick J. Wong xfs_rmap_lookup_eq(
754b8ed677SDarrick J. Wong 	struct xfs_btree_cur	*cur,
764b8ed677SDarrick J. Wong 	xfs_agblock_t		bno,
774b8ed677SDarrick J. Wong 	xfs_extlen_t		len,
784b8ed677SDarrick J. Wong 	uint64_t		owner,
794b8ed677SDarrick J. Wong 	uint64_t		offset,
804b8ed677SDarrick J. Wong 	unsigned int		flags,
814b8ed677SDarrick J. Wong 	int			*stat)
824b8ed677SDarrick J. Wong {
834b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_startblock = bno;
844b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_blockcount = len;
854b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_owner = owner;
864b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_offset = offset;
874b8ed677SDarrick J. Wong 	cur->bc_rec.r.rm_flags = flags;
884b8ed677SDarrick J. Wong 	return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
894b8ed677SDarrick J. Wong }
904b8ed677SDarrick J. Wong 
914b8ed677SDarrick J. Wong /*
924b8ed677SDarrick J. Wong  * Update the record referred to by cur to the value given
934b8ed677SDarrick J. Wong  * by [bno, len, owner, offset].
944b8ed677SDarrick J. Wong  * This either works (return 0) or gets an EFSCORRUPTED error.
954b8ed677SDarrick J. Wong  */
964b8ed677SDarrick J. Wong STATIC int
xfs_rmap_update(struct xfs_btree_cur * cur,struct xfs_rmap_irec * irec)974b8ed677SDarrick J. Wong xfs_rmap_update(
984b8ed677SDarrick J. Wong 	struct xfs_btree_cur	*cur,
994b8ed677SDarrick J. Wong 	struct xfs_rmap_irec	*irec)
1004b8ed677SDarrick J. Wong {
1014b8ed677SDarrick J. Wong 	union xfs_btree_rec	rec;
102abf09233SDarrick J. Wong 	int			error;
103abf09233SDarrick J. Wong 
10447492ed1SDarrick J. Wong 	trace_xfs_rmap_update(cur, irec->rm_startblock, irec->rm_blockcount,
105abf09233SDarrick J. Wong 			irec->rm_owner, irec->rm_offset, irec->rm_flags);
1064b8ed677SDarrick J. Wong 
1074b8ed677SDarrick J. Wong 	rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
1084b8ed677SDarrick J. Wong 	rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
1094b8ed677SDarrick J. Wong 	rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
1104b8ed677SDarrick J. Wong 	rec.rmap.rm_offset = cpu_to_be64(
1114b8ed677SDarrick J. Wong 			xfs_rmap_irec_offset_pack(irec));
112abf09233SDarrick J. Wong 	error = xfs_btree_update(cur, &rec);
113abf09233SDarrick J. Wong 	if (error)
11471f5a17eSDarrick J. Wong 		trace_xfs_rmap_update_error(cur, error, _RET_IP_);
115abf09233SDarrick J. Wong 	return error;
116abf09233SDarrick J. Wong }
117abf09233SDarrick J. Wong 
118abf09233SDarrick J. Wong int
xfs_rmap_insert(struct xfs_btree_cur * rcur,xfs_agblock_t agbno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags)119abf09233SDarrick J. Wong xfs_rmap_insert(
120abf09233SDarrick J. Wong 	struct xfs_btree_cur	*rcur,
121abf09233SDarrick J. Wong 	xfs_agblock_t		agbno,
122abf09233SDarrick J. Wong 	xfs_extlen_t		len,
123abf09233SDarrick J. Wong 	uint64_t		owner,
124abf09233SDarrick J. Wong 	uint64_t		offset,
125abf09233SDarrick J. Wong 	unsigned int		flags)
126abf09233SDarrick J. Wong {
127abf09233SDarrick J. Wong 	int			i;
128abf09233SDarrick J. Wong 	int			error;
129abf09233SDarrick J. Wong 
13047492ed1SDarrick J. Wong 	trace_xfs_rmap_insert(rcur, agbno, len, owner, offset, flags);
131abf09233SDarrick J. Wong 
132abf09233SDarrick J. Wong 	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
133abf09233SDarrick J. Wong 	if (error)
134abf09233SDarrick J. Wong 		goto done;
135f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
136989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(rcur);
137f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
138f9e03706SDarrick J. Wong 		goto done;
139f9e03706SDarrick J. Wong 	}
140abf09233SDarrick J. Wong 
141abf09233SDarrick J. Wong 	rcur->bc_rec.r.rm_startblock = agbno;
142abf09233SDarrick J. Wong 	rcur->bc_rec.r.rm_blockcount = len;
143abf09233SDarrick J. Wong 	rcur->bc_rec.r.rm_owner = owner;
144abf09233SDarrick J. Wong 	rcur->bc_rec.r.rm_offset = offset;
145abf09233SDarrick J. Wong 	rcur->bc_rec.r.rm_flags = flags;
146abf09233SDarrick J. Wong 	error = xfs_btree_insert(rcur, &i);
147abf09233SDarrick J. Wong 	if (error)
148abf09233SDarrick J. Wong 		goto done;
149f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
150989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(rcur);
151f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
152f9e03706SDarrick J. Wong 		goto done;
153f9e03706SDarrick J. Wong 	}
154abf09233SDarrick J. Wong done:
155abf09233SDarrick J. Wong 	if (error)
15671f5a17eSDarrick J. Wong 		trace_xfs_rmap_insert_error(rcur, error, _RET_IP_);
157abf09233SDarrick J. Wong 	return error;
1584b8ed677SDarrick J. Wong }
1594b8ed677SDarrick J. Wong 
160ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_delete(struct xfs_btree_cur * rcur,xfs_agblock_t agbno,xfs_extlen_t len,uint64_t owner,uint64_t offset,unsigned int flags)161ceeb9c83SDarrick J. Wong xfs_rmap_delete(
162ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur	*rcur,
163ceeb9c83SDarrick J. Wong 	xfs_agblock_t		agbno,
164ceeb9c83SDarrick J. Wong 	xfs_extlen_t		len,
165ceeb9c83SDarrick J. Wong 	uint64_t		owner,
166ceeb9c83SDarrick J. Wong 	uint64_t		offset,
167ceeb9c83SDarrick J. Wong 	unsigned int		flags)
168ceeb9c83SDarrick J. Wong {
169ceeb9c83SDarrick J. Wong 	int			i;
170ceeb9c83SDarrick J. Wong 	int			error;
171ceeb9c83SDarrick J. Wong 
17247492ed1SDarrick J. Wong 	trace_xfs_rmap_delete(rcur, agbno, len, owner, offset, flags);
173ceeb9c83SDarrick J. Wong 
174ceeb9c83SDarrick J. Wong 	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
175ceeb9c83SDarrick J. Wong 	if (error)
176ceeb9c83SDarrick J. Wong 		goto done;
177f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
178989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(rcur);
179f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
180f9e03706SDarrick J. Wong 		goto done;
181f9e03706SDarrick J. Wong 	}
182ceeb9c83SDarrick J. Wong 
183ceeb9c83SDarrick J. Wong 	error = xfs_btree_delete(rcur, &i);
184ceeb9c83SDarrick J. Wong 	if (error)
185ceeb9c83SDarrick J. Wong 		goto done;
186f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
187989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(rcur);
188f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
189f9e03706SDarrick J. Wong 		goto done;
190f9e03706SDarrick J. Wong 	}
191ceeb9c83SDarrick J. Wong done:
192ceeb9c83SDarrick J. Wong 	if (error)
19371f5a17eSDarrick J. Wong 		trace_xfs_rmap_delete_error(rcur, error, _RET_IP_);
194ceeb9c83SDarrick J. Wong 	return error;
195ceeb9c83SDarrick J. Wong }
196ceeb9c83SDarrick J. Wong 
19726788097SDarrick J. Wong /* Convert an internal btree record to an rmap record. */
19839ab26d5SDarrick J. Wong xfs_failaddr_t
xfs_rmap_btrec_to_irec(const union xfs_btree_rec * rec,struct xfs_rmap_irec * irec)1994b8ed677SDarrick J. Wong xfs_rmap_btrec_to_irec(
200159eb69dSDarrick J. Wong 	const union xfs_btree_rec	*rec,
2014b8ed677SDarrick J. Wong 	struct xfs_rmap_irec		*irec)
2024b8ed677SDarrick J. Wong {
2034b8ed677SDarrick J. Wong 	irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
2044b8ed677SDarrick J. Wong 	irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
2054b8ed677SDarrick J. Wong 	irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
2064b8ed677SDarrick J. Wong 	return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
2074b8ed677SDarrick J. Wong 			irec);
2084b8ed677SDarrick J. Wong }
2094b8ed677SDarrick J. Wong 
210c4e34172SDarrick J. Wong /* Simple checks for rmap records. */
211c4e34172SDarrick J. Wong xfs_failaddr_t
xfs_rmap_check_irec(struct xfs_perag * pag,const struct xfs_rmap_irec * irec)212c4e34172SDarrick J. Wong xfs_rmap_check_irec(
21332080a9bSDarrick J. Wong 	struct xfs_perag		*pag,
214c4e34172SDarrick J. Wong 	const struct xfs_rmap_irec	*irec)
215c4e34172SDarrick J. Wong {
21632080a9bSDarrick J. Wong 	struct xfs_mount		*mp = pag->pag_mount;
2177d7d6d2fSDarrick J. Wong 	bool				is_inode;
2187d7d6d2fSDarrick J. Wong 	bool				is_unwritten;
2197d7d6d2fSDarrick J. Wong 	bool				is_bmbt;
2207d7d6d2fSDarrick J. Wong 	bool				is_attr;
221c4e34172SDarrick J. Wong 
222c4e34172SDarrick J. Wong 	if (irec->rm_blockcount == 0)
223c4e34172SDarrick J. Wong 		return __this_address;
224c4e34172SDarrick J. Wong 	if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
225c4e34172SDarrick J. Wong 		if (irec->rm_owner != XFS_RMAP_OWN_FS)
226c4e34172SDarrick J. Wong 			return __this_address;
227c4e34172SDarrick J. Wong 		if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
228c4e34172SDarrick J. Wong 			return __this_address;
229c4e34172SDarrick J. Wong 	} else {
230c4e34172SDarrick J. Wong 		/* check for valid extent range, including overflow */
23132080a9bSDarrick J. Wong 		if (!xfs_verify_agbext(pag, irec->rm_startblock,
232c4e34172SDarrick J. Wong 					    irec->rm_blockcount))
233c4e34172SDarrick J. Wong 			return __this_address;
234c4e34172SDarrick J. Wong 	}
235c4e34172SDarrick J. Wong 
236c4e34172SDarrick J. Wong 	if (!(xfs_verify_ino(mp, irec->rm_owner) ||
237c4e34172SDarrick J. Wong 	      (irec->rm_owner <= XFS_RMAP_OWN_FS &&
238c4e34172SDarrick J. Wong 	       irec->rm_owner >= XFS_RMAP_OWN_MIN)))
239c4e34172SDarrick J. Wong 		return __this_address;
240c4e34172SDarrick J. Wong 
2417d7d6d2fSDarrick J. Wong 	/* Check flags. */
2427d7d6d2fSDarrick J. Wong 	is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
2437d7d6d2fSDarrick J. Wong 	is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
2447d7d6d2fSDarrick J. Wong 	is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
2457d7d6d2fSDarrick J. Wong 	is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
2467d7d6d2fSDarrick J. Wong 
2477d7d6d2fSDarrick J. Wong 	if (is_bmbt && irec->rm_offset != 0)
2487d7d6d2fSDarrick J. Wong 		return __this_address;
2497d7d6d2fSDarrick J. Wong 
2507d7d6d2fSDarrick J. Wong 	if (!is_inode && irec->rm_offset != 0)
2517d7d6d2fSDarrick J. Wong 		return __this_address;
2527d7d6d2fSDarrick J. Wong 
2537d7d6d2fSDarrick J. Wong 	if (is_unwritten && (is_bmbt || !is_inode || is_attr))
2547d7d6d2fSDarrick J. Wong 		return __this_address;
2557d7d6d2fSDarrick J. Wong 
2567d7d6d2fSDarrick J. Wong 	if (!is_inode && (is_bmbt || is_unwritten || is_attr))
2577d7d6d2fSDarrick J. Wong 		return __this_address;
2587d7d6d2fSDarrick J. Wong 
259e774b2eaSDarrick J. Wong 	/* Check for a valid fork offset, if applicable. */
260e774b2eaSDarrick J. Wong 	if (is_inode && !is_bmbt &&
261e774b2eaSDarrick J. Wong 	    !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
262e774b2eaSDarrick J. Wong 		return __this_address;
263e774b2eaSDarrick J. Wong 
264c4e34172SDarrick J. Wong 	return NULL;
265c4e34172SDarrick J. Wong }
266c4e34172SDarrick J. Wong 
2674787fc80SDarrick J. Wong static inline xfs_failaddr_t
xfs_rmap_check_btrec(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * irec)2684787fc80SDarrick J. Wong xfs_rmap_check_btrec(
2694787fc80SDarrick J. Wong 	struct xfs_btree_cur		*cur,
2704787fc80SDarrick J. Wong 	const struct xfs_rmap_irec	*irec)
2714787fc80SDarrick J. Wong {
2724787fc80SDarrick J. Wong 	if (xfs_btree_is_mem_rmap(cur->bc_ops))
2734787fc80SDarrick J. Wong 		return xfs_rmap_check_irec(cur->bc_mem.pag, irec);
2744787fc80SDarrick J. Wong 	return xfs_rmap_check_irec(cur->bc_ag.pag, irec);
2754787fc80SDarrick J. Wong }
2764787fc80SDarrick J. Wong 
277ee12eaaaSDarrick J. Wong static inline int
xfs_rmap_complain_bad_rec(struct xfs_btree_cur * cur,xfs_failaddr_t fa,const struct xfs_rmap_irec * irec)278ee12eaaaSDarrick J. Wong xfs_rmap_complain_bad_rec(
279ee12eaaaSDarrick J. Wong 	struct xfs_btree_cur		*cur,
280ee12eaaaSDarrick J. Wong 	xfs_failaddr_t			fa,
281ee12eaaaSDarrick J. Wong 	const struct xfs_rmap_irec	*irec)
282ee12eaaaSDarrick J. Wong {
283ee12eaaaSDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
284ee12eaaaSDarrick J. Wong 
2854787fc80SDarrick J. Wong 	if (xfs_btree_is_mem_rmap(cur->bc_ops))
2864787fc80SDarrick J. Wong 		xfs_warn(mp,
2874787fc80SDarrick J. Wong  "In-Memory Reverse Mapping BTree record corruption detected at %pS!", fa);
2884787fc80SDarrick J. Wong 	else
289ee12eaaaSDarrick J. Wong 		xfs_warn(mp,
290ee12eaaaSDarrick J. Wong  "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
291ee12eaaaSDarrick J. Wong 			cur->bc_ag.pag->pag_agno, fa);
292ee12eaaaSDarrick J. Wong 	xfs_warn(mp,
293ee12eaaaSDarrick J. Wong 		"Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
294ee12eaaaSDarrick J. Wong 		irec->rm_owner, irec->rm_flags, irec->rm_startblock,
295ee12eaaaSDarrick J. Wong 		irec->rm_blockcount);
296a78d10f4SDarrick J. Wong 	xfs_btree_mark_sick(cur);
297ee12eaaaSDarrick J. Wong 	return -EFSCORRUPTED;
298ee12eaaaSDarrick J. Wong }
299ee12eaaaSDarrick J. Wong 
3004b8ed677SDarrick J. Wong /*
3014b8ed677SDarrick J. Wong  * Get the data from the pointed-to record.
3024b8ed677SDarrick J. Wong  */
3034b8ed677SDarrick J. Wong int
xfs_rmap_get_rec(struct xfs_btree_cur * cur,struct xfs_rmap_irec * irec,int * stat)3044b8ed677SDarrick J. Wong xfs_rmap_get_rec(
3054b8ed677SDarrick J. Wong 	struct xfs_btree_cur	*cur,
3064b8ed677SDarrick J. Wong 	struct xfs_rmap_irec	*irec,
3074b8ed677SDarrick J. Wong 	int			*stat)
3084b8ed677SDarrick J. Wong {
3094b8ed677SDarrick J. Wong 	union xfs_btree_rec	*rec;
310c4e34172SDarrick J. Wong 	xfs_failaddr_t		fa;
3114b8ed677SDarrick J. Wong 	int			error;
3124b8ed677SDarrick J. Wong 
3134b8ed677SDarrick J. Wong 	error = xfs_btree_get_rec(cur, &rec, stat);
3144b8ed677SDarrick J. Wong 	if (error || !*stat)
3154b8ed677SDarrick J. Wong 		return error;
3164b8ed677SDarrick J. Wong 
317c4e34172SDarrick J. Wong 	fa = xfs_rmap_btrec_to_irec(rec, irec);
318c4e34172SDarrick J. Wong 	if (!fa)
3194787fc80SDarrick J. Wong 		fa = xfs_rmap_check_btrec(cur, irec);
320c4e34172SDarrick J. Wong 	if (fa)
321ee12eaaaSDarrick J. Wong 		return xfs_rmap_complain_bad_rec(cur, fa, irec);
3229e6c08d4SDave Chinner 
3239e6c08d4SDave Chinner 	return 0;
3244b8ed677SDarrick J. Wong }
3254b8ed677SDarrick J. Wong 
326ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info {
327ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec	high;
328ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec	*irec;
329ceeb9c83SDarrick J. Wong };
330ceeb9c83SDarrick J. Wong 
331ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */
332ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_find_left_neighbor_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)333ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper(
334ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur		*cur,
335159eb69dSDarrick J. Wong 	const struct xfs_rmap_irec	*rec,
336ceeb9c83SDarrick J. Wong 	void				*priv)
337ceeb9c83SDarrick J. Wong {
338ceeb9c83SDarrick J. Wong 	struct xfs_find_left_neighbor_info	*info = priv;
339ceeb9c83SDarrick J. Wong 
34047492ed1SDarrick J. Wong 	trace_xfs_rmap_find_left_neighbor_candidate(cur, rec->rm_startblock,
341ceeb9c83SDarrick J. Wong 			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
342ceeb9c83SDarrick J. Wong 			rec->rm_flags);
343ceeb9c83SDarrick J. Wong 
344ceeb9c83SDarrick J. Wong 	if (rec->rm_owner != info->high.rm_owner)
34539ee2239SDarrick J. Wong 		return 0;
346ceeb9c83SDarrick J. Wong 	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
347ceeb9c83SDarrick J. Wong 	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
348ceeb9c83SDarrick J. Wong 	    rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
34939ee2239SDarrick J. Wong 		return 0;
350ceeb9c83SDarrick J. Wong 
351ceeb9c83SDarrick J. Wong 	*info->irec = *rec;
352e7ee96dfSDarrick J. Wong 	return -ECANCELED;
353ceeb9c83SDarrick J. Wong }
354ceeb9c83SDarrick J. Wong 
355ceeb9c83SDarrick J. Wong /*
356ceeb9c83SDarrick J. Wong  * Find the record to the left of the given extent, being careful only to
357ceeb9c83SDarrick J. Wong  * return a match with the same owner and adjacent physical and logical
358ceeb9c83SDarrick J. Wong  * block ranges.
359ceeb9c83SDarrick J. Wong  */
3601edf8056SDarrick J. Wong STATIC int
xfs_rmap_find_left_neighbor(struct xfs_btree_cur * cur,xfs_agblock_t bno,uint64_t owner,uint64_t offset,unsigned int flags,struct xfs_rmap_irec * irec,int * stat)361ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor(
362ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur	*cur,
363ceeb9c83SDarrick J. Wong 	xfs_agblock_t		bno,
364ceeb9c83SDarrick J. Wong 	uint64_t		owner,
365ceeb9c83SDarrick J. Wong 	uint64_t		offset,
366ceeb9c83SDarrick J. Wong 	unsigned int		flags,
367ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec	*irec,
368ceeb9c83SDarrick J. Wong 	int			*stat)
369ceeb9c83SDarrick J. Wong {
370ceeb9c83SDarrick J. Wong 	struct xfs_find_left_neighbor_info	info;
3711edf8056SDarrick J. Wong 	int			found = 0;
372ceeb9c83SDarrick J. Wong 	int			error;
373ceeb9c83SDarrick J. Wong 
374ceeb9c83SDarrick J. Wong 	*stat = 0;
375ceeb9c83SDarrick J. Wong 	if (bno == 0)
376ceeb9c83SDarrick J. Wong 		return 0;
377ceeb9c83SDarrick J. Wong 	info.high.rm_startblock = bno - 1;
378ceeb9c83SDarrick J. Wong 	info.high.rm_owner = owner;
379ceeb9c83SDarrick J. Wong 	if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
380ceeb9c83SDarrick J. Wong 	    !(flags & XFS_RMAP_BMBT_BLOCK)) {
381ceeb9c83SDarrick J. Wong 		if (offset == 0)
382ceeb9c83SDarrick J. Wong 			return 0;
383ceeb9c83SDarrick J. Wong 		info.high.rm_offset = offset - 1;
384ceeb9c83SDarrick J. Wong 	} else
385ceeb9c83SDarrick J. Wong 		info.high.rm_offset = 0;
386ceeb9c83SDarrick J. Wong 	info.high.rm_flags = flags;
387ceeb9c83SDarrick J. Wong 	info.high.rm_blockcount = 0;
388ceeb9c83SDarrick J. Wong 	info.irec = irec;
389ceeb9c83SDarrick J. Wong 
39047492ed1SDarrick J. Wong 	trace_xfs_rmap_find_left_neighbor_query(cur, bno, 0, owner, offset,
39147492ed1SDarrick J. Wong 			flags);
392ceeb9c83SDarrick J. Wong 
3931edf8056SDarrick J. Wong 	/*
3941edf8056SDarrick J. Wong 	 * Historically, we always used the range query to walk every reverse
3951edf8056SDarrick J. Wong 	 * mapping that could possibly overlap the key that the caller asked
3961edf8056SDarrick J. Wong 	 * for, and filter out the ones that don't.  That is very slow when
3971edf8056SDarrick J. Wong 	 * there are a lot of records.
3981edf8056SDarrick J. Wong 	 *
3991edf8056SDarrick J. Wong 	 * However, there are two scenarios where the classic btree search can
4001edf8056SDarrick J. Wong 	 * produce correct results -- if the index contains a record that is an
4011edf8056SDarrick J. Wong 	 * exact match for the lookup key; and if there are no other records
4021edf8056SDarrick J. Wong 	 * between the record we want and the key we supplied.
4031edf8056SDarrick J. Wong 	 *
4041edf8056SDarrick J. Wong 	 * As an optimization, try a non-overlapped lookup first.  This makes
4051edf8056SDarrick J. Wong 	 * extent conversion and remap operations run a bit faster if the
4061edf8056SDarrick J. Wong 	 * physical extents aren't being shared.  If we don't find what we
4071edf8056SDarrick J. Wong 	 * want, we fall back to the overlapped query.
4081edf8056SDarrick J. Wong 	 */
4091edf8056SDarrick J. Wong 	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
4101edf8056SDarrick J. Wong 			&found);
4111edf8056SDarrick J. Wong 	if (error)
4121edf8056SDarrick J. Wong 		return error;
4131edf8056SDarrick J. Wong 	if (found)
4141edf8056SDarrick J. Wong 		error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
4151edf8056SDarrick J. Wong 	if (!error)
416ceeb9c83SDarrick J. Wong 		error = xfs_rmap_query_range(cur, &info.high, &info.high,
417ceeb9c83SDarrick J. Wong 				xfs_rmap_find_left_neighbor_helper, &info);
4181edf8056SDarrick J. Wong 	if (error != -ECANCELED)
4191edf8056SDarrick J. Wong 		return error;
4201edf8056SDarrick J. Wong 
4211edf8056SDarrick J. Wong 	*stat = 1;
42247492ed1SDarrick J. Wong 	trace_xfs_rmap_find_left_neighbor_result(cur, irec->rm_startblock,
4231edf8056SDarrick J. Wong 			irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
4241edf8056SDarrick J. Wong 			irec->rm_flags);
4251edf8056SDarrick J. Wong 	return 0;
426ceeb9c83SDarrick J. Wong }
427ceeb9c83SDarrick J. Wong 
428ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */
429ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_lookup_le_range_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)430ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper(
431ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur		*cur,
432159eb69dSDarrick J. Wong 	const struct xfs_rmap_irec	*rec,
433ceeb9c83SDarrick J. Wong 	void				*priv)
434ceeb9c83SDarrick J. Wong {
435ceeb9c83SDarrick J. Wong 	struct xfs_find_left_neighbor_info	*info = priv;
436ceeb9c83SDarrick J. Wong 
43747492ed1SDarrick J. Wong 	trace_xfs_rmap_lookup_le_range_candidate(cur, rec->rm_startblock,
438ceeb9c83SDarrick J. Wong 			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
439ceeb9c83SDarrick J. Wong 			rec->rm_flags);
440ceeb9c83SDarrick J. Wong 
441ceeb9c83SDarrick J. Wong 	if (rec->rm_owner != info->high.rm_owner)
44239ee2239SDarrick J. Wong 		return 0;
443ceeb9c83SDarrick J. Wong 	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
444ceeb9c83SDarrick J. Wong 	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
445ceeb9c83SDarrick J. Wong 	    (rec->rm_offset > info->high.rm_offset ||
446ceeb9c83SDarrick J. Wong 	     rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
44739ee2239SDarrick J. Wong 		return 0;
448ceeb9c83SDarrick J. Wong 
449ceeb9c83SDarrick J. Wong 	*info->irec = *rec;
450e7ee96dfSDarrick J. Wong 	return -ECANCELED;
451ceeb9c83SDarrick J. Wong }
452ceeb9c83SDarrick J. Wong 
453ceeb9c83SDarrick J. Wong /*
454ceeb9c83SDarrick J. Wong  * Find the record to the left of the given extent, being careful only to
455ceeb9c83SDarrick J. Wong  * return a match with the same owner and overlapping physical and logical
456ceeb9c83SDarrick J. Wong  * block ranges.  This is the overlapping-interval version of
457ceeb9c83SDarrick J. Wong  * xfs_rmap_lookup_le.
458ceeb9c83SDarrick J. Wong  */
459ceeb9c83SDarrick J. Wong int
xfs_rmap_lookup_le_range(struct xfs_btree_cur * cur,xfs_agblock_t bno,uint64_t owner,uint64_t offset,unsigned int flags,struct xfs_rmap_irec * irec,int * stat)460ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range(
461ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur	*cur,
462ceeb9c83SDarrick J. Wong 	xfs_agblock_t		bno,
463ceeb9c83SDarrick J. Wong 	uint64_t		owner,
464ceeb9c83SDarrick J. Wong 	uint64_t		offset,
465ceeb9c83SDarrick J. Wong 	unsigned int		flags,
466ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec	*irec,
467ceeb9c83SDarrick J. Wong 	int			*stat)
468ceeb9c83SDarrick J. Wong {
469ceeb9c83SDarrick J. Wong 	struct xfs_find_left_neighbor_info	info;
47075d893d1SDarrick J. Wong 	int			found = 0;
471ceeb9c83SDarrick J. Wong 	int			error;
472ceeb9c83SDarrick J. Wong 
473ceeb9c83SDarrick J. Wong 	info.high.rm_startblock = bno;
474ceeb9c83SDarrick J. Wong 	info.high.rm_owner = owner;
475ceeb9c83SDarrick J. Wong 	if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
476ceeb9c83SDarrick J. Wong 		info.high.rm_offset = offset;
477ceeb9c83SDarrick J. Wong 	else
478ceeb9c83SDarrick J. Wong 		info.high.rm_offset = 0;
479ceeb9c83SDarrick J. Wong 	info.high.rm_flags = flags;
480ceeb9c83SDarrick J. Wong 	info.high.rm_blockcount = 0;
481ceeb9c83SDarrick J. Wong 	*stat = 0;
482ceeb9c83SDarrick J. Wong 	info.irec = irec;
483ceeb9c83SDarrick J. Wong 
48447492ed1SDarrick J. Wong 	trace_xfs_rmap_lookup_le_range(cur, bno, 0, owner, offset, flags);
48575d893d1SDarrick J. Wong 
48675d893d1SDarrick J. Wong 	/*
48775d893d1SDarrick J. Wong 	 * Historically, we always used the range query to walk every reverse
48875d893d1SDarrick J. Wong 	 * mapping that could possibly overlap the key that the caller asked
48975d893d1SDarrick J. Wong 	 * for, and filter out the ones that don't.  That is very slow when
49075d893d1SDarrick J. Wong 	 * there are a lot of records.
49175d893d1SDarrick J. Wong 	 *
49275d893d1SDarrick J. Wong 	 * However, there are two scenarios where the classic btree search can
49375d893d1SDarrick J. Wong 	 * produce correct results -- if the index contains a record that is an
49475d893d1SDarrick J. Wong 	 * exact match for the lookup key; and if there are no other records
49575d893d1SDarrick J. Wong 	 * between the record we want and the key we supplied.
49675d893d1SDarrick J. Wong 	 *
49775d893d1SDarrick J. Wong 	 * As an optimization, try a non-overlapped lookup first.  This makes
49875d893d1SDarrick J. Wong 	 * scrub run much faster on most filesystems because bmbt records are
49975d893d1SDarrick J. Wong 	 * usually an exact match for rmap records.  If we don't find what we
50075d893d1SDarrick J. Wong 	 * want, we fall back to the overlapped query.
50175d893d1SDarrick J. Wong 	 */
50275d893d1SDarrick J. Wong 	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
50375d893d1SDarrick J. Wong 			&found);
50475d893d1SDarrick J. Wong 	if (error)
50575d893d1SDarrick J. Wong 		return error;
50675d893d1SDarrick J. Wong 	if (found)
50775d893d1SDarrick J. Wong 		error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
50875d893d1SDarrick J. Wong 	if (!error)
509ceeb9c83SDarrick J. Wong 		error = xfs_rmap_query_range(cur, &info.high, &info.high,
510ceeb9c83SDarrick J. Wong 				xfs_rmap_lookup_le_range_helper, &info);
51175d893d1SDarrick J. Wong 	if (error != -ECANCELED)
51275d893d1SDarrick J. Wong 		return error;
51375d893d1SDarrick J. Wong 
51475d893d1SDarrick J. Wong 	*stat = 1;
51547492ed1SDarrick J. Wong 	trace_xfs_rmap_lookup_le_range_result(cur, irec->rm_startblock,
51675d893d1SDarrick J. Wong 			irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
51775d893d1SDarrick J. Wong 			irec->rm_flags);
51875d893d1SDarrick J. Wong 	return 0;
519ceeb9c83SDarrick J. Wong }
520ceeb9c83SDarrick J. Wong 
521f922cd90SDarrick J. Wong /*
52268c58e9bSDarrick J. Wong  * Perform all the relevant owner checks for a removal op.  If we're doing an
52368c58e9bSDarrick J. Wong  * unknown-owner removal then we have no owner information to check.
52468c58e9bSDarrick J. Wong  */
52568c58e9bSDarrick J. Wong static int
xfs_rmap_free_check_owner(struct xfs_btree_cur * cur,uint64_t ltoff,struct xfs_rmap_irec * rec,xfs_filblks_t len,uint64_t owner,uint64_t offset,unsigned int flags)52668c58e9bSDarrick J. Wong xfs_rmap_free_check_owner(
527989d5ec3SDarrick J. Wong 	struct xfs_btree_cur	*cur,
52868c58e9bSDarrick J. Wong 	uint64_t		ltoff,
52968c58e9bSDarrick J. Wong 	struct xfs_rmap_irec	*rec,
53068c58e9bSDarrick J. Wong 	xfs_filblks_t		len,
53168c58e9bSDarrick J. Wong 	uint64_t		owner,
53268c58e9bSDarrick J. Wong 	uint64_t		offset,
53368c58e9bSDarrick J. Wong 	unsigned int		flags)
53468c58e9bSDarrick J. Wong {
535989d5ec3SDarrick J. Wong 	struct xfs_mount	*mp = cur->bc_mp;
53668c58e9bSDarrick J. Wong 	int			error = 0;
53768c58e9bSDarrick J. Wong 
53868c58e9bSDarrick J. Wong 	if (owner == XFS_RMAP_OWN_UNKNOWN)
53968c58e9bSDarrick J. Wong 		return 0;
54068c58e9bSDarrick J. Wong 
54168c58e9bSDarrick J. Wong 	/* Make sure the unwritten flag matches. */
542f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp,
543f9e03706SDarrick J. Wong 			   (flags & XFS_RMAP_UNWRITTEN) !=
544f9e03706SDarrick J. Wong 			   (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
545989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
546f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
547f9e03706SDarrick J. Wong 		goto out;
548f9e03706SDarrick J. Wong 	}
54968c58e9bSDarrick J. Wong 
55068c58e9bSDarrick J. Wong 	/* Make sure the owner matches what we expect to find in the tree. */
551f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
552989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
553f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
554f9e03706SDarrick J. Wong 		goto out;
555f9e03706SDarrick J. Wong 	}
55668c58e9bSDarrick J. Wong 
55768c58e9bSDarrick J. Wong 	/* Check the offset, if necessary. */
55868c58e9bSDarrick J. Wong 	if (XFS_RMAP_NON_INODE_OWNER(owner))
55968c58e9bSDarrick J. Wong 		goto out;
56068c58e9bSDarrick J. Wong 
56168c58e9bSDarrick J. Wong 	if (flags & XFS_RMAP_BMBT_BLOCK) {
562f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp,
563f9e03706SDarrick J. Wong 				   !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
564989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
565f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
566f9e03706SDarrick J. Wong 			goto out;
567f9e03706SDarrick J. Wong 		}
56868c58e9bSDarrick J. Wong 	} else {
569f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
570989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
571f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
572f9e03706SDarrick J. Wong 			goto out;
573f9e03706SDarrick J. Wong 		}
574f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp,
575f9e03706SDarrick J. Wong 				   offset + len > ltoff + rec->rm_blockcount)) {
576989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
577f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
578f9e03706SDarrick J. Wong 			goto out;
579f9e03706SDarrick J. Wong 		}
58068c58e9bSDarrick J. Wong 	}
58168c58e9bSDarrick J. Wong 
58268c58e9bSDarrick J. Wong out:
58368c58e9bSDarrick J. Wong 	return error;
58468c58e9bSDarrick J. Wong }
58568c58e9bSDarrick J. Wong 
58668c58e9bSDarrick J. Wong /*
587f922cd90SDarrick J. Wong  * Find the extent in the rmap btree and remove it.
588f922cd90SDarrick J. Wong  *
589f922cd90SDarrick J. Wong  * The record we find should always be an exact match for the extent that we're
590f922cd90SDarrick J. Wong  * looking for, since we insert them into the btree without modification.
591f922cd90SDarrick J. Wong  *
592f922cd90SDarrick J. Wong  * Special Case #1: when growing the filesystem, we "free" an extent when
593f922cd90SDarrick J. Wong  * growing the last AG. This extent is new space and so it is not tracked as
594f922cd90SDarrick J. Wong  * used space in the btree. The growfs code will pass in an owner of
595f922cd90SDarrick J. Wong  * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
596f922cd90SDarrick J. Wong  * extent. We verify that - the extent lookup result in a record that does not
597f922cd90SDarrick J. Wong  * overlap.
598f922cd90SDarrick J. Wong  *
599f922cd90SDarrick J. Wong  * Special Case #2: EFIs do not record the owner of the extent, so when
600f922cd90SDarrick J. Wong  * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
601f922cd90SDarrick J. Wong  * btree to ignore the owner (i.e. wildcard match) so we don't trigger
602f922cd90SDarrick J. Wong  * corruption checks during log recovery.
603f922cd90SDarrick J. Wong  */
604f922cd90SDarrick J. Wong STATIC int
xfs_rmap_unmap(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)605f922cd90SDarrick J. Wong xfs_rmap_unmap(
606f922cd90SDarrick J. Wong 	struct xfs_btree_cur		*cur,
607f922cd90SDarrick J. Wong 	xfs_agblock_t			bno,
608f922cd90SDarrick J. Wong 	xfs_extlen_t			len,
609f922cd90SDarrick J. Wong 	bool				unwritten,
61066e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
611f922cd90SDarrick J. Wong {
612f922cd90SDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
613f922cd90SDarrick J. Wong 	struct xfs_rmap_irec		ltrec;
614f922cd90SDarrick J. Wong 	uint64_t			ltoff;
615f922cd90SDarrick J. Wong 	int				error = 0;
616f922cd90SDarrick J. Wong 	int				i;
617f922cd90SDarrick J. Wong 	uint64_t			owner;
618f922cd90SDarrick J. Wong 	uint64_t			offset;
619f922cd90SDarrick J. Wong 	unsigned int			flags;
620f922cd90SDarrick J. Wong 	bool				ignore_off;
621f922cd90SDarrick J. Wong 
622f922cd90SDarrick J. Wong 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
623f922cd90SDarrick J. Wong 	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
624f922cd90SDarrick J. Wong 			(flags & XFS_RMAP_BMBT_BLOCK);
625f922cd90SDarrick J. Wong 	if (unwritten)
626f922cd90SDarrick J. Wong 		flags |= XFS_RMAP_UNWRITTEN;
62747492ed1SDarrick J. Wong 	trace_xfs_rmap_unmap(cur, bno, len, unwritten, oinfo);
628f922cd90SDarrick J. Wong 
629f922cd90SDarrick J. Wong 	/*
630f922cd90SDarrick J. Wong 	 * We should always have a left record because there's a static record
631f922cd90SDarrick J. Wong 	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
632f922cd90SDarrick J. Wong 	 * will not ever be removed from the tree.
633f922cd90SDarrick J. Wong 	 */
6345b7ca8b3SDarrick J. Wong 	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec, &i);
635f922cd90SDarrick J. Wong 	if (error)
636f922cd90SDarrick J. Wong 		goto out_error;
637f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, i != 1)) {
638989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
639f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
640f9e03706SDarrick J. Wong 		goto out_error;
641f9e03706SDarrick J. Wong 	}
642f922cd90SDarrick J. Wong 
64347492ed1SDarrick J. Wong 	trace_xfs_rmap_lookup_le_range_result(cur, ltrec.rm_startblock,
64447492ed1SDarrick J. Wong 			ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset,
64547492ed1SDarrick J. Wong 			ltrec.rm_flags);
646f922cd90SDarrick J. Wong 	ltoff = ltrec.rm_offset;
647f922cd90SDarrick J. Wong 
648f922cd90SDarrick J. Wong 	/*
649f922cd90SDarrick J. Wong 	 * For growfs, the incoming extent must be beyond the left record we
650f922cd90SDarrick J. Wong 	 * just found as it is new space and won't be used by anyone. This is
651f922cd90SDarrick J. Wong 	 * just a corruption check as we don't actually do anything with this
652f922cd90SDarrick J. Wong 	 * extent.  Note that we need to use >= instead of > because it might
653f922cd90SDarrick J. Wong 	 * be the case that the "left" extent goes all the way to EOFS.
654f922cd90SDarrick J. Wong 	 */
655f922cd90SDarrick J. Wong 	if (owner == XFS_RMAP_OWN_NULL) {
656f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp,
657f9e03706SDarrick J. Wong 				   bno <
658f9e03706SDarrick J. Wong 				   ltrec.rm_startblock + ltrec.rm_blockcount)) {
659989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
660f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
661f9e03706SDarrick J. Wong 			goto out_error;
662f9e03706SDarrick J. Wong 		}
663f922cd90SDarrick J. Wong 		goto out_done;
664f922cd90SDarrick J. Wong 	}
665f922cd90SDarrick J. Wong 
66633df3a9cSDarrick J. Wong 	/*
66733df3a9cSDarrick J. Wong 	 * If we're doing an unknown-owner removal for EFI recovery, we expect
66833df3a9cSDarrick J. Wong 	 * to find the full range in the rmapbt or nothing at all.  If we
66933df3a9cSDarrick J. Wong 	 * don't find any rmaps overlapping either end of the range, we're
67033df3a9cSDarrick J. Wong 	 * done.  Hopefully this means that the EFI creator already queued
67133df3a9cSDarrick J. Wong 	 * (and finished) a RUI to remove the rmap.
67233df3a9cSDarrick J. Wong 	 */
67333df3a9cSDarrick J. Wong 	if (owner == XFS_RMAP_OWN_UNKNOWN &&
67433df3a9cSDarrick J. Wong 	    ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
67533df3a9cSDarrick J. Wong 		struct xfs_rmap_irec    rtrec;
67633df3a9cSDarrick J. Wong 
67733df3a9cSDarrick J. Wong 		error = xfs_btree_increment(cur, 0, &i);
67833df3a9cSDarrick J. Wong 		if (error)
67933df3a9cSDarrick J. Wong 			goto out_error;
68033df3a9cSDarrick J. Wong 		if (i == 0)
68133df3a9cSDarrick J. Wong 			goto out_done;
68233df3a9cSDarrick J. Wong 		error = xfs_rmap_get_rec(cur, &rtrec, &i);
68333df3a9cSDarrick J. Wong 		if (error)
68433df3a9cSDarrick J. Wong 			goto out_error;
685f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
686989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
687f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
688f9e03706SDarrick J. Wong 			goto out_error;
689f9e03706SDarrick J. Wong 		}
69033df3a9cSDarrick J. Wong 		if (rtrec.rm_startblock >= bno + len)
69133df3a9cSDarrick J. Wong 			goto out_done;
69233df3a9cSDarrick J. Wong 	}
69333df3a9cSDarrick J. Wong 
694f922cd90SDarrick J. Wong 	/* Make sure the extent we found covers the entire freeing range. */
695f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp,
696f9e03706SDarrick J. Wong 			   ltrec.rm_startblock > bno ||
697f9e03706SDarrick J. Wong 			   ltrec.rm_startblock + ltrec.rm_blockcount <
698f9e03706SDarrick J. Wong 			   bno + len)) {
699989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
700f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
701f9e03706SDarrick J. Wong 		goto out_error;
702f9e03706SDarrick J. Wong 	}
703f922cd90SDarrick J. Wong 
70468c58e9bSDarrick J. Wong 	/* Check owner information. */
705989d5ec3SDarrick J. Wong 	error = xfs_rmap_free_check_owner(cur, ltoff, &ltrec, len, owner,
70668c58e9bSDarrick J. Wong 			offset, flags);
70768c58e9bSDarrick J. Wong 	if (error)
70868c58e9bSDarrick J. Wong 		goto out_error;
709f922cd90SDarrick J. Wong 
710f922cd90SDarrick J. Wong 	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
711f922cd90SDarrick J. Wong 		/* exact match, simply remove the record from rmap tree */
71247492ed1SDarrick J. Wong 		trace_xfs_rmap_delete(cur, ltrec.rm_startblock,
71347492ed1SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
71447492ed1SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags);
715f922cd90SDarrick J. Wong 		error = xfs_btree_delete(cur, &i);
716f922cd90SDarrick J. Wong 		if (error)
717f922cd90SDarrick J. Wong 			goto out_error;
718f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
719989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
720f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
721f9e03706SDarrick J. Wong 			goto out_error;
722f9e03706SDarrick J. Wong 		}
723f922cd90SDarrick J. Wong 	} else if (ltrec.rm_startblock == bno) {
724f922cd90SDarrick J. Wong 		/*
725f922cd90SDarrick J. Wong 		 * overlap left hand side of extent: move the start, trim the
726f922cd90SDarrick J. Wong 		 * length and update the current record.
727f922cd90SDarrick J. Wong 		 *
728f922cd90SDarrick J. Wong 		 *       ltbno                ltlen
729f922cd90SDarrick J. Wong 		 * Orig:    |oooooooooooooooooooo|
730f922cd90SDarrick J. Wong 		 * Freeing: |fffffffff|
731f922cd90SDarrick J. Wong 		 * Result:            |rrrrrrrrrr|
732f922cd90SDarrick J. Wong 		 *         bno       len
733f922cd90SDarrick J. Wong 		 */
734f922cd90SDarrick J. Wong 		ltrec.rm_startblock += len;
735f922cd90SDarrick J. Wong 		ltrec.rm_blockcount -= len;
736f922cd90SDarrick J. Wong 		if (!ignore_off)
737f922cd90SDarrick J. Wong 			ltrec.rm_offset += len;
738f922cd90SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
739f922cd90SDarrick J. Wong 		if (error)
740f922cd90SDarrick J. Wong 			goto out_error;
741f922cd90SDarrick J. Wong 	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
742f922cd90SDarrick J. Wong 		/*
743f922cd90SDarrick J. Wong 		 * overlap right hand side of extent: trim the length and update
744f922cd90SDarrick J. Wong 		 * the current record.
745f922cd90SDarrick J. Wong 		 *
746f922cd90SDarrick J. Wong 		 *       ltbno                ltlen
747f922cd90SDarrick J. Wong 		 * Orig:    |oooooooooooooooooooo|
748f922cd90SDarrick J. Wong 		 * Freeing:            |fffffffff|
749f922cd90SDarrick J. Wong 		 * Result:  |rrrrrrrrrr|
750f922cd90SDarrick J. Wong 		 *                    bno       len
751f922cd90SDarrick J. Wong 		 */
752f922cd90SDarrick J. Wong 		ltrec.rm_blockcount -= len;
753f922cd90SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
754f922cd90SDarrick J. Wong 		if (error)
755f922cd90SDarrick J. Wong 			goto out_error;
756f922cd90SDarrick J. Wong 	} else {
757f922cd90SDarrick J. Wong 
758f922cd90SDarrick J. Wong 		/*
759f922cd90SDarrick J. Wong 		 * overlap middle of extent: trim the length of the existing
760f922cd90SDarrick J. Wong 		 * record to the length of the new left-extent size, increment
761f922cd90SDarrick J. Wong 		 * the insertion position so we can insert a new record
762f922cd90SDarrick J. Wong 		 * containing the remaining right-extent space.
763f922cd90SDarrick J. Wong 		 *
764f922cd90SDarrick J. Wong 		 *       ltbno                ltlen
765f922cd90SDarrick J. Wong 		 * Orig:    |oooooooooooooooooooo|
766f922cd90SDarrick J. Wong 		 * Freeing:       |fffffffff|
767f922cd90SDarrick J. Wong 		 * Result:  |rrrrr|         |rrrr|
768f922cd90SDarrick J. Wong 		 *               bno       len
769f922cd90SDarrick J. Wong 		 */
770f922cd90SDarrick J. Wong 		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
771f922cd90SDarrick J. Wong 
772f922cd90SDarrick J. Wong 		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
773f922cd90SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
774f922cd90SDarrick J. Wong 		if (error)
775f922cd90SDarrick J. Wong 			goto out_error;
776f922cd90SDarrick J. Wong 
777f922cd90SDarrick J. Wong 		error = xfs_btree_increment(cur, 0, &i);
778f922cd90SDarrick J. Wong 		if (error)
779f922cd90SDarrick J. Wong 			goto out_error;
780f922cd90SDarrick J. Wong 
781f922cd90SDarrick J. Wong 		cur->bc_rec.r.rm_startblock = bno + len;
782f922cd90SDarrick J. Wong 		cur->bc_rec.r.rm_blockcount = orig_len - len -
783f922cd90SDarrick J. Wong 						     ltrec.rm_blockcount;
784f922cd90SDarrick J. Wong 		cur->bc_rec.r.rm_owner = ltrec.rm_owner;
785f922cd90SDarrick J. Wong 		if (ignore_off)
786f922cd90SDarrick J. Wong 			cur->bc_rec.r.rm_offset = 0;
787f922cd90SDarrick J. Wong 		else
788f922cd90SDarrick J. Wong 			cur->bc_rec.r.rm_offset = offset + len;
789f922cd90SDarrick J. Wong 		cur->bc_rec.r.rm_flags = flags;
79047492ed1SDarrick J. Wong 		trace_xfs_rmap_insert(cur, cur->bc_rec.r.rm_startblock,
791f922cd90SDarrick J. Wong 				cur->bc_rec.r.rm_blockcount,
792f922cd90SDarrick J. Wong 				cur->bc_rec.r.rm_owner,
793f922cd90SDarrick J. Wong 				cur->bc_rec.r.rm_offset,
794f922cd90SDarrick J. Wong 				cur->bc_rec.r.rm_flags);
795f922cd90SDarrick J. Wong 		error = xfs_btree_insert(cur, &i);
796f922cd90SDarrick J. Wong 		if (error)
797f922cd90SDarrick J. Wong 			goto out_error;
798f922cd90SDarrick J. Wong 	}
799f922cd90SDarrick J. Wong 
800f922cd90SDarrick J. Wong out_done:
80147492ed1SDarrick J. Wong 	trace_xfs_rmap_unmap_done(cur, bno, len, unwritten, oinfo);
802f922cd90SDarrick J. Wong out_error:
803f922cd90SDarrick J. Wong 	if (error)
80471f5a17eSDarrick J. Wong 		trace_xfs_rmap_unmap_error(cur, error, _RET_IP_);
805f922cd90SDarrick J. Wong 	return error;
806f922cd90SDarrick J. Wong }
807f922cd90SDarrick J. Wong 
8087e1b84b2SDarrick J. Wong #ifdef CONFIG_XFS_LIVE_HOOKS
8097e1b84b2SDarrick J. Wong /*
8107e1b84b2SDarrick J. Wong  * Use a static key here to reduce the overhead of rmapbt live updates.  If
8117e1b84b2SDarrick J. Wong  * the compiler supports jump labels, the static branch will be replaced by a
8127e1b84b2SDarrick J. Wong  * nop sled when there are no hook users.  Online fsck is currently the only
8137e1b84b2SDarrick J. Wong  * caller, so this is a reasonable tradeoff.
8147e1b84b2SDarrick J. Wong  *
8157e1b84b2SDarrick J. Wong  * Note: Patching the kernel code requires taking the cpu hotplug lock.  Other
8167e1b84b2SDarrick J. Wong  * parts of the kernel allocate memory with that lock held, which means that
8177e1b84b2SDarrick J. Wong  * XFS callers cannot hold any locks that might be used by memory reclaim or
8187e1b84b2SDarrick J. Wong  * writeback when calling the static_branch_{inc,dec} functions.
8197e1b84b2SDarrick J. Wong  */
8207e1b84b2SDarrick J. Wong DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_rmap_hooks_switch);
8217e1b84b2SDarrick J. Wong 
8227e1b84b2SDarrick J. Wong void
xfs_rmap_hook_disable(void)8237e1b84b2SDarrick J. Wong xfs_rmap_hook_disable(void)
8247e1b84b2SDarrick J. Wong {
8257e1b84b2SDarrick J. Wong 	xfs_hooks_switch_off(&xfs_rmap_hooks_switch);
8267e1b84b2SDarrick J. Wong }
8277e1b84b2SDarrick J. Wong 
8287e1b84b2SDarrick J. Wong void
xfs_rmap_hook_enable(void)8297e1b84b2SDarrick J. Wong xfs_rmap_hook_enable(void)
8307e1b84b2SDarrick J. Wong {
8317e1b84b2SDarrick J. Wong 	xfs_hooks_switch_on(&xfs_rmap_hooks_switch);
8327e1b84b2SDarrick J. Wong }
8337e1b84b2SDarrick J. Wong 
8347e1b84b2SDarrick J. Wong /* Call downstream hooks for a reverse mapping update. */
8357e1b84b2SDarrick J. Wong static inline void
xfs_rmap_update_hook(struct xfs_trans * tp,struct xfs_perag * pag,enum xfs_rmap_intent_type op,xfs_agblock_t startblock,xfs_extlen_t blockcount,bool unwritten,const struct xfs_owner_info * oinfo)8367e1b84b2SDarrick J. Wong xfs_rmap_update_hook(
8377e1b84b2SDarrick J. Wong 	struct xfs_trans		*tp,
8387e1b84b2SDarrick J. Wong 	struct xfs_perag		*pag,
8397e1b84b2SDarrick J. Wong 	enum xfs_rmap_intent_type	op,
8407e1b84b2SDarrick J. Wong 	xfs_agblock_t			startblock,
8417e1b84b2SDarrick J. Wong 	xfs_extlen_t			blockcount,
8427e1b84b2SDarrick J. Wong 	bool				unwritten,
8437e1b84b2SDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
8447e1b84b2SDarrick J. Wong {
8457e1b84b2SDarrick J. Wong 	if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch)) {
8467e1b84b2SDarrick J. Wong 		struct xfs_rmap_update_params	p = {
8477e1b84b2SDarrick J. Wong 			.startblock	= startblock,
8487e1b84b2SDarrick J. Wong 			.blockcount	= blockcount,
8497e1b84b2SDarrick J. Wong 			.unwritten	= unwritten,
8507e1b84b2SDarrick J. Wong 			.oinfo		= *oinfo, /* struct copy */
8517e1b84b2SDarrick J. Wong 		};
8527e1b84b2SDarrick J. Wong 
8537e1b84b2SDarrick J. Wong 		if (pag)
8547e1b84b2SDarrick J. Wong 			xfs_hooks_call(&pag->pag_rmap_update_hooks, op, &p);
8557e1b84b2SDarrick J. Wong 	}
8567e1b84b2SDarrick J. Wong }
8577e1b84b2SDarrick J. Wong 
8587e1b84b2SDarrick J. Wong /* Call the specified function during a reverse mapping update. */
8597e1b84b2SDarrick J. Wong int
xfs_rmap_hook_add(struct xfs_perag * pag,struct xfs_rmap_hook * hook)8607e1b84b2SDarrick J. Wong xfs_rmap_hook_add(
8617e1b84b2SDarrick J. Wong 	struct xfs_perag	*pag,
8627e1b84b2SDarrick J. Wong 	struct xfs_rmap_hook	*hook)
8637e1b84b2SDarrick J. Wong {
8647e1b84b2SDarrick J. Wong 	return xfs_hooks_add(&pag->pag_rmap_update_hooks, &hook->rmap_hook);
8657e1b84b2SDarrick J. Wong }
8667e1b84b2SDarrick J. Wong 
8677e1b84b2SDarrick J. Wong /* Stop calling the specified function during a reverse mapping update. */
8687e1b84b2SDarrick J. Wong void
xfs_rmap_hook_del(struct xfs_perag * pag,struct xfs_rmap_hook * hook)8697e1b84b2SDarrick J. Wong xfs_rmap_hook_del(
8707e1b84b2SDarrick J. Wong 	struct xfs_perag	*pag,
8717e1b84b2SDarrick J. Wong 	struct xfs_rmap_hook	*hook)
8727e1b84b2SDarrick J. Wong {
8737e1b84b2SDarrick J. Wong 	xfs_hooks_del(&pag->pag_rmap_update_hooks, &hook->rmap_hook);
8747e1b84b2SDarrick J. Wong }
8757e1b84b2SDarrick J. Wong 
8767e1b84b2SDarrick J. Wong /* Configure rmap update hook functions. */
8777e1b84b2SDarrick J. Wong void
xfs_rmap_hook_setup(struct xfs_rmap_hook * hook,notifier_fn_t mod_fn)8787e1b84b2SDarrick J. Wong xfs_rmap_hook_setup(
8797e1b84b2SDarrick J. Wong 	struct xfs_rmap_hook	*hook,
8807e1b84b2SDarrick J. Wong 	notifier_fn_t		mod_fn)
8817e1b84b2SDarrick J. Wong {
8827e1b84b2SDarrick J. Wong 	xfs_hook_setup(&hook->rmap_hook, mod_fn);
8837e1b84b2SDarrick J. Wong }
8847e1b84b2SDarrick J. Wong #else
8857e1b84b2SDarrick J. Wong # define xfs_rmap_update_hook(t, p, o, s, b, u, oi)	do { } while (0)
8867e1b84b2SDarrick J. Wong #endif /* CONFIG_XFS_LIVE_HOOKS */
8877e1b84b2SDarrick J. Wong 
888f922cd90SDarrick J. Wong /*
889f922cd90SDarrick J. Wong  * Remove a reference to an extent in the rmap btree.
890f922cd90SDarrick J. Wong  */
891673930c3SDarrick J. Wong int
xfs_rmap_free(struct xfs_trans * tp,struct xfs_buf * agbp,struct xfs_perag * pag,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo)892673930c3SDarrick J. Wong xfs_rmap_free(
893673930c3SDarrick J. Wong 	struct xfs_trans		*tp,
894673930c3SDarrick J. Wong 	struct xfs_buf			*agbp,
895fa9c3c19SDave Chinner 	struct xfs_perag		*pag,
896673930c3SDarrick J. Wong 	xfs_agblock_t			bno,
897673930c3SDarrick J. Wong 	xfs_extlen_t			len,
89866e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
899673930c3SDarrick J. Wong {
900673930c3SDarrick J. Wong 	struct xfs_mount		*mp = tp->t_mountp;
901f922cd90SDarrick J. Wong 	struct xfs_btree_cur		*cur;
902f922cd90SDarrick J. Wong 	int				error;
903673930c3SDarrick J. Wong 
90438c26bfdSDave Chinner 	if (!xfs_has_rmapbt(mp))
905673930c3SDarrick J. Wong 		return 0;
906673930c3SDarrick J. Wong 
907fa9c3c19SDave Chinner 	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
9087e1b84b2SDarrick J. Wong 	xfs_rmap_update_hook(tp, pag, XFS_RMAP_UNMAP, bno, len, false, oinfo);
909f922cd90SDarrick J. Wong 	error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
910f922cd90SDarrick J. Wong 
9110b04b6b8SDarrick J. Wong 	xfs_btree_del_cursor(cur, error);
912673930c3SDarrick J. Wong 	return error;
913673930c3SDarrick J. Wong }
914673930c3SDarrick J. Wong 
9150a1b0b38SDarrick J. Wong /*
9160a1b0b38SDarrick J. Wong  * A mergeable rmap must have the same owner and the same values for
9170a1b0b38SDarrick J. Wong  * the unwritten, attr_fork, and bmbt flags.  The startblock and
9180a1b0b38SDarrick J. Wong  * offset are checked separately.
9190a1b0b38SDarrick J. Wong  */
9200a1b0b38SDarrick J. Wong static bool
xfs_rmap_is_mergeable(struct xfs_rmap_irec * irec,uint64_t owner,unsigned int flags)9210a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable(
9220a1b0b38SDarrick J. Wong 	struct xfs_rmap_irec	*irec,
9230a1b0b38SDarrick J. Wong 	uint64_t		owner,
9240a1b0b38SDarrick J. Wong 	unsigned int		flags)
9250a1b0b38SDarrick J. Wong {
9260a1b0b38SDarrick J. Wong 	if (irec->rm_owner == XFS_RMAP_OWN_NULL)
9270a1b0b38SDarrick J. Wong 		return false;
9280a1b0b38SDarrick J. Wong 	if (irec->rm_owner != owner)
9290a1b0b38SDarrick J. Wong 		return false;
9300a1b0b38SDarrick J. Wong 	if ((flags & XFS_RMAP_UNWRITTEN) ^
9310a1b0b38SDarrick J. Wong 	    (irec->rm_flags & XFS_RMAP_UNWRITTEN))
9320a1b0b38SDarrick J. Wong 		return false;
9330a1b0b38SDarrick J. Wong 	if ((flags & XFS_RMAP_ATTR_FORK) ^
9340a1b0b38SDarrick J. Wong 	    (irec->rm_flags & XFS_RMAP_ATTR_FORK))
9350a1b0b38SDarrick J. Wong 		return false;
9360a1b0b38SDarrick J. Wong 	if ((flags & XFS_RMAP_BMBT_BLOCK) ^
9370a1b0b38SDarrick J. Wong 	    (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
9380a1b0b38SDarrick J. Wong 		return false;
9390a1b0b38SDarrick J. Wong 	return true;
9400a1b0b38SDarrick J. Wong }
9410a1b0b38SDarrick J. Wong 
9420a1b0b38SDarrick J. Wong /*
9430a1b0b38SDarrick J. Wong  * When we allocate a new block, the first thing we do is add a reference to
9440a1b0b38SDarrick J. Wong  * the extent in the rmap btree. This takes the form of a [agbno, length,
9450a1b0b38SDarrick J. Wong  * owner, offset] record.  Flags are encoded in the high bits of the offset
9460a1b0b38SDarrick J. Wong  * field.
9470a1b0b38SDarrick J. Wong  */
9480a1b0b38SDarrick J. Wong STATIC int
xfs_rmap_map(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)9490a1b0b38SDarrick J. Wong xfs_rmap_map(
9500a1b0b38SDarrick J. Wong 	struct xfs_btree_cur		*cur,
9510a1b0b38SDarrick J. Wong 	xfs_agblock_t			bno,
9520a1b0b38SDarrick J. Wong 	xfs_extlen_t			len,
9530a1b0b38SDarrick J. Wong 	bool				unwritten,
95466e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
9550a1b0b38SDarrick J. Wong {
9560a1b0b38SDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
9570a1b0b38SDarrick J. Wong 	struct xfs_rmap_irec		ltrec;
9580a1b0b38SDarrick J. Wong 	struct xfs_rmap_irec		gtrec;
9590a1b0b38SDarrick J. Wong 	int				have_gt;
9600a1b0b38SDarrick J. Wong 	int				have_lt;
9610a1b0b38SDarrick J. Wong 	int				error = 0;
9620a1b0b38SDarrick J. Wong 	int				i;
9630a1b0b38SDarrick J. Wong 	uint64_t			owner;
9640a1b0b38SDarrick J. Wong 	uint64_t			offset;
9650a1b0b38SDarrick J. Wong 	unsigned int			flags = 0;
9660a1b0b38SDarrick J. Wong 	bool				ignore_off;
9670a1b0b38SDarrick J. Wong 
9680a1b0b38SDarrick J. Wong 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
9690a1b0b38SDarrick J. Wong 	ASSERT(owner != 0);
9700a1b0b38SDarrick J. Wong 	ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
9710a1b0b38SDarrick J. Wong 			(flags & XFS_RMAP_BMBT_BLOCK);
9720a1b0b38SDarrick J. Wong 	if (unwritten)
9730a1b0b38SDarrick J. Wong 		flags |= XFS_RMAP_UNWRITTEN;
97447492ed1SDarrick J. Wong 	trace_xfs_rmap_map(cur, bno, len, unwritten, oinfo);
97533df3a9cSDarrick J. Wong 	ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
9760a1b0b38SDarrick J. Wong 
9770a1b0b38SDarrick J. Wong 	/*
9780a1b0b38SDarrick J. Wong 	 * For the initial lookup, look for an exact match or the left-adjacent
9790a1b0b38SDarrick J. Wong 	 * record for our insertion point. This will also give us the record for
9800a1b0b38SDarrick J. Wong 	 * start block contiguity tests.
9810a1b0b38SDarrick J. Wong 	 */
9825b7ca8b3SDarrick J. Wong 	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec,
9830a1b0b38SDarrick J. Wong 			&have_lt);
9840a1b0b38SDarrick J. Wong 	if (error)
9850a1b0b38SDarrick J. Wong 		goto out_error;
986fa248de9SDarrick J. Wong 	if (have_lt) {
98747492ed1SDarrick J. Wong 		trace_xfs_rmap_lookup_le_range_result(cur, ltrec.rm_startblock,
9880a1b0b38SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
9890a1b0b38SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags);
9900a1b0b38SDarrick J. Wong 
9910a1b0b38SDarrick J. Wong 		if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
9920a1b0b38SDarrick J. Wong 			have_lt = 0;
993fa248de9SDarrick J. Wong 	}
9940a1b0b38SDarrick J. Wong 
995f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp,
996f9e03706SDarrick J. Wong 			   have_lt != 0 &&
997f9e03706SDarrick J. Wong 			   ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
998989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
999f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
1000f9e03706SDarrick J. Wong 		goto out_error;
1001f9e03706SDarrick J. Wong 	}
10020a1b0b38SDarrick J. Wong 
10030a1b0b38SDarrick J. Wong 	/*
10040a1b0b38SDarrick J. Wong 	 * Increment the cursor to see if we have a right-adjacent record to our
10050a1b0b38SDarrick J. Wong 	 * insertion point. This will give us the record for end block
10060a1b0b38SDarrick J. Wong 	 * contiguity tests.
10070a1b0b38SDarrick J. Wong 	 */
10080a1b0b38SDarrick J. Wong 	error = xfs_btree_increment(cur, 0, &have_gt);
10090a1b0b38SDarrick J. Wong 	if (error)
10100a1b0b38SDarrick J. Wong 		goto out_error;
10110a1b0b38SDarrick J. Wong 	if (have_gt) {
10120a1b0b38SDarrick J. Wong 		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
10130a1b0b38SDarrick J. Wong 		if (error)
10140a1b0b38SDarrick J. Wong 			goto out_error;
1015f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
1016989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1017f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1018f9e03706SDarrick J. Wong 			goto out_error;
1019f9e03706SDarrick J. Wong 		}
1020f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
1021989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1022f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1023f9e03706SDarrick J. Wong 			goto out_error;
1024f9e03706SDarrick J. Wong 		}
102547492ed1SDarrick J. Wong 		trace_xfs_rmap_find_right_neighbor_result(cur,
102647492ed1SDarrick J. Wong 				gtrec.rm_startblock, gtrec.rm_blockcount,
102747492ed1SDarrick J. Wong 				gtrec.rm_owner, gtrec.rm_offset,
102847492ed1SDarrick J. Wong 				gtrec.rm_flags);
10290a1b0b38SDarrick J. Wong 		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
10300a1b0b38SDarrick J. Wong 			have_gt = 0;
10310a1b0b38SDarrick J. Wong 	}
10320a1b0b38SDarrick J. Wong 
10330a1b0b38SDarrick J. Wong 	/*
10340a1b0b38SDarrick J. Wong 	 * Note: cursor currently points one record to the right of ltrec, even
10350a1b0b38SDarrick J. Wong 	 * if there is no record in the tree to the right.
10360a1b0b38SDarrick J. Wong 	 */
10370a1b0b38SDarrick J. Wong 	if (have_lt &&
10380a1b0b38SDarrick J. Wong 	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
10390a1b0b38SDarrick J. Wong 	    (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
10400a1b0b38SDarrick J. Wong 		/*
10410a1b0b38SDarrick J. Wong 		 * left edge contiguous, merge into left record.
10420a1b0b38SDarrick J. Wong 		 *
10430a1b0b38SDarrick J. Wong 		 *       ltbno     ltlen
10440a1b0b38SDarrick J. Wong 		 * orig:   |ooooooooo|
10450a1b0b38SDarrick J. Wong 		 * adding:           |aaaaaaaaa|
10460a1b0b38SDarrick J. Wong 		 * result: |rrrrrrrrrrrrrrrrrrr|
10470a1b0b38SDarrick J. Wong 		 *                  bno       len
10480a1b0b38SDarrick J. Wong 		 */
10490a1b0b38SDarrick J. Wong 		ltrec.rm_blockcount += len;
10500a1b0b38SDarrick J. Wong 		if (have_gt &&
10510a1b0b38SDarrick J. Wong 		    bno + len == gtrec.rm_startblock &&
10520a1b0b38SDarrick J. Wong 		    (ignore_off || offset + len == gtrec.rm_offset) &&
10530a1b0b38SDarrick J. Wong 		    (unsigned long)ltrec.rm_blockcount + len +
10540a1b0b38SDarrick J. Wong 				gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
10550a1b0b38SDarrick J. Wong 			/*
10560a1b0b38SDarrick J. Wong 			 * right edge also contiguous, delete right record
10570a1b0b38SDarrick J. Wong 			 * and merge into left record.
10580a1b0b38SDarrick J. Wong 			 *
10590a1b0b38SDarrick J. Wong 			 *       ltbno     ltlen    gtbno     gtlen
10600a1b0b38SDarrick J. Wong 			 * orig:   |ooooooooo|         |ooooooooo|
10610a1b0b38SDarrick J. Wong 			 * adding:           |aaaaaaaaa|
10620a1b0b38SDarrick J. Wong 			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
10630a1b0b38SDarrick J. Wong 			 */
10640a1b0b38SDarrick J. Wong 			ltrec.rm_blockcount += gtrec.rm_blockcount;
106547492ed1SDarrick J. Wong 			trace_xfs_rmap_delete(cur, gtrec.rm_startblock,
106647492ed1SDarrick J. Wong 					gtrec.rm_blockcount, gtrec.rm_owner,
106747492ed1SDarrick J. Wong 					gtrec.rm_offset, gtrec.rm_flags);
10680a1b0b38SDarrick J. Wong 			error = xfs_btree_delete(cur, &i);
10690a1b0b38SDarrick J. Wong 			if (error)
10700a1b0b38SDarrick J. Wong 				goto out_error;
1071f9e03706SDarrick J. Wong 			if (XFS_IS_CORRUPT(mp, i != 1)) {
1072989d5ec3SDarrick J. Wong 				xfs_btree_mark_sick(cur);
1073f9e03706SDarrick J. Wong 				error = -EFSCORRUPTED;
1074f9e03706SDarrick J. Wong 				goto out_error;
1075f9e03706SDarrick J. Wong 			}
10760a1b0b38SDarrick J. Wong 		}
10770a1b0b38SDarrick J. Wong 
10780a1b0b38SDarrick J. Wong 		/* point the cursor back to the left record and update */
10790a1b0b38SDarrick J. Wong 		error = xfs_btree_decrement(cur, 0, &have_gt);
10800a1b0b38SDarrick J. Wong 		if (error)
10810a1b0b38SDarrick J. Wong 			goto out_error;
10820a1b0b38SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
10830a1b0b38SDarrick J. Wong 		if (error)
10840a1b0b38SDarrick J. Wong 			goto out_error;
10850a1b0b38SDarrick J. Wong 	} else if (have_gt &&
10860a1b0b38SDarrick J. Wong 		   bno + len == gtrec.rm_startblock &&
10870a1b0b38SDarrick J. Wong 		   (ignore_off || offset + len == gtrec.rm_offset)) {
10880a1b0b38SDarrick J. Wong 		/*
10890a1b0b38SDarrick J. Wong 		 * right edge contiguous, merge into right record.
10900a1b0b38SDarrick J. Wong 		 *
10910a1b0b38SDarrick J. Wong 		 *                 gtbno     gtlen
10920a1b0b38SDarrick J. Wong 		 * Orig:             |ooooooooo|
10930a1b0b38SDarrick J. Wong 		 * adding: |aaaaaaaaa|
10940a1b0b38SDarrick J. Wong 		 * Result: |rrrrrrrrrrrrrrrrrrr|
10950a1b0b38SDarrick J. Wong 		 *        bno       len
10960a1b0b38SDarrick J. Wong 		 */
10970a1b0b38SDarrick J. Wong 		gtrec.rm_startblock = bno;
10980a1b0b38SDarrick J. Wong 		gtrec.rm_blockcount += len;
10990a1b0b38SDarrick J. Wong 		if (!ignore_off)
11000a1b0b38SDarrick J. Wong 			gtrec.rm_offset = offset;
11010a1b0b38SDarrick J. Wong 		error = xfs_rmap_update(cur, &gtrec);
11020a1b0b38SDarrick J. Wong 		if (error)
11030a1b0b38SDarrick J. Wong 			goto out_error;
11040a1b0b38SDarrick J. Wong 	} else {
11050a1b0b38SDarrick J. Wong 		/*
11060a1b0b38SDarrick J. Wong 		 * no contiguous edge with identical owner, insert
11070a1b0b38SDarrick J. Wong 		 * new record at current cursor position.
11080a1b0b38SDarrick J. Wong 		 */
11090a1b0b38SDarrick J. Wong 		cur->bc_rec.r.rm_startblock = bno;
11100a1b0b38SDarrick J. Wong 		cur->bc_rec.r.rm_blockcount = len;
11110a1b0b38SDarrick J. Wong 		cur->bc_rec.r.rm_owner = owner;
11120a1b0b38SDarrick J. Wong 		cur->bc_rec.r.rm_offset = offset;
11130a1b0b38SDarrick J. Wong 		cur->bc_rec.r.rm_flags = flags;
111447492ed1SDarrick J. Wong 		trace_xfs_rmap_insert(cur, bno, len, owner, offset, flags);
11150a1b0b38SDarrick J. Wong 		error = xfs_btree_insert(cur, &i);
11160a1b0b38SDarrick J. Wong 		if (error)
11170a1b0b38SDarrick J. Wong 			goto out_error;
1118f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1119989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1120f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1121f9e03706SDarrick J. Wong 			goto out_error;
1122f9e03706SDarrick J. Wong 		}
11230a1b0b38SDarrick J. Wong 	}
11240a1b0b38SDarrick J. Wong 
112547492ed1SDarrick J. Wong 	trace_xfs_rmap_map_done(cur, bno, len, unwritten, oinfo);
11260a1b0b38SDarrick J. Wong out_error:
11270a1b0b38SDarrick J. Wong 	if (error)
112871f5a17eSDarrick J. Wong 		trace_xfs_rmap_map_error(cur, error, _RET_IP_);
11290a1b0b38SDarrick J. Wong 	return error;
11300a1b0b38SDarrick J. Wong }
11310a1b0b38SDarrick J. Wong 
11320a1b0b38SDarrick J. Wong /*
11330a1b0b38SDarrick J. Wong  * Add a reference to an extent in the rmap btree.
11340a1b0b38SDarrick J. Wong  */
1135673930c3SDarrick J. Wong int
xfs_rmap_alloc(struct xfs_trans * tp,struct xfs_buf * agbp,struct xfs_perag * pag,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo)1136673930c3SDarrick J. Wong xfs_rmap_alloc(
1137673930c3SDarrick J. Wong 	struct xfs_trans		*tp,
1138673930c3SDarrick J. Wong 	struct xfs_buf			*agbp,
1139fa9c3c19SDave Chinner 	struct xfs_perag		*pag,
1140673930c3SDarrick J. Wong 	xfs_agblock_t			bno,
1141673930c3SDarrick J. Wong 	xfs_extlen_t			len,
114266e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
1143673930c3SDarrick J. Wong {
1144673930c3SDarrick J. Wong 	struct xfs_mount		*mp = tp->t_mountp;
11450a1b0b38SDarrick J. Wong 	struct xfs_btree_cur		*cur;
11460a1b0b38SDarrick J. Wong 	int				error;
1147673930c3SDarrick J. Wong 
114838c26bfdSDave Chinner 	if (!xfs_has_rmapbt(mp))
1149673930c3SDarrick J. Wong 		return 0;
1150673930c3SDarrick J. Wong 
1151fa9c3c19SDave Chinner 	cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
11527e1b84b2SDarrick J. Wong 	xfs_rmap_update_hook(tp, pag, XFS_RMAP_MAP, bno, len, false, oinfo);
11530a1b0b38SDarrick J. Wong 	error = xfs_rmap_map(cur, bno, len, false, oinfo);
11540a1b0b38SDarrick J. Wong 
11550b04b6b8SDarrick J. Wong 	xfs_btree_del_cursor(cur, error);
1156673930c3SDarrick J. Wong 	return error;
1157673930c3SDarrick J. Wong }
1158c543838aSDarrick J. Wong 
1159fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG	(1 << 0)
1160fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG	(1 << 1)
1161fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING	(1 << 2)
1162fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING	(1 << 3)
1163fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID		(1 << 6)
1164fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID	(1 << 7)
1165fb7d9267SDarrick J. Wong 
1166fb7d9267SDarrick J. Wong #define LEFT		r[0]
1167fb7d9267SDarrick J. Wong #define RIGHT		r[1]
1168fb7d9267SDarrick J. Wong #define PREV		r[2]
1169fb7d9267SDarrick J. Wong #define NEW		r[3]
1170fb7d9267SDarrick J. Wong 
1171fb7d9267SDarrick J. Wong /*
1172fb7d9267SDarrick J. Wong  * Convert an unwritten extent to a real extent or vice versa.
1173fb7d9267SDarrick J. Wong  * Does not handle overlapping extents.
1174fb7d9267SDarrick J. Wong  */
1175fb7d9267SDarrick J. Wong STATIC int
xfs_rmap_convert(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)1176fb7d9267SDarrick J. Wong xfs_rmap_convert(
1177fb7d9267SDarrick J. Wong 	struct xfs_btree_cur		*cur,
1178fb7d9267SDarrick J. Wong 	xfs_agblock_t			bno,
1179fb7d9267SDarrick J. Wong 	xfs_extlen_t			len,
1180fb7d9267SDarrick J. Wong 	bool				unwritten,
118166e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
1182fb7d9267SDarrick J. Wong {
1183fb7d9267SDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
1184fb7d9267SDarrick J. Wong 	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
118566e3237eSDarrick J. Wong 						/* left is 0, right is 1, */
118666e3237eSDarrick J. Wong 						/* prev is 2, new is 3 */
1187fb7d9267SDarrick J. Wong 	uint64_t		owner;
1188fb7d9267SDarrick J. Wong 	uint64_t		offset;
1189fb7d9267SDarrick J. Wong 	uint64_t		new_endoff;
1190fb7d9267SDarrick J. Wong 	unsigned int		oldext;
1191fb7d9267SDarrick J. Wong 	unsigned int		newext;
1192fb7d9267SDarrick J. Wong 	unsigned int		flags = 0;
1193fb7d9267SDarrick J. Wong 	int			i;
1194fb7d9267SDarrick J. Wong 	int			state = 0;
1195fb7d9267SDarrick J. Wong 	int			error;
1196fb7d9267SDarrick J. Wong 
1197fb7d9267SDarrick J. Wong 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1198fb7d9267SDarrick J. Wong 	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1199fb7d9267SDarrick J. Wong 			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1200fb7d9267SDarrick J. Wong 	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1201fb7d9267SDarrick J. Wong 	new_endoff = offset + len;
120247492ed1SDarrick J. Wong 	trace_xfs_rmap_convert(cur, bno, len, unwritten, oinfo);
1203fb7d9267SDarrick J. Wong 
1204fb7d9267SDarrick J. Wong 	/*
1205fb7d9267SDarrick J. Wong 	 * For the initial lookup, look for an exact match or the left-adjacent
1206fb7d9267SDarrick J. Wong 	 * record for our insertion point. This will also give us the record for
1207fb7d9267SDarrick J. Wong 	 * start block contiguity tests.
1208fb7d9267SDarrick J. Wong 	 */
12095b7ca8b3SDarrick J. Wong 	error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1210fb7d9267SDarrick J. Wong 	if (error)
1211fb7d9267SDarrick J. Wong 		goto done;
1212f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1213989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
1214f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
1215f9e03706SDarrick J. Wong 		goto done;
1216f9e03706SDarrick J. Wong 	}
1217fb7d9267SDarrick J. Wong 
121847492ed1SDarrick J. Wong 	trace_xfs_rmap_lookup_le_range_result(cur, PREV.rm_startblock,
121947492ed1SDarrick J. Wong 			PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset,
122047492ed1SDarrick J. Wong 			PREV.rm_flags);
1221fb7d9267SDarrick J. Wong 
1222fb7d9267SDarrick J. Wong 	ASSERT(PREV.rm_offset <= offset);
1223fb7d9267SDarrick J. Wong 	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1224fb7d9267SDarrick J. Wong 	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1225fb7d9267SDarrick J. Wong 	newext = ~oldext & XFS_RMAP_UNWRITTEN;
1226fb7d9267SDarrick J. Wong 
1227fb7d9267SDarrick J. Wong 	/*
1228fb7d9267SDarrick J. Wong 	 * Set flags determining what part of the previous oldext allocation
1229fb7d9267SDarrick J. Wong 	 * extent is being replaced by a newext allocation.
1230fb7d9267SDarrick J. Wong 	 */
1231fb7d9267SDarrick J. Wong 	if (PREV.rm_offset == offset)
1232fb7d9267SDarrick J. Wong 		state |= RMAP_LEFT_FILLING;
1233fb7d9267SDarrick J. Wong 	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1234fb7d9267SDarrick J. Wong 		state |= RMAP_RIGHT_FILLING;
1235fb7d9267SDarrick J. Wong 
1236fb7d9267SDarrick J. Wong 	/*
1237fb7d9267SDarrick J. Wong 	 * Decrement the cursor to see if we have a left-adjacent record to our
1238fb7d9267SDarrick J. Wong 	 * insertion point. This will give us the record for end block
1239fb7d9267SDarrick J. Wong 	 * contiguity tests.
1240fb7d9267SDarrick J. Wong 	 */
1241fb7d9267SDarrick J. Wong 	error = xfs_btree_decrement(cur, 0, &i);
1242fb7d9267SDarrick J. Wong 	if (error)
1243fb7d9267SDarrick J. Wong 		goto done;
1244fb7d9267SDarrick J. Wong 	if (i) {
1245fb7d9267SDarrick J. Wong 		state |= RMAP_LEFT_VALID;
1246fb7d9267SDarrick J. Wong 		error = xfs_rmap_get_rec(cur, &LEFT, &i);
1247fb7d9267SDarrick J. Wong 		if (error)
1248fb7d9267SDarrick J. Wong 			goto done;
1249f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1250989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1251f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1252f9e03706SDarrick J. Wong 			goto done;
1253f9e03706SDarrick J. Wong 		}
1254f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp,
1255f9e03706SDarrick J. Wong 				   LEFT.rm_startblock + LEFT.rm_blockcount >
1256f9e03706SDarrick J. Wong 				   bno)) {
1257989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1258f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1259f9e03706SDarrick J. Wong 			goto done;
1260f9e03706SDarrick J. Wong 		}
126147492ed1SDarrick J. Wong 		trace_xfs_rmap_find_left_neighbor_result(cur,
126247492ed1SDarrick J. Wong 				LEFT.rm_startblock, LEFT.rm_blockcount,
126347492ed1SDarrick J. Wong 				LEFT.rm_owner, LEFT.rm_offset, LEFT.rm_flags);
1264fb7d9267SDarrick J. Wong 		if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1265fb7d9267SDarrick J. Wong 		    LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1266fb7d9267SDarrick J. Wong 		    xfs_rmap_is_mergeable(&LEFT, owner, newext))
1267fb7d9267SDarrick J. Wong 			state |= RMAP_LEFT_CONTIG;
1268fb7d9267SDarrick J. Wong 	}
1269fb7d9267SDarrick J. Wong 
1270fb7d9267SDarrick J. Wong 	/*
1271fb7d9267SDarrick J. Wong 	 * Increment the cursor to see if we have a right-adjacent record to our
1272fb7d9267SDarrick J. Wong 	 * insertion point. This will give us the record for end block
1273fb7d9267SDarrick J. Wong 	 * contiguity tests.
1274fb7d9267SDarrick J. Wong 	 */
1275fb7d9267SDarrick J. Wong 	error = xfs_btree_increment(cur, 0, &i);
1276fb7d9267SDarrick J. Wong 	if (error)
1277fb7d9267SDarrick J. Wong 		goto done;
1278f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1279989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
1280f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
1281f9e03706SDarrick J. Wong 		goto done;
1282f9e03706SDarrick J. Wong 	}
1283fb7d9267SDarrick J. Wong 	error = xfs_btree_increment(cur, 0, &i);
1284fb7d9267SDarrick J. Wong 	if (error)
1285fb7d9267SDarrick J. Wong 		goto done;
1286fb7d9267SDarrick J. Wong 	if (i) {
1287fb7d9267SDarrick J. Wong 		state |= RMAP_RIGHT_VALID;
1288fb7d9267SDarrick J. Wong 		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1289fb7d9267SDarrick J. Wong 		if (error)
1290fb7d9267SDarrick J. Wong 			goto done;
1291f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1292989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1293f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1294f9e03706SDarrick J. Wong 			goto done;
1295f9e03706SDarrick J. Wong 		}
1296f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1297989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1298f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1299f9e03706SDarrick J. Wong 			goto done;
1300f9e03706SDarrick J. Wong 		}
130147492ed1SDarrick J. Wong 		trace_xfs_rmap_find_right_neighbor_result(cur,
130247492ed1SDarrick J. Wong 				RIGHT.rm_startblock, RIGHT.rm_blockcount,
130347492ed1SDarrick J. Wong 				RIGHT.rm_owner, RIGHT.rm_offset,
130447492ed1SDarrick J. Wong 				RIGHT.rm_flags);
1305fb7d9267SDarrick J. Wong 		if (bno + len == RIGHT.rm_startblock &&
1306fb7d9267SDarrick J. Wong 		    offset + len == RIGHT.rm_offset &&
1307fb7d9267SDarrick J. Wong 		    xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1308fb7d9267SDarrick J. Wong 			state |= RMAP_RIGHT_CONTIG;
1309fb7d9267SDarrick J. Wong 	}
1310fb7d9267SDarrick J. Wong 
1311fb7d9267SDarrick J. Wong 	/* check that left + prev + right is not too long */
1312fb7d9267SDarrick J. Wong 	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1313fb7d9267SDarrick J. Wong 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1314fb7d9267SDarrick J. Wong 	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1315fb7d9267SDarrick J. Wong 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1316fb7d9267SDarrick J. Wong 	    (unsigned long)LEFT.rm_blockcount + len +
1317fb7d9267SDarrick J. Wong 	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1318fb7d9267SDarrick J. Wong 		state &= ~RMAP_RIGHT_CONTIG;
1319fb7d9267SDarrick J. Wong 
132071f5a17eSDarrick J. Wong 	trace_xfs_rmap_convert_state(cur, state, _RET_IP_);
1321fb7d9267SDarrick J. Wong 
1322fb7d9267SDarrick J. Wong 	/* reset the cursor back to PREV */
13235b7ca8b3SDarrick J. Wong 	error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1324fb7d9267SDarrick J. Wong 	if (error)
1325fb7d9267SDarrick J. Wong 		goto done;
1326f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1327989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
1328f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
1329f9e03706SDarrick J. Wong 		goto done;
1330f9e03706SDarrick J. Wong 	}
1331fb7d9267SDarrick J. Wong 
1332fb7d9267SDarrick J. Wong 	/*
1333fb7d9267SDarrick J. Wong 	 * Switch out based on the FILLING and CONTIG state bits.
1334fb7d9267SDarrick J. Wong 	 */
1335fb7d9267SDarrick J. Wong 	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1336fb7d9267SDarrick J. Wong 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1337fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1338fb7d9267SDarrick J. Wong 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1339fb7d9267SDarrick J. Wong 		/*
1340fb7d9267SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
1341fb7d9267SDarrick J. Wong 		 * The left and right neighbors are both contiguous with new.
1342fb7d9267SDarrick J. Wong 		 */
1343fb7d9267SDarrick J. Wong 		error = xfs_btree_increment(cur, 0, &i);
1344fb7d9267SDarrick J. Wong 		if (error)
1345fb7d9267SDarrick J. Wong 			goto done;
1346f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1347989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1348f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1349f9e03706SDarrick J. Wong 			goto done;
1350f9e03706SDarrick J. Wong 		}
135147492ed1SDarrick J. Wong 		trace_xfs_rmap_delete(cur, RIGHT.rm_startblock,
135247492ed1SDarrick J. Wong 				RIGHT.rm_blockcount, RIGHT.rm_owner,
135347492ed1SDarrick J. Wong 				RIGHT.rm_offset, RIGHT.rm_flags);
1354fb7d9267SDarrick J. Wong 		error = xfs_btree_delete(cur, &i);
1355fb7d9267SDarrick J. Wong 		if (error)
1356fb7d9267SDarrick J. Wong 			goto done;
1357f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1358989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1359f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1360f9e03706SDarrick J. Wong 			goto done;
1361f9e03706SDarrick J. Wong 		}
1362fb7d9267SDarrick J. Wong 		error = xfs_btree_decrement(cur, 0, &i);
1363fb7d9267SDarrick J. Wong 		if (error)
1364fb7d9267SDarrick J. Wong 			goto done;
1365f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1366989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1367f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1368f9e03706SDarrick J. Wong 			goto done;
1369f9e03706SDarrick J. Wong 		}
137047492ed1SDarrick J. Wong 		trace_xfs_rmap_delete(cur, PREV.rm_startblock,
137147492ed1SDarrick J. Wong 				PREV.rm_blockcount, PREV.rm_owner,
137247492ed1SDarrick J. Wong 				PREV.rm_offset, PREV.rm_flags);
1373fb7d9267SDarrick J. Wong 		error = xfs_btree_delete(cur, &i);
1374fb7d9267SDarrick J. Wong 		if (error)
1375fb7d9267SDarrick J. Wong 			goto done;
1376f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1377989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1378f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1379f9e03706SDarrick J. Wong 			goto done;
1380f9e03706SDarrick J. Wong 		}
1381fb7d9267SDarrick J. Wong 		error = xfs_btree_decrement(cur, 0, &i);
1382fb7d9267SDarrick J. Wong 		if (error)
1383fb7d9267SDarrick J. Wong 			goto done;
1384f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1385989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1386f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1387f9e03706SDarrick J. Wong 			goto done;
1388f9e03706SDarrick J. Wong 		}
1389fb7d9267SDarrick J. Wong 		NEW = LEFT;
1390fb7d9267SDarrick J. Wong 		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1391fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1392fb7d9267SDarrick J. Wong 		if (error)
1393fb7d9267SDarrick J. Wong 			goto done;
1394fb7d9267SDarrick J. Wong 		break;
1395fb7d9267SDarrick J. Wong 
1396fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1397fb7d9267SDarrick J. Wong 		/*
1398fb7d9267SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
1399fb7d9267SDarrick J. Wong 		 * The left neighbor is contiguous, the right is not.
1400fb7d9267SDarrick J. Wong 		 */
140147492ed1SDarrick J. Wong 		trace_xfs_rmap_delete(cur, PREV.rm_startblock,
140247492ed1SDarrick J. Wong 				PREV.rm_blockcount, PREV.rm_owner,
140347492ed1SDarrick J. Wong 				PREV.rm_offset, PREV.rm_flags);
1404fb7d9267SDarrick J. Wong 		error = xfs_btree_delete(cur, &i);
1405fb7d9267SDarrick J. Wong 		if (error)
1406fb7d9267SDarrick J. Wong 			goto done;
1407f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1408989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1409f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1410f9e03706SDarrick J. Wong 			goto done;
1411f9e03706SDarrick J. Wong 		}
1412fb7d9267SDarrick J. Wong 		error = xfs_btree_decrement(cur, 0, &i);
1413fb7d9267SDarrick J. Wong 		if (error)
1414fb7d9267SDarrick J. Wong 			goto done;
1415f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1416989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1417f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1418f9e03706SDarrick J. Wong 			goto done;
1419f9e03706SDarrick J. Wong 		}
1420fb7d9267SDarrick J. Wong 		NEW = LEFT;
1421fb7d9267SDarrick J. Wong 		NEW.rm_blockcount += PREV.rm_blockcount;
1422fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1423fb7d9267SDarrick J. Wong 		if (error)
1424fb7d9267SDarrick J. Wong 			goto done;
1425fb7d9267SDarrick J. Wong 		break;
1426fb7d9267SDarrick J. Wong 
1427fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1428fb7d9267SDarrick J. Wong 		/*
1429fb7d9267SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
1430fb7d9267SDarrick J. Wong 		 * The right neighbor is contiguous, the left is not.
1431fb7d9267SDarrick J. Wong 		 */
1432fb7d9267SDarrick J. Wong 		error = xfs_btree_increment(cur, 0, &i);
1433fb7d9267SDarrick J. Wong 		if (error)
1434fb7d9267SDarrick J. Wong 			goto done;
1435f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1436989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1437f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1438f9e03706SDarrick J. Wong 			goto done;
1439f9e03706SDarrick J. Wong 		}
144047492ed1SDarrick J. Wong 		trace_xfs_rmap_delete(cur, RIGHT.rm_startblock,
144147492ed1SDarrick J. Wong 				RIGHT.rm_blockcount, RIGHT.rm_owner,
144247492ed1SDarrick J. Wong 				RIGHT.rm_offset, RIGHT.rm_flags);
1443fb7d9267SDarrick J. Wong 		error = xfs_btree_delete(cur, &i);
1444fb7d9267SDarrick J. Wong 		if (error)
1445fb7d9267SDarrick J. Wong 			goto done;
1446f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1447989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1448f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1449f9e03706SDarrick J. Wong 			goto done;
1450f9e03706SDarrick J. Wong 		}
1451fb7d9267SDarrick J. Wong 		error = xfs_btree_decrement(cur, 0, &i);
1452fb7d9267SDarrick J. Wong 		if (error)
1453fb7d9267SDarrick J. Wong 			goto done;
1454f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1455989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1456f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1457f9e03706SDarrick J. Wong 			goto done;
1458f9e03706SDarrick J. Wong 		}
1459fb7d9267SDarrick J. Wong 		NEW = PREV;
1460fb7d9267SDarrick J. Wong 		NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1461fb7d9267SDarrick J. Wong 		NEW.rm_flags = newext;
1462fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1463fb7d9267SDarrick J. Wong 		if (error)
1464fb7d9267SDarrick J. Wong 			goto done;
1465fb7d9267SDarrick J. Wong 		break;
1466fb7d9267SDarrick J. Wong 
1467fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1468fb7d9267SDarrick J. Wong 		/*
1469fb7d9267SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
1470fb7d9267SDarrick J. Wong 		 * Neither the left nor right neighbors are contiguous with
1471fb7d9267SDarrick J. Wong 		 * the new one.
1472fb7d9267SDarrick J. Wong 		 */
1473fb7d9267SDarrick J. Wong 		NEW = PREV;
1474fb7d9267SDarrick J. Wong 		NEW.rm_flags = newext;
1475fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1476fb7d9267SDarrick J. Wong 		if (error)
1477fb7d9267SDarrick J. Wong 			goto done;
1478fb7d9267SDarrick J. Wong 		break;
1479fb7d9267SDarrick J. Wong 
1480fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1481fb7d9267SDarrick J. Wong 		/*
1482fb7d9267SDarrick J. Wong 		 * Setting the first part of a previous oldext extent to newext.
1483fb7d9267SDarrick J. Wong 		 * The left neighbor is contiguous.
1484fb7d9267SDarrick J. Wong 		 */
1485fb7d9267SDarrick J. Wong 		NEW = PREV;
1486fb7d9267SDarrick J. Wong 		NEW.rm_offset += len;
1487fb7d9267SDarrick J. Wong 		NEW.rm_startblock += len;
1488fb7d9267SDarrick J. Wong 		NEW.rm_blockcount -= len;
1489fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1490fb7d9267SDarrick J. Wong 		if (error)
1491fb7d9267SDarrick J. Wong 			goto done;
1492fb7d9267SDarrick J. Wong 		error = xfs_btree_decrement(cur, 0, &i);
1493fb7d9267SDarrick J. Wong 		if (error)
1494fb7d9267SDarrick J. Wong 			goto done;
1495fb7d9267SDarrick J. Wong 		NEW = LEFT;
1496fb7d9267SDarrick J. Wong 		NEW.rm_blockcount += len;
1497fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1498fb7d9267SDarrick J. Wong 		if (error)
1499fb7d9267SDarrick J. Wong 			goto done;
1500fb7d9267SDarrick J. Wong 		break;
1501fb7d9267SDarrick J. Wong 
1502fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING:
1503fb7d9267SDarrick J. Wong 		/*
1504fb7d9267SDarrick J. Wong 		 * Setting the first part of a previous oldext extent to newext.
1505fb7d9267SDarrick J. Wong 		 * The left neighbor is not contiguous.
1506fb7d9267SDarrick J. Wong 		 */
1507fb7d9267SDarrick J. Wong 		NEW = PREV;
1508fb7d9267SDarrick J. Wong 		NEW.rm_startblock += len;
1509fb7d9267SDarrick J. Wong 		NEW.rm_offset += len;
1510fb7d9267SDarrick J. Wong 		NEW.rm_blockcount -= len;
1511fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1512fb7d9267SDarrick J. Wong 		if (error)
1513fb7d9267SDarrick J. Wong 			goto done;
1514fb7d9267SDarrick J. Wong 		NEW.rm_startblock = bno;
1515fb7d9267SDarrick J. Wong 		NEW.rm_owner = owner;
1516fb7d9267SDarrick J. Wong 		NEW.rm_offset = offset;
1517fb7d9267SDarrick J. Wong 		NEW.rm_blockcount = len;
1518fb7d9267SDarrick J. Wong 		NEW.rm_flags = newext;
1519fb7d9267SDarrick J. Wong 		cur->bc_rec.r = NEW;
152047492ed1SDarrick J. Wong 		trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1521fb7d9267SDarrick J. Wong 		error = xfs_btree_insert(cur, &i);
1522fb7d9267SDarrick J. Wong 		if (error)
1523fb7d9267SDarrick J. Wong 			goto done;
1524f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1525989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1526f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1527f9e03706SDarrick J. Wong 			goto done;
1528f9e03706SDarrick J. Wong 		}
1529fb7d9267SDarrick J. Wong 		break;
1530fb7d9267SDarrick J. Wong 
1531fb7d9267SDarrick J. Wong 	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1532fb7d9267SDarrick J. Wong 		/*
1533fb7d9267SDarrick J. Wong 		 * Setting the last part of a previous oldext extent to newext.
1534fb7d9267SDarrick J. Wong 		 * The right neighbor is contiguous with the new allocation.
1535fb7d9267SDarrick J. Wong 		 */
1536fb7d9267SDarrick J. Wong 		NEW = PREV;
1537fb7d9267SDarrick J. Wong 		NEW.rm_blockcount -= len;
1538fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1539fb7d9267SDarrick J. Wong 		if (error)
1540fb7d9267SDarrick J. Wong 			goto done;
1541fb7d9267SDarrick J. Wong 		error = xfs_btree_increment(cur, 0, &i);
1542fb7d9267SDarrick J. Wong 		if (error)
1543fb7d9267SDarrick J. Wong 			goto done;
1544fb7d9267SDarrick J. Wong 		NEW = RIGHT;
1545fb7d9267SDarrick J. Wong 		NEW.rm_offset = offset;
1546fb7d9267SDarrick J. Wong 		NEW.rm_startblock = bno;
1547fb7d9267SDarrick J. Wong 		NEW.rm_blockcount += len;
1548fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1549fb7d9267SDarrick J. Wong 		if (error)
1550fb7d9267SDarrick J. Wong 			goto done;
1551fb7d9267SDarrick J. Wong 		break;
1552fb7d9267SDarrick J. Wong 
1553fb7d9267SDarrick J. Wong 	case RMAP_RIGHT_FILLING:
1554fb7d9267SDarrick J. Wong 		/*
1555fb7d9267SDarrick J. Wong 		 * Setting the last part of a previous oldext extent to newext.
1556fb7d9267SDarrick J. Wong 		 * The right neighbor is not contiguous.
1557fb7d9267SDarrick J. Wong 		 */
1558fb7d9267SDarrick J. Wong 		NEW = PREV;
1559fb7d9267SDarrick J. Wong 		NEW.rm_blockcount -= len;
1560fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1561fb7d9267SDarrick J. Wong 		if (error)
1562fb7d9267SDarrick J. Wong 			goto done;
1563fb7d9267SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1564fb7d9267SDarrick J. Wong 				oldext, &i);
1565fb7d9267SDarrick J. Wong 		if (error)
1566fb7d9267SDarrick J. Wong 			goto done;
1567f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 0)) {
1568989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1569f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1570f9e03706SDarrick J. Wong 			goto done;
1571f9e03706SDarrick J. Wong 		}
1572fb7d9267SDarrick J. Wong 		NEW.rm_startblock = bno;
1573fb7d9267SDarrick J. Wong 		NEW.rm_owner = owner;
1574fb7d9267SDarrick J. Wong 		NEW.rm_offset = offset;
1575fb7d9267SDarrick J. Wong 		NEW.rm_blockcount = len;
1576fb7d9267SDarrick J. Wong 		NEW.rm_flags = newext;
1577fb7d9267SDarrick J. Wong 		cur->bc_rec.r = NEW;
157847492ed1SDarrick J. Wong 		trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1579fb7d9267SDarrick J. Wong 		error = xfs_btree_insert(cur, &i);
1580fb7d9267SDarrick J. Wong 		if (error)
1581fb7d9267SDarrick J. Wong 			goto done;
1582f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1583989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1584f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1585f9e03706SDarrick J. Wong 			goto done;
1586f9e03706SDarrick J. Wong 		}
1587fb7d9267SDarrick J. Wong 		break;
1588fb7d9267SDarrick J. Wong 
1589fb7d9267SDarrick J. Wong 	case 0:
1590fb7d9267SDarrick J. Wong 		/*
1591fb7d9267SDarrick J. Wong 		 * Setting the middle part of a previous oldext extent to
1592fb7d9267SDarrick J. Wong 		 * newext.  Contiguity is impossible here.
1593fb7d9267SDarrick J. Wong 		 * One extent becomes three extents.
1594fb7d9267SDarrick J. Wong 		 */
1595fb7d9267SDarrick J. Wong 		/* new right extent - oldext */
1596fb7d9267SDarrick J. Wong 		NEW.rm_startblock = bno + len;
1597fb7d9267SDarrick J. Wong 		NEW.rm_owner = owner;
1598fb7d9267SDarrick J. Wong 		NEW.rm_offset = new_endoff;
1599fb7d9267SDarrick J. Wong 		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1600fb7d9267SDarrick J. Wong 				new_endoff;
1601fb7d9267SDarrick J. Wong 		NEW.rm_flags = PREV.rm_flags;
1602fb7d9267SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
1603fb7d9267SDarrick J. Wong 		if (error)
1604fb7d9267SDarrick J. Wong 			goto done;
1605fb7d9267SDarrick J. Wong 		/* new left extent - oldext */
1606fb7d9267SDarrick J. Wong 		NEW = PREV;
1607fb7d9267SDarrick J. Wong 		NEW.rm_blockcount = offset - PREV.rm_offset;
1608fb7d9267SDarrick J. Wong 		cur->bc_rec.r = NEW;
160947492ed1SDarrick J. Wong 		trace_xfs_rmap_insert(cur, NEW.rm_startblock,
161047492ed1SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1611fb7d9267SDarrick J. Wong 				NEW.rm_flags);
1612fb7d9267SDarrick J. Wong 		error = xfs_btree_insert(cur, &i);
1613fb7d9267SDarrick J. Wong 		if (error)
1614fb7d9267SDarrick J. Wong 			goto done;
1615f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1616989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1617f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1618f9e03706SDarrick J. Wong 			goto done;
1619f9e03706SDarrick J. Wong 		}
1620fb7d9267SDarrick J. Wong 		/*
1621fb7d9267SDarrick J. Wong 		 * Reset the cursor to the position of the new extent
1622fb7d9267SDarrick J. Wong 		 * we are about to insert as we can't trust it after
1623fb7d9267SDarrick J. Wong 		 * the previous insert.
1624fb7d9267SDarrick J. Wong 		 */
1625fb7d9267SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1626fb7d9267SDarrick J. Wong 				oldext, &i);
1627fb7d9267SDarrick J. Wong 		if (error)
1628fb7d9267SDarrick J. Wong 			goto done;
1629f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 0)) {
1630989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1631f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1632f9e03706SDarrick J. Wong 			goto done;
1633f9e03706SDarrick J. Wong 		}
1634fb7d9267SDarrick J. Wong 		/* new middle extent - newext */
1635fb7d9267SDarrick J. Wong 		cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1636fb7d9267SDarrick J. Wong 		cur->bc_rec.r.rm_flags |= newext;
163747492ed1SDarrick J. Wong 		trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1638fb7d9267SDarrick J. Wong 		error = xfs_btree_insert(cur, &i);
1639fb7d9267SDarrick J. Wong 		if (error)
1640fb7d9267SDarrick J. Wong 			goto done;
1641f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1642989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1643f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1644f9e03706SDarrick J. Wong 			goto done;
1645f9e03706SDarrick J. Wong 		}
1646fb7d9267SDarrick J. Wong 		break;
1647fb7d9267SDarrick J. Wong 
1648fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1649fb7d9267SDarrick J. Wong 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1650fb7d9267SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1651fb7d9267SDarrick J. Wong 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1652fb7d9267SDarrick J. Wong 	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1653fb7d9267SDarrick J. Wong 	case RMAP_LEFT_CONTIG:
1654fb7d9267SDarrick J. Wong 	case RMAP_RIGHT_CONTIG:
1655fb7d9267SDarrick J. Wong 		/*
1656fb7d9267SDarrick J. Wong 		 * These cases are all impossible.
1657fb7d9267SDarrick J. Wong 		 */
1658fb7d9267SDarrick J. Wong 		ASSERT(0);
1659fb7d9267SDarrick J. Wong 	}
1660fb7d9267SDarrick J. Wong 
166147492ed1SDarrick J. Wong 	trace_xfs_rmap_convert_done(cur, bno, len, unwritten, oinfo);
1662fb7d9267SDarrick J. Wong done:
1663fb7d9267SDarrick J. Wong 	if (error)
166471f5a17eSDarrick J. Wong 		trace_xfs_rmap_convert_error(cur, error, _RET_IP_);
1665fb7d9267SDarrick J. Wong 	return error;
1666fb7d9267SDarrick J. Wong }
1667fb7d9267SDarrick J. Wong 
16683f165b33SDarrick J. Wong /*
16693f165b33SDarrick J. Wong  * Convert an unwritten extent to a real extent or vice versa.  If there is no
16703f165b33SDarrick J. Wong  * possibility of overlapping extents, delegate to the simpler convert
16713f165b33SDarrick J. Wong  * function.
16723f165b33SDarrick J. Wong  */
16733f165b33SDarrick J. Wong STATIC int
xfs_rmap_convert_shared(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)16743f165b33SDarrick J. Wong xfs_rmap_convert_shared(
16753f165b33SDarrick J. Wong 	struct xfs_btree_cur		*cur,
16763f165b33SDarrick J. Wong 	xfs_agblock_t			bno,
16773f165b33SDarrick J. Wong 	xfs_extlen_t			len,
16783f165b33SDarrick J. Wong 	bool				unwritten,
167966e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
16803f165b33SDarrick J. Wong {
16813f165b33SDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
16823f165b33SDarrick J. Wong 	struct xfs_rmap_irec		r[4];	/* neighbor extent entries */
168366e3237eSDarrick J. Wong 						/* left is 0, right is 1, */
168466e3237eSDarrick J. Wong 						/* prev is 2, new is 3 */
16853f165b33SDarrick J. Wong 	uint64_t		owner;
16863f165b33SDarrick J. Wong 	uint64_t		offset;
16873f165b33SDarrick J. Wong 	uint64_t		new_endoff;
16883f165b33SDarrick J. Wong 	unsigned int		oldext;
16893f165b33SDarrick J. Wong 	unsigned int		newext;
16903f165b33SDarrick J. Wong 	unsigned int		flags = 0;
16913f165b33SDarrick J. Wong 	int			i;
16923f165b33SDarrick J. Wong 	int			state = 0;
16933f165b33SDarrick J. Wong 	int			error;
16943f165b33SDarrick J. Wong 
16953f165b33SDarrick J. Wong 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
16963f165b33SDarrick J. Wong 	ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
16973f165b33SDarrick J. Wong 			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
16983f165b33SDarrick J. Wong 	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
16993f165b33SDarrick J. Wong 	new_endoff = offset + len;
170047492ed1SDarrick J. Wong 	trace_xfs_rmap_convert(cur, bno, len, unwritten, oinfo);
17013f165b33SDarrick J. Wong 
17023f165b33SDarrick J. Wong 	/*
17033f165b33SDarrick J. Wong 	 * For the initial lookup, look for and exact match or the left-adjacent
17043f165b33SDarrick J. Wong 	 * record for our insertion point. This will also give us the record for
17053f165b33SDarrick J. Wong 	 * start block contiguity tests.
17063f165b33SDarrick J. Wong 	 */
1707ea843989SDarrick J. Wong 	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
17083f165b33SDarrick J. Wong 			&PREV, &i);
170952101dfeSDarrick J. Wong 	if (error)
171052101dfeSDarrick J. Wong 		goto done;
1711f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, i != 1)) {
1712989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
1713f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
1714f9e03706SDarrick J. Wong 		goto done;
1715f9e03706SDarrick J. Wong 	}
17163f165b33SDarrick J. Wong 
17173f165b33SDarrick J. Wong 	ASSERT(PREV.rm_offset <= offset);
17183f165b33SDarrick J. Wong 	ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
17193f165b33SDarrick J. Wong 	ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
17203f165b33SDarrick J. Wong 	newext = ~oldext & XFS_RMAP_UNWRITTEN;
17213f165b33SDarrick J. Wong 
17223f165b33SDarrick J. Wong 	/*
17233f165b33SDarrick J. Wong 	 * Set flags determining what part of the previous oldext allocation
17243f165b33SDarrick J. Wong 	 * extent is being replaced by a newext allocation.
17253f165b33SDarrick J. Wong 	 */
17263f165b33SDarrick J. Wong 	if (PREV.rm_offset == offset)
17273f165b33SDarrick J. Wong 		state |= RMAP_LEFT_FILLING;
17283f165b33SDarrick J. Wong 	if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
17293f165b33SDarrick J. Wong 		state |= RMAP_RIGHT_FILLING;
17303f165b33SDarrick J. Wong 
17313f165b33SDarrick J. Wong 	/* Is there a left record that abuts our range? */
17323f165b33SDarrick J. Wong 	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
17333f165b33SDarrick J. Wong 			&LEFT, &i);
17343f165b33SDarrick J. Wong 	if (error)
17353f165b33SDarrick J. Wong 		goto done;
17363f165b33SDarrick J. Wong 	if (i) {
17373f165b33SDarrick J. Wong 		state |= RMAP_LEFT_VALID;
1738f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp,
1739f9e03706SDarrick J. Wong 				   LEFT.rm_startblock + LEFT.rm_blockcount >
1740f9e03706SDarrick J. Wong 				   bno)) {
1741989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1742f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1743f9e03706SDarrick J. Wong 			goto done;
1744f9e03706SDarrick J. Wong 		}
17453f165b33SDarrick J. Wong 		if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
17463f165b33SDarrick J. Wong 			state |= RMAP_LEFT_CONTIG;
17473f165b33SDarrick J. Wong 	}
17483f165b33SDarrick J. Wong 
17493f165b33SDarrick J. Wong 	/* Is there a right record that abuts our range? */
17503f165b33SDarrick J. Wong 	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
17513f165b33SDarrick J. Wong 			newext, &i);
17523f165b33SDarrick J. Wong 	if (error)
17533f165b33SDarrick J. Wong 		goto done;
17543f165b33SDarrick J. Wong 	if (i) {
17553f165b33SDarrick J. Wong 		state |= RMAP_RIGHT_VALID;
17563f165b33SDarrick J. Wong 		error = xfs_rmap_get_rec(cur, &RIGHT, &i);
17573f165b33SDarrick J. Wong 		if (error)
17583f165b33SDarrick J. Wong 			goto done;
1759f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1760989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1761f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1762f9e03706SDarrick J. Wong 			goto done;
1763f9e03706SDarrick J. Wong 		}
1764f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1765989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1766f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1767f9e03706SDarrick J. Wong 			goto done;
1768f9e03706SDarrick J. Wong 		}
176947492ed1SDarrick J. Wong 		trace_xfs_rmap_find_right_neighbor_result(cur,
177047492ed1SDarrick J. Wong 				RIGHT.rm_startblock, RIGHT.rm_blockcount,
177147492ed1SDarrick J. Wong 				RIGHT.rm_owner, RIGHT.rm_offset,
177247492ed1SDarrick J. Wong 				RIGHT.rm_flags);
17733f165b33SDarrick J. Wong 		if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
17743f165b33SDarrick J. Wong 			state |= RMAP_RIGHT_CONTIG;
17753f165b33SDarrick J. Wong 	}
17763f165b33SDarrick J. Wong 
17773f165b33SDarrick J. Wong 	/* check that left + prev + right is not too long */
17783f165b33SDarrick J. Wong 	if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
17793f165b33SDarrick J. Wong 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
17803f165b33SDarrick J. Wong 	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
17813f165b33SDarrick J. Wong 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
17823f165b33SDarrick J. Wong 	    (unsigned long)LEFT.rm_blockcount + len +
17833f165b33SDarrick J. Wong 	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
17843f165b33SDarrick J. Wong 		state &= ~RMAP_RIGHT_CONTIG;
17853f165b33SDarrick J. Wong 
178671f5a17eSDarrick J. Wong 	trace_xfs_rmap_convert_state(cur, state, _RET_IP_);
17873f165b33SDarrick J. Wong 	/*
17883f165b33SDarrick J. Wong 	 * Switch out based on the FILLING and CONTIG state bits.
17893f165b33SDarrick J. Wong 	 */
17903f165b33SDarrick J. Wong 	switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
17913f165b33SDarrick J. Wong 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
17923f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
17933f165b33SDarrick J. Wong 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
17943f165b33SDarrick J. Wong 		/*
17953f165b33SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
17963f165b33SDarrick J. Wong 		 * The left and right neighbors are both contiguous with new.
17973f165b33SDarrick J. Wong 		 */
17983f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
17993f165b33SDarrick J. Wong 				RIGHT.rm_blockcount, RIGHT.rm_owner,
18003f165b33SDarrick J. Wong 				RIGHT.rm_offset, RIGHT.rm_flags);
18013f165b33SDarrick J. Wong 		if (error)
18023f165b33SDarrick J. Wong 			goto done;
18033f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, PREV.rm_startblock,
18043f165b33SDarrick J. Wong 				PREV.rm_blockcount, PREV.rm_owner,
18053f165b33SDarrick J. Wong 				PREV.rm_offset, PREV.rm_flags);
18063f165b33SDarrick J. Wong 		if (error)
18073f165b33SDarrick J. Wong 			goto done;
18083f165b33SDarrick J. Wong 		NEW = LEFT;
18093f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18103f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
18113f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
18123f165b33SDarrick J. Wong 		if (error)
18133f165b33SDarrick J. Wong 			goto done;
1814f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1815989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1816f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1817f9e03706SDarrick J. Wong 			goto done;
1818f9e03706SDarrick J. Wong 		}
18193f165b33SDarrick J. Wong 		NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
18203f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
18213f165b33SDarrick J. Wong 		if (error)
18223f165b33SDarrick J. Wong 			goto done;
18233f165b33SDarrick J. Wong 		break;
18243f165b33SDarrick J. Wong 
18253f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
18263f165b33SDarrick J. Wong 		/*
18273f165b33SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
18283f165b33SDarrick J. Wong 		 * The left neighbor is contiguous, the right is not.
18293f165b33SDarrick J. Wong 		 */
18303f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, PREV.rm_startblock,
18313f165b33SDarrick J. Wong 				PREV.rm_blockcount, PREV.rm_owner,
18323f165b33SDarrick J. Wong 				PREV.rm_offset, PREV.rm_flags);
18333f165b33SDarrick J. Wong 		if (error)
18343f165b33SDarrick J. Wong 			goto done;
18353f165b33SDarrick J. Wong 		NEW = LEFT;
18363f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18373f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
18383f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
18393f165b33SDarrick J. Wong 		if (error)
18403f165b33SDarrick J. Wong 			goto done;
1841f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1842989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1843f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1844f9e03706SDarrick J. Wong 			goto done;
1845f9e03706SDarrick J. Wong 		}
18463f165b33SDarrick J. Wong 		NEW.rm_blockcount += PREV.rm_blockcount;
18473f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
18483f165b33SDarrick J. Wong 		if (error)
18493f165b33SDarrick J. Wong 			goto done;
18503f165b33SDarrick J. Wong 		break;
18513f165b33SDarrick J. Wong 
18523f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
18533f165b33SDarrick J. Wong 		/*
18543f165b33SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
18553f165b33SDarrick J. Wong 		 * The right neighbor is contiguous, the left is not.
18563f165b33SDarrick J. Wong 		 */
18573f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
18583f165b33SDarrick J. Wong 				RIGHT.rm_blockcount, RIGHT.rm_owner,
18593f165b33SDarrick J. Wong 				RIGHT.rm_offset, RIGHT.rm_flags);
18603f165b33SDarrick J. Wong 		if (error)
18613f165b33SDarrick J. Wong 			goto done;
18623f165b33SDarrick J. Wong 		NEW = PREV;
18633f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18643f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
18653f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
18663f165b33SDarrick J. Wong 		if (error)
18673f165b33SDarrick J. Wong 			goto done;
1868f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1869989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1870f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1871f9e03706SDarrick J. Wong 			goto done;
1872f9e03706SDarrick J. Wong 		}
18733f165b33SDarrick J. Wong 		NEW.rm_blockcount += RIGHT.rm_blockcount;
18743f165b33SDarrick J. Wong 		NEW.rm_flags = RIGHT.rm_flags;
18753f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
18763f165b33SDarrick J. Wong 		if (error)
18773f165b33SDarrick J. Wong 			goto done;
18783f165b33SDarrick J. Wong 		break;
18793f165b33SDarrick J. Wong 
18803f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
18813f165b33SDarrick J. Wong 		/*
18823f165b33SDarrick J. Wong 		 * Setting all of a previous oldext extent to newext.
18833f165b33SDarrick J. Wong 		 * Neither the left nor right neighbors are contiguous with
18843f165b33SDarrick J. Wong 		 * the new one.
18853f165b33SDarrick J. Wong 		 */
18863f165b33SDarrick J. Wong 		NEW = PREV;
18873f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18883f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
18893f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
18903f165b33SDarrick J. Wong 		if (error)
18913f165b33SDarrick J. Wong 			goto done;
1892f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1893989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1894f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1895f9e03706SDarrick J. Wong 			goto done;
1896f9e03706SDarrick J. Wong 		}
18973f165b33SDarrick J. Wong 		NEW.rm_flags = newext;
18983f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
18993f165b33SDarrick J. Wong 		if (error)
19003f165b33SDarrick J. Wong 			goto done;
19013f165b33SDarrick J. Wong 		break;
19023f165b33SDarrick J. Wong 
19033f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
19043f165b33SDarrick J. Wong 		/*
19053f165b33SDarrick J. Wong 		 * Setting the first part of a previous oldext extent to newext.
19063f165b33SDarrick J. Wong 		 * The left neighbor is contiguous.
19073f165b33SDarrick J. Wong 		 */
19083f165b33SDarrick J. Wong 		NEW = PREV;
19093f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, NEW.rm_startblock,
19103f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19113f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags);
19123f165b33SDarrick J. Wong 		if (error)
19133f165b33SDarrick J. Wong 			goto done;
19143f165b33SDarrick J. Wong 		NEW.rm_offset += len;
19153f165b33SDarrick J. Wong 		NEW.rm_startblock += len;
19163f165b33SDarrick J. Wong 		NEW.rm_blockcount -= len;
19173f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
19183f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19193f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags);
19203f165b33SDarrick J. Wong 		if (error)
19213f165b33SDarrick J. Wong 			goto done;
19223f165b33SDarrick J. Wong 		NEW = LEFT;
19233f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
19243f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19253f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
19263f165b33SDarrick J. Wong 		if (error)
19273f165b33SDarrick J. Wong 			goto done;
1928f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1929989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1930f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1931f9e03706SDarrick J. Wong 			goto done;
1932f9e03706SDarrick J. Wong 		}
19333f165b33SDarrick J. Wong 		NEW.rm_blockcount += len;
19343f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
19353f165b33SDarrick J. Wong 		if (error)
19363f165b33SDarrick J. Wong 			goto done;
19373f165b33SDarrick J. Wong 		break;
19383f165b33SDarrick J. Wong 
19393f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING:
19403f165b33SDarrick J. Wong 		/*
19413f165b33SDarrick J. Wong 		 * Setting the first part of a previous oldext extent to newext.
19423f165b33SDarrick J. Wong 		 * The left neighbor is not contiguous.
19433f165b33SDarrick J. Wong 		 */
19443f165b33SDarrick J. Wong 		NEW = PREV;
19453f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, NEW.rm_startblock,
19463f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19473f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags);
19483f165b33SDarrick J. Wong 		if (error)
19493f165b33SDarrick J. Wong 			goto done;
19503f165b33SDarrick J. Wong 		NEW.rm_offset += len;
19513f165b33SDarrick J. Wong 		NEW.rm_startblock += len;
19523f165b33SDarrick J. Wong 		NEW.rm_blockcount -= len;
19533f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
19543f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19553f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags);
19563f165b33SDarrick J. Wong 		if (error)
19573f165b33SDarrick J. Wong 			goto done;
19583f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
19593f165b33SDarrick J. Wong 		if (error)
19603f165b33SDarrick J. Wong 			goto done;
19613f165b33SDarrick J. Wong 		break;
19623f165b33SDarrick J. Wong 
19633f165b33SDarrick J. Wong 	case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
19643f165b33SDarrick J. Wong 		/*
19653f165b33SDarrick J. Wong 		 * Setting the last part of a previous oldext extent to newext.
19663f165b33SDarrick J. Wong 		 * The right neighbor is contiguous with the new allocation.
19673f165b33SDarrick J. Wong 		 */
19683f165b33SDarrick J. Wong 		NEW = PREV;
19693f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
19703f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19713f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
19723f165b33SDarrick J. Wong 		if (error)
19733f165b33SDarrick J. Wong 			goto done;
1974f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
1975989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
1976f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
1977f9e03706SDarrick J. Wong 			goto done;
1978f9e03706SDarrick J. Wong 		}
19793f165b33SDarrick J. Wong 		NEW.rm_blockcount = offset - NEW.rm_offset;
19803f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
19813f165b33SDarrick J. Wong 		if (error)
19823f165b33SDarrick J. Wong 			goto done;
19833f165b33SDarrick J. Wong 		NEW = RIGHT;
19843f165b33SDarrick J. Wong 		error = xfs_rmap_delete(cur, NEW.rm_startblock,
19853f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19863f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags);
19873f165b33SDarrick J. Wong 		if (error)
19883f165b33SDarrick J. Wong 			goto done;
19893f165b33SDarrick J. Wong 		NEW.rm_offset = offset;
19903f165b33SDarrick J. Wong 		NEW.rm_startblock = bno;
19913f165b33SDarrick J. Wong 		NEW.rm_blockcount += len;
19923f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
19933f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
19943f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags);
19953f165b33SDarrick J. Wong 		if (error)
19963f165b33SDarrick J. Wong 			goto done;
19973f165b33SDarrick J. Wong 		break;
19983f165b33SDarrick J. Wong 
19993f165b33SDarrick J. Wong 	case RMAP_RIGHT_FILLING:
20003f165b33SDarrick J. Wong 		/*
20013f165b33SDarrick J. Wong 		 * Setting the last part of a previous oldext extent to newext.
20023f165b33SDarrick J. Wong 		 * The right neighbor is not contiguous.
20033f165b33SDarrick J. Wong 		 */
20043f165b33SDarrick J. Wong 		NEW = PREV;
20053f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
20063f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
20073f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
20083f165b33SDarrick J. Wong 		if (error)
20093f165b33SDarrick J. Wong 			goto done;
2010f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2011989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
2012f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
2013f9e03706SDarrick J. Wong 			goto done;
2014f9e03706SDarrick J. Wong 		}
20153f165b33SDarrick J. Wong 		NEW.rm_blockcount -= len;
20163f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
20173f165b33SDarrick J. Wong 		if (error)
20183f165b33SDarrick J. Wong 			goto done;
20193f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
20203f165b33SDarrick J. Wong 		if (error)
20213f165b33SDarrick J. Wong 			goto done;
20223f165b33SDarrick J. Wong 		break;
20233f165b33SDarrick J. Wong 
20243f165b33SDarrick J. Wong 	case 0:
20253f165b33SDarrick J. Wong 		/*
20263f165b33SDarrick J. Wong 		 * Setting the middle part of a previous oldext extent to
20273f165b33SDarrick J. Wong 		 * newext.  Contiguity is impossible here.
20283f165b33SDarrick J. Wong 		 * One extent becomes three extents.
20293f165b33SDarrick J. Wong 		 */
20303f165b33SDarrick J. Wong 		/* new right extent - oldext */
20313f165b33SDarrick J. Wong 		NEW.rm_startblock = bno + len;
20323f165b33SDarrick J. Wong 		NEW.rm_owner = owner;
20333f165b33SDarrick J. Wong 		NEW.rm_offset = new_endoff;
20343f165b33SDarrick J. Wong 		NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
20353f165b33SDarrick J. Wong 				new_endoff;
20363f165b33SDarrick J. Wong 		NEW.rm_flags = PREV.rm_flags;
20373f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
20383f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
20393f165b33SDarrick J. Wong 				NEW.rm_flags);
20403f165b33SDarrick J. Wong 		if (error)
20413f165b33SDarrick J. Wong 			goto done;
20423f165b33SDarrick J. Wong 		/* new left extent - oldext */
20433f165b33SDarrick J. Wong 		NEW = PREV;
20443f165b33SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
20453f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner,
20463f165b33SDarrick J. Wong 				NEW.rm_offset, NEW.rm_flags, &i);
20473f165b33SDarrick J. Wong 		if (error)
20483f165b33SDarrick J. Wong 			goto done;
2049f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2050989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
2051f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
2052f9e03706SDarrick J. Wong 			goto done;
2053f9e03706SDarrick J. Wong 		}
20543f165b33SDarrick J. Wong 		NEW.rm_blockcount = offset - NEW.rm_offset;
20553f165b33SDarrick J. Wong 		error = xfs_rmap_update(cur, &NEW);
20563f165b33SDarrick J. Wong 		if (error)
20573f165b33SDarrick J. Wong 			goto done;
20583f165b33SDarrick J. Wong 		/* new middle extent - newext */
20593f165b33SDarrick J. Wong 		NEW.rm_startblock = bno;
20603f165b33SDarrick J. Wong 		NEW.rm_blockcount = len;
20613f165b33SDarrick J. Wong 		NEW.rm_owner = owner;
20623f165b33SDarrick J. Wong 		NEW.rm_offset = offset;
20633f165b33SDarrick J. Wong 		NEW.rm_flags = newext;
20643f165b33SDarrick J. Wong 		error = xfs_rmap_insert(cur, NEW.rm_startblock,
20653f165b33SDarrick J. Wong 				NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
20663f165b33SDarrick J. Wong 				NEW.rm_flags);
20673f165b33SDarrick J. Wong 		if (error)
20683f165b33SDarrick J. Wong 			goto done;
20693f165b33SDarrick J. Wong 		break;
20703f165b33SDarrick J. Wong 
20713f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
20723f165b33SDarrick J. Wong 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
20733f165b33SDarrick J. Wong 	case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
20743f165b33SDarrick J. Wong 	case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
20753f165b33SDarrick J. Wong 	case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
20763f165b33SDarrick J. Wong 	case RMAP_LEFT_CONTIG:
20773f165b33SDarrick J. Wong 	case RMAP_RIGHT_CONTIG:
20783f165b33SDarrick J. Wong 		/*
20793f165b33SDarrick J. Wong 		 * These cases are all impossible.
20803f165b33SDarrick J. Wong 		 */
20813f165b33SDarrick J. Wong 		ASSERT(0);
20823f165b33SDarrick J. Wong 	}
20833f165b33SDarrick J. Wong 
208447492ed1SDarrick J. Wong 	trace_xfs_rmap_convert_done(cur, bno, len, unwritten, oinfo);
20853f165b33SDarrick J. Wong done:
20863f165b33SDarrick J. Wong 	if (error)
208771f5a17eSDarrick J. Wong 		trace_xfs_rmap_convert_error(cur, error, _RET_IP_);
20883f165b33SDarrick J. Wong 	return error;
20893f165b33SDarrick J. Wong }
20903f165b33SDarrick J. Wong 
2091fb7d9267SDarrick J. Wong #undef	NEW
2092fb7d9267SDarrick J. Wong #undef	LEFT
2093fb7d9267SDarrick J. Wong #undef	RIGHT
2094fb7d9267SDarrick J. Wong #undef	PREV
2095fb7d9267SDarrick J. Wong 
2096ceeb9c83SDarrick J. Wong /*
2097ceeb9c83SDarrick J. Wong  * Find an extent in the rmap btree and unmap it.  For rmap extent types that
2098ceeb9c83SDarrick J. Wong  * can overlap (data fork rmaps on reflink filesystems) we must be careful
2099ceeb9c83SDarrick J. Wong  * that the prev/next records in the btree might belong to another owner.
2100ceeb9c83SDarrick J. Wong  * Therefore we must use delete+insert to alter any of the key fields.
2101ceeb9c83SDarrick J. Wong  *
2102ceeb9c83SDarrick J. Wong  * For every other situation there can only be one owner for a given extent,
2103ceeb9c83SDarrick J. Wong  * so we can call the regular _free function.
2104ceeb9c83SDarrick J. Wong  */
2105ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_unmap_shared(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)2106ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared(
2107ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur		*cur,
2108ceeb9c83SDarrick J. Wong 	xfs_agblock_t			bno,
2109ceeb9c83SDarrick J. Wong 	xfs_extlen_t			len,
2110ceeb9c83SDarrick J. Wong 	bool				unwritten,
211166e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
2112ceeb9c83SDarrick J. Wong {
2113ceeb9c83SDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
2114ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec		ltrec;
2115ceeb9c83SDarrick J. Wong 	uint64_t			ltoff;
2116ceeb9c83SDarrick J. Wong 	int				error = 0;
2117ceeb9c83SDarrick J. Wong 	int				i;
2118ceeb9c83SDarrick J. Wong 	uint64_t			owner;
2119ceeb9c83SDarrick J. Wong 	uint64_t			offset;
2120ceeb9c83SDarrick J. Wong 	unsigned int			flags;
2121ceeb9c83SDarrick J. Wong 
2122ceeb9c83SDarrick J. Wong 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2123ceeb9c83SDarrick J. Wong 	if (unwritten)
2124ceeb9c83SDarrick J. Wong 		flags |= XFS_RMAP_UNWRITTEN;
212547492ed1SDarrick J. Wong 	trace_xfs_rmap_unmap(cur, bno, len, unwritten, oinfo);
2126ceeb9c83SDarrick J. Wong 
2127ceeb9c83SDarrick J. Wong 	/*
2128ceeb9c83SDarrick J. Wong 	 * We should always have a left record because there's a static record
2129ceeb9c83SDarrick J. Wong 	 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2130ceeb9c83SDarrick J. Wong 	 * will not ever be removed from the tree.
2131ceeb9c83SDarrick J. Wong 	 */
2132ceeb9c83SDarrick J. Wong 	error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2133ceeb9c83SDarrick J. Wong 			&ltrec, &i);
2134ceeb9c83SDarrick J. Wong 	if (error)
2135ceeb9c83SDarrick J. Wong 		goto out_error;
2136f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, i != 1)) {
2137989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
2138f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
2139f9e03706SDarrick J. Wong 		goto out_error;
2140f9e03706SDarrick J. Wong 	}
2141ceeb9c83SDarrick J. Wong 	ltoff = ltrec.rm_offset;
2142ceeb9c83SDarrick J. Wong 
2143ceeb9c83SDarrick J. Wong 	/* Make sure the extent we found covers the entire freeing range. */
2144f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp,
2145f9e03706SDarrick J. Wong 			   ltrec.rm_startblock > bno ||
2146f9e03706SDarrick J. Wong 			   ltrec.rm_startblock + ltrec.rm_blockcount <
2147f9e03706SDarrick J. Wong 			   bno + len)) {
2148989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
2149f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
2150f9e03706SDarrick J. Wong 		goto out_error;
2151f9e03706SDarrick J. Wong 	}
2152ceeb9c83SDarrick J. Wong 
2153ceeb9c83SDarrick J. Wong 	/* Make sure the owner matches what we expect to find in the tree. */
2154f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
2155989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
2156f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
2157f9e03706SDarrick J. Wong 		goto out_error;
2158f9e03706SDarrick J. Wong 	}
2159ceeb9c83SDarrick J. Wong 
2160ceeb9c83SDarrick J. Wong 	/* Make sure the unwritten flag matches. */
2161f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp,
2162f9e03706SDarrick J. Wong 			   (flags & XFS_RMAP_UNWRITTEN) !=
2163f9e03706SDarrick J. Wong 			   (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2164989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
2165f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
2166f9e03706SDarrick J. Wong 		goto out_error;
2167f9e03706SDarrick J. Wong 	}
2168ceeb9c83SDarrick J. Wong 
2169ceeb9c83SDarrick J. Wong 	/* Check the offset. */
2170f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2171989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
2172f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
2173f9e03706SDarrick J. Wong 		goto out_error;
2174f9e03706SDarrick J. Wong 	}
2175f9e03706SDarrick J. Wong 	if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2176989d5ec3SDarrick J. Wong 		xfs_btree_mark_sick(cur);
2177f9e03706SDarrick J. Wong 		error = -EFSCORRUPTED;
2178f9e03706SDarrick J. Wong 		goto out_error;
2179f9e03706SDarrick J. Wong 	}
2180ceeb9c83SDarrick J. Wong 
2181ceeb9c83SDarrick J. Wong 	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2182ceeb9c83SDarrick J. Wong 		/* Exact match, simply remove the record from rmap tree. */
2183ceeb9c83SDarrick J. Wong 		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2184ceeb9c83SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
2185ceeb9c83SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags);
2186ceeb9c83SDarrick J. Wong 		if (error)
2187ceeb9c83SDarrick J. Wong 			goto out_error;
2188ceeb9c83SDarrick J. Wong 	} else if (ltrec.rm_startblock == bno) {
2189ceeb9c83SDarrick J. Wong 		/*
2190ceeb9c83SDarrick J. Wong 		 * Overlap left hand side of extent: move the start, trim the
2191ceeb9c83SDarrick J. Wong 		 * length and update the current record.
2192ceeb9c83SDarrick J. Wong 		 *
2193ceeb9c83SDarrick J. Wong 		 *       ltbno                ltlen
2194ceeb9c83SDarrick J. Wong 		 * Orig:    |oooooooooooooooooooo|
2195ceeb9c83SDarrick J. Wong 		 * Freeing: |fffffffff|
2196ceeb9c83SDarrick J. Wong 		 * Result:            |rrrrrrrrrr|
2197ceeb9c83SDarrick J. Wong 		 *         bno       len
2198ceeb9c83SDarrick J. Wong 		 */
2199ceeb9c83SDarrick J. Wong 
2200ceeb9c83SDarrick J. Wong 		/* Delete prev rmap. */
2201ceeb9c83SDarrick J. Wong 		error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2202ceeb9c83SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
2203ceeb9c83SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags);
2204ceeb9c83SDarrick J. Wong 		if (error)
2205ceeb9c83SDarrick J. Wong 			goto out_error;
2206ceeb9c83SDarrick J. Wong 
2207ceeb9c83SDarrick J. Wong 		/* Add an rmap at the new offset. */
2208ceeb9c83SDarrick J. Wong 		ltrec.rm_startblock += len;
2209ceeb9c83SDarrick J. Wong 		ltrec.rm_blockcount -= len;
2210ceeb9c83SDarrick J. Wong 		ltrec.rm_offset += len;
2211ceeb9c83SDarrick J. Wong 		error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2212ceeb9c83SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
2213ceeb9c83SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags);
2214ceeb9c83SDarrick J. Wong 		if (error)
2215ceeb9c83SDarrick J. Wong 			goto out_error;
2216ceeb9c83SDarrick J. Wong 	} else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2217ceeb9c83SDarrick J. Wong 		/*
2218ceeb9c83SDarrick J. Wong 		 * Overlap right hand side of extent: trim the length and
2219ceeb9c83SDarrick J. Wong 		 * update the current record.
2220ceeb9c83SDarrick J. Wong 		 *
2221ceeb9c83SDarrick J. Wong 		 *       ltbno                ltlen
2222ceeb9c83SDarrick J. Wong 		 * Orig:    |oooooooooooooooooooo|
2223ceeb9c83SDarrick J. Wong 		 * Freeing:            |fffffffff|
2224ceeb9c83SDarrick J. Wong 		 * Result:  |rrrrrrrrrr|
2225ceeb9c83SDarrick J. Wong 		 *                    bno       len
2226ceeb9c83SDarrick J. Wong 		 */
2227ceeb9c83SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2228ceeb9c83SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
2229ceeb9c83SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags, &i);
2230ceeb9c83SDarrick J. Wong 		if (error)
2231ceeb9c83SDarrick J. Wong 			goto out_error;
2232f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2233989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
2234f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
2235f9e03706SDarrick J. Wong 			goto out_error;
2236f9e03706SDarrick J. Wong 		}
2237ceeb9c83SDarrick J. Wong 		ltrec.rm_blockcount -= len;
2238ceeb9c83SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
2239ceeb9c83SDarrick J. Wong 		if (error)
2240ceeb9c83SDarrick J. Wong 			goto out_error;
2241ceeb9c83SDarrick J. Wong 	} else {
2242ceeb9c83SDarrick J. Wong 		/*
2243ceeb9c83SDarrick J. Wong 		 * Overlap middle of extent: trim the length of the existing
2244ceeb9c83SDarrick J. Wong 		 * record to the length of the new left-extent size, increment
2245ceeb9c83SDarrick J. Wong 		 * the insertion position so we can insert a new record
2246ceeb9c83SDarrick J. Wong 		 * containing the remaining right-extent space.
2247ceeb9c83SDarrick J. Wong 		 *
2248ceeb9c83SDarrick J. Wong 		 *       ltbno                ltlen
2249ceeb9c83SDarrick J. Wong 		 * Orig:    |oooooooooooooooooooo|
2250ceeb9c83SDarrick J. Wong 		 * Freeing:       |fffffffff|
2251ceeb9c83SDarrick J. Wong 		 * Result:  |rrrrr|         |rrrr|
2252ceeb9c83SDarrick J. Wong 		 *               bno       len
2253ceeb9c83SDarrick J. Wong 		 */
2254ceeb9c83SDarrick J. Wong 		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
2255ceeb9c83SDarrick J. Wong 
2256ceeb9c83SDarrick J. Wong 		/* Shrink the left side of the rmap */
2257ceeb9c83SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2258ceeb9c83SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
2259ceeb9c83SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags, &i);
2260ceeb9c83SDarrick J. Wong 		if (error)
2261ceeb9c83SDarrick J. Wong 			goto out_error;
2262f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2263989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
2264f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
2265f9e03706SDarrick J. Wong 			goto out_error;
2266f9e03706SDarrick J. Wong 		}
2267ceeb9c83SDarrick J. Wong 		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2268ceeb9c83SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
2269ceeb9c83SDarrick J. Wong 		if (error)
2270ceeb9c83SDarrick J. Wong 			goto out_error;
2271ceeb9c83SDarrick J. Wong 
2272ceeb9c83SDarrick J. Wong 		/* Add an rmap at the new offset */
2273ceeb9c83SDarrick J. Wong 		error = xfs_rmap_insert(cur, bno + len,
2274ceeb9c83SDarrick J. Wong 				orig_len - len - ltrec.rm_blockcount,
2275ceeb9c83SDarrick J. Wong 				ltrec.rm_owner, offset + len,
2276ceeb9c83SDarrick J. Wong 				ltrec.rm_flags);
2277ceeb9c83SDarrick J. Wong 		if (error)
2278ceeb9c83SDarrick J. Wong 			goto out_error;
2279ceeb9c83SDarrick J. Wong 	}
2280ceeb9c83SDarrick J. Wong 
228147492ed1SDarrick J. Wong 	trace_xfs_rmap_unmap_done(cur, bno, len, unwritten, oinfo);
2282ceeb9c83SDarrick J. Wong out_error:
2283ceeb9c83SDarrick J. Wong 	if (error)
228471f5a17eSDarrick J. Wong 		trace_xfs_rmap_unmap_error(cur, error, _RET_IP_);
2285ceeb9c83SDarrick J. Wong 	return error;
2286ceeb9c83SDarrick J. Wong }
2287ceeb9c83SDarrick J. Wong 
2288ceeb9c83SDarrick J. Wong /*
2289ceeb9c83SDarrick J. Wong  * Find an extent in the rmap btree and map it.  For rmap extent types that
2290ceeb9c83SDarrick J. Wong  * can overlap (data fork rmaps on reflink filesystems) we must be careful
2291ceeb9c83SDarrick J. Wong  * that the prev/next records in the btree might belong to another owner.
2292ceeb9c83SDarrick J. Wong  * Therefore we must use delete+insert to alter any of the key fields.
2293ceeb9c83SDarrick J. Wong  *
2294ceeb9c83SDarrick J. Wong  * For every other situation there can only be one owner for a given extent,
2295ceeb9c83SDarrick J. Wong  * so we can call the regular _alloc function.
2296ceeb9c83SDarrick J. Wong  */
2297ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_map_shared(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,bool unwritten,const struct xfs_owner_info * oinfo)2298ceeb9c83SDarrick J. Wong xfs_rmap_map_shared(
2299ceeb9c83SDarrick J. Wong 	struct xfs_btree_cur		*cur,
2300ceeb9c83SDarrick J. Wong 	xfs_agblock_t			bno,
2301ceeb9c83SDarrick J. Wong 	xfs_extlen_t			len,
2302ceeb9c83SDarrick J. Wong 	bool				unwritten,
230366e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo)
2304ceeb9c83SDarrick J. Wong {
2305ceeb9c83SDarrick J. Wong 	struct xfs_mount		*mp = cur->bc_mp;
2306ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec		ltrec;
2307ceeb9c83SDarrick J. Wong 	struct xfs_rmap_irec		gtrec;
2308ceeb9c83SDarrick J. Wong 	int				have_gt;
2309ceeb9c83SDarrick J. Wong 	int				have_lt;
2310ceeb9c83SDarrick J. Wong 	int				error = 0;
2311ceeb9c83SDarrick J. Wong 	int				i;
2312ceeb9c83SDarrick J. Wong 	uint64_t			owner;
2313ceeb9c83SDarrick J. Wong 	uint64_t			offset;
2314ceeb9c83SDarrick J. Wong 	unsigned int			flags = 0;
2315ceeb9c83SDarrick J. Wong 
2316ceeb9c83SDarrick J. Wong 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2317ceeb9c83SDarrick J. Wong 	if (unwritten)
2318ceeb9c83SDarrick J. Wong 		flags |= XFS_RMAP_UNWRITTEN;
231947492ed1SDarrick J. Wong 	trace_xfs_rmap_map(cur, bno, len, unwritten, oinfo);
2320ceeb9c83SDarrick J. Wong 
2321ceeb9c83SDarrick J. Wong 	/* Is there a left record that abuts our range? */
2322ceeb9c83SDarrick J. Wong 	error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2323ceeb9c83SDarrick J. Wong 			&ltrec, &have_lt);
2324ceeb9c83SDarrick J. Wong 	if (error)
2325ceeb9c83SDarrick J. Wong 		goto out_error;
2326ceeb9c83SDarrick J. Wong 	if (have_lt &&
2327ceeb9c83SDarrick J. Wong 	    !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2328ceeb9c83SDarrick J. Wong 		have_lt = 0;
2329ceeb9c83SDarrick J. Wong 
2330ceeb9c83SDarrick J. Wong 	/* Is there a right record that abuts our range? */
2331ceeb9c83SDarrick J. Wong 	error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2332ceeb9c83SDarrick J. Wong 			flags, &have_gt);
2333ceeb9c83SDarrick J. Wong 	if (error)
2334ceeb9c83SDarrick J. Wong 		goto out_error;
2335ceeb9c83SDarrick J. Wong 	if (have_gt) {
2336ceeb9c83SDarrick J. Wong 		error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2337ceeb9c83SDarrick J. Wong 		if (error)
2338ceeb9c83SDarrick J. Wong 			goto out_error;
2339f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2340989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
2341f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
2342f9e03706SDarrick J. Wong 			goto out_error;
2343f9e03706SDarrick J. Wong 		}
234447492ed1SDarrick J. Wong 		trace_xfs_rmap_find_right_neighbor_result(cur,
234547492ed1SDarrick J. Wong 				gtrec.rm_startblock, gtrec.rm_blockcount,
234647492ed1SDarrick J. Wong 				gtrec.rm_owner, gtrec.rm_offset,
234747492ed1SDarrick J. Wong 				gtrec.rm_flags);
2348ceeb9c83SDarrick J. Wong 
2349ceeb9c83SDarrick J. Wong 		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2350ceeb9c83SDarrick J. Wong 			have_gt = 0;
2351ceeb9c83SDarrick J. Wong 	}
2352ceeb9c83SDarrick J. Wong 
2353ceeb9c83SDarrick J. Wong 	if (have_lt &&
2354ceeb9c83SDarrick J. Wong 	    ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2355ceeb9c83SDarrick J. Wong 	    ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2356ceeb9c83SDarrick J. Wong 		/*
2357ceeb9c83SDarrick J. Wong 		 * Left edge contiguous, merge into left record.
2358ceeb9c83SDarrick J. Wong 		 *
2359ceeb9c83SDarrick J. Wong 		 *       ltbno     ltlen
2360ceeb9c83SDarrick J. Wong 		 * orig:   |ooooooooo|
2361ceeb9c83SDarrick J. Wong 		 * adding:           |aaaaaaaaa|
2362ceeb9c83SDarrick J. Wong 		 * result: |rrrrrrrrrrrrrrrrrrr|
2363ceeb9c83SDarrick J. Wong 		 *                  bno       len
2364ceeb9c83SDarrick J. Wong 		 */
2365ceeb9c83SDarrick J. Wong 		ltrec.rm_blockcount += len;
2366ceeb9c83SDarrick J. Wong 		if (have_gt &&
2367ceeb9c83SDarrick J. Wong 		    bno + len == gtrec.rm_startblock &&
2368ceeb9c83SDarrick J. Wong 		    offset + len == gtrec.rm_offset) {
2369ceeb9c83SDarrick J. Wong 			/*
2370ceeb9c83SDarrick J. Wong 			 * Right edge also contiguous, delete right record
2371ceeb9c83SDarrick J. Wong 			 * and merge into left record.
2372ceeb9c83SDarrick J. Wong 			 *
2373ceeb9c83SDarrick J. Wong 			 *       ltbno     ltlen    gtbno     gtlen
2374ceeb9c83SDarrick J. Wong 			 * orig:   |ooooooooo|         |ooooooooo|
2375ceeb9c83SDarrick J. Wong 			 * adding:           |aaaaaaaaa|
2376ceeb9c83SDarrick J. Wong 			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2377ceeb9c83SDarrick J. Wong 			 */
2378ceeb9c83SDarrick J. Wong 			ltrec.rm_blockcount += gtrec.rm_blockcount;
2379ceeb9c83SDarrick J. Wong 			error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2380ceeb9c83SDarrick J. Wong 					gtrec.rm_blockcount, gtrec.rm_owner,
2381ceeb9c83SDarrick J. Wong 					gtrec.rm_offset, gtrec.rm_flags);
2382ceeb9c83SDarrick J. Wong 			if (error)
2383ceeb9c83SDarrick J. Wong 				goto out_error;
2384ceeb9c83SDarrick J. Wong 		}
2385ceeb9c83SDarrick J. Wong 
2386ceeb9c83SDarrick J. Wong 		/* Point the cursor back to the left record and update. */
2387ceeb9c83SDarrick J. Wong 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2388ceeb9c83SDarrick J. Wong 				ltrec.rm_blockcount, ltrec.rm_owner,
2389ceeb9c83SDarrick J. Wong 				ltrec.rm_offset, ltrec.rm_flags, &i);
2390ceeb9c83SDarrick J. Wong 		if (error)
2391ceeb9c83SDarrick J. Wong 			goto out_error;
2392f9e03706SDarrick J. Wong 		if (XFS_IS_CORRUPT(mp, i != 1)) {
2393989d5ec3SDarrick J. Wong 			xfs_btree_mark_sick(cur);
2394f9e03706SDarrick J. Wong 			error = -EFSCORRUPTED;
2395f9e03706SDarrick J. Wong 			goto out_error;
2396f9e03706SDarrick J. Wong 		}
2397ceeb9c83SDarrick J. Wong 
2398ceeb9c83SDarrick J. Wong 		error = xfs_rmap_update(cur, &ltrec);
2399ceeb9c83SDarrick J. Wong 		if (error)
2400ceeb9c83SDarrick J. Wong 			goto out_error;
2401ceeb9c83SDarrick J. Wong 	} else if (have_gt &&
2402ceeb9c83SDarrick J. Wong 		   bno + len == gtrec.rm_startblock &&
2403ceeb9c83SDarrick J. Wong 		   offset + len == gtrec.rm_offset) {
2404ceeb9c83SDarrick J. Wong 		/*
2405ceeb9c83SDarrick J. Wong 		 * Right edge contiguous, merge into right record.
2406ceeb9c83SDarrick J. Wong 		 *
2407ceeb9c83SDarrick J. Wong 		 *                 gtbno     gtlen
2408ceeb9c83SDarrick J. Wong 		 * Orig:             |ooooooooo|
2409ceeb9c83SDarrick J. Wong 		 * adding: |aaaaaaaaa|
2410ceeb9c83SDarrick J. Wong 		 * Result: |rrrrrrrrrrrrrrrrrrr|
2411ceeb9c83SDarrick J. Wong 		 *        bno       len
2412ceeb9c83SDarrick J. Wong 		 */
2413ceeb9c83SDarrick J. Wong 		/* Delete the old record. */
2414ceeb9c83SDarrick J. Wong 		error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2415ceeb9c83SDarrick J. Wong 				gtrec.rm_blockcount, gtrec.rm_owner,
2416ceeb9c83SDarrick J. Wong 				gtrec.rm_offset, gtrec.rm_flags);
2417ceeb9c83SDarrick J. Wong 		if (error)
2418ceeb9c83SDarrick J. Wong 			goto out_error;
2419ceeb9c83SDarrick J. Wong 
2420ceeb9c83SDarrick J. Wong 		/* Move the start and re-add it. */
2421ceeb9c83SDarrick J. Wong 		gtrec.rm_startblock = bno;
2422ceeb9c83SDarrick J. Wong 		gtrec.rm_blockcount += len;
2423ceeb9c83SDarrick J. Wong 		gtrec.rm_offset = offset;
2424ceeb9c83SDarrick J. Wong 		error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2425ceeb9c83SDarrick J. Wong 				gtrec.rm_blockcount, gtrec.rm_owner,
2426ceeb9c83SDarrick J. Wong 				gtrec.rm_offset, gtrec.rm_flags);
2427ceeb9c83SDarrick J. Wong 		if (error)
2428ceeb9c83SDarrick J. Wong 			goto out_error;
2429ceeb9c83SDarrick J. Wong 	} else {
2430ceeb9c83SDarrick J. Wong 		/*
2431ceeb9c83SDarrick J. Wong 		 * No contiguous edge with identical owner, insert
2432ceeb9c83SDarrick J. Wong 		 * new record at current cursor position.
2433ceeb9c83SDarrick J. Wong 		 */
2434ceeb9c83SDarrick J. Wong 		error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2435ceeb9c83SDarrick J. Wong 		if (error)
2436ceeb9c83SDarrick J. Wong 			goto out_error;
2437ceeb9c83SDarrick J. Wong 	}
2438ceeb9c83SDarrick J. Wong 
243947492ed1SDarrick J. Wong 	trace_xfs_rmap_map_done(cur, bno, len, unwritten, oinfo);
2440ceeb9c83SDarrick J. Wong out_error:
2441ceeb9c83SDarrick J. Wong 	if (error)
244271f5a17eSDarrick J. Wong 		trace_xfs_rmap_map_error(cur, error, _RET_IP_);
2443ceeb9c83SDarrick J. Wong 	return error;
2444ceeb9c83SDarrick J. Wong }
2445ceeb9c83SDarrick J. Wong 
24464d4f86b4SDarrick J. Wong /* Insert a raw rmap into the rmapbt. */
24474d4f86b4SDarrick J. Wong int
xfs_rmap_map_raw(struct xfs_btree_cur * cur,struct xfs_rmap_irec * rmap)24484d4f86b4SDarrick J. Wong xfs_rmap_map_raw(
24494d4f86b4SDarrick J. Wong 	struct xfs_btree_cur	*cur,
24504d4f86b4SDarrick J. Wong 	struct xfs_rmap_irec	*rmap)
24514d4f86b4SDarrick J. Wong {
24524d4f86b4SDarrick J. Wong 	struct xfs_owner_info	oinfo;
24534d4f86b4SDarrick J. Wong 
24544787fc80SDarrick J. Wong 	xfs_owner_info_pack(&oinfo, rmap->rm_owner, rmap->rm_offset,
24554787fc80SDarrick J. Wong 			rmap->rm_flags);
24564d4f86b4SDarrick J. Wong 
24574787fc80SDarrick J. Wong 	if ((rmap->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
24584787fc80SDarrick J. Wong 			       XFS_RMAP_UNWRITTEN)) ||
24594787fc80SDarrick J. Wong 	    XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
24604d4f86b4SDarrick J. Wong 		return xfs_rmap_map(cur, rmap->rm_startblock,
24614d4f86b4SDarrick J. Wong 				rmap->rm_blockcount,
24624d4f86b4SDarrick J. Wong 				rmap->rm_flags & XFS_RMAP_UNWRITTEN,
24634d4f86b4SDarrick J. Wong 				&oinfo);
24644d4f86b4SDarrick J. Wong 
24654d4f86b4SDarrick J. Wong 	return xfs_rmap_map_shared(cur, rmap->rm_startblock,
24664d4f86b4SDarrick J. Wong 			rmap->rm_blockcount,
24674d4f86b4SDarrick J. Wong 			rmap->rm_flags & XFS_RMAP_UNWRITTEN,
24684d4f86b4SDarrick J. Wong 			&oinfo);
24694d4f86b4SDarrick J. Wong }
24704d4f86b4SDarrick J. Wong 
2471c543838aSDarrick J. Wong struct xfs_rmap_query_range_info {
2472c543838aSDarrick J. Wong 	xfs_rmap_query_range_fn	fn;
2473c543838aSDarrick J. Wong 	void				*priv;
2474c543838aSDarrick J. Wong };
2475c543838aSDarrick J. Wong 
2476c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */
2477c543838aSDarrick J. Wong STATIC int
xfs_rmap_query_range_helper(struct xfs_btree_cur * cur,const union xfs_btree_rec * rec,void * priv)2478c543838aSDarrick J. Wong xfs_rmap_query_range_helper(
2479c543838aSDarrick J. Wong 	struct xfs_btree_cur		*cur,
2480159eb69dSDarrick J. Wong 	const union xfs_btree_rec	*rec,
2481c543838aSDarrick J. Wong 	void				*priv)
2482c543838aSDarrick J. Wong {
2483c543838aSDarrick J. Wong 	struct xfs_rmap_query_range_info	*query = priv;
2484c543838aSDarrick J. Wong 	struct xfs_rmap_irec			irec;
2485ee12eaaaSDarrick J. Wong 	xfs_failaddr_t				fa;
2486c543838aSDarrick J. Wong 
2487ee12eaaaSDarrick J. Wong 	fa = xfs_rmap_btrec_to_irec(rec, &irec);
2488ee12eaaaSDarrick J. Wong 	if (!fa)
24894787fc80SDarrick J. Wong 		fa = xfs_rmap_check_btrec(cur, &irec);
2490ee12eaaaSDarrick J. Wong 	if (fa)
2491ee12eaaaSDarrick J. Wong 		return xfs_rmap_complain_bad_rec(cur, fa, &irec);
249239ab26d5SDarrick J. Wong 
2493c543838aSDarrick J. Wong 	return query->fn(cur, &irec, query->priv);
2494c543838aSDarrick J. Wong }
2495c543838aSDarrick J. Wong 
2496c543838aSDarrick J. Wong /* Find all rmaps between two keys. */
2497c543838aSDarrick J. Wong int
xfs_rmap_query_range(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * low_rec,const struct xfs_rmap_irec * high_rec,xfs_rmap_query_range_fn fn,void * priv)2498c543838aSDarrick J. Wong xfs_rmap_query_range(
2499c543838aSDarrick J. Wong 	struct xfs_btree_cur			*cur,
250004dcb474SDarrick J. Wong 	const struct xfs_rmap_irec		*low_rec,
250104dcb474SDarrick J. Wong 	const struct xfs_rmap_irec		*high_rec,
2502c543838aSDarrick J. Wong 	xfs_rmap_query_range_fn			fn,
2503c543838aSDarrick J. Wong 	void					*priv)
2504c543838aSDarrick J. Wong {
250575dc0345SDarrick J. Wong 	union xfs_btree_irec			low_brec = { .r = *low_rec };
250675dc0345SDarrick J. Wong 	union xfs_btree_irec			high_brec = { .r = *high_rec };
250775dc0345SDarrick J. Wong 	struct xfs_rmap_query_range_info	query = { .priv = priv, .fn = fn };
2508c543838aSDarrick J. Wong 
2509c543838aSDarrick J. Wong 	return xfs_btree_query_range(cur, &low_brec, &high_brec,
2510c543838aSDarrick J. Wong 			xfs_rmap_query_range_helper, &query);
2511e9a2599aSDarrick J. Wong }
2512e9a2599aSDarrick J. Wong 
2513e9a2599aSDarrick J. Wong /* Find all rmaps. */
2514e9a2599aSDarrick J. Wong int
xfs_rmap_query_all(struct xfs_btree_cur * cur,xfs_rmap_query_range_fn fn,void * priv)2515e9a2599aSDarrick J. Wong xfs_rmap_query_all(
2516e9a2599aSDarrick J. Wong 	struct xfs_btree_cur			*cur,
2517e9a2599aSDarrick J. Wong 	xfs_rmap_query_range_fn			fn,
2518e9a2599aSDarrick J. Wong 	void					*priv)
2519e9a2599aSDarrick J. Wong {
2520e9a2599aSDarrick J. Wong 	struct xfs_rmap_query_range_info	query;
2521e9a2599aSDarrick J. Wong 
2522e9a2599aSDarrick J. Wong 	query.priv = priv;
2523e9a2599aSDarrick J. Wong 	query.fn = fn;
2524e9a2599aSDarrick J. Wong 	return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2525c543838aSDarrick J. Wong }
25269c194644SDarrick J. Wong 
25277e1b84b2SDarrick J. Wong /* Commit an rmap operation into the ondisk tree. */
25287e1b84b2SDarrick J. Wong int
__xfs_rmap_finish_intent(struct xfs_btree_cur * rcur,enum xfs_rmap_intent_type op,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo,bool unwritten)25297e1b84b2SDarrick J. Wong __xfs_rmap_finish_intent(
25307e1b84b2SDarrick J. Wong 	struct xfs_btree_cur		*rcur,
25317e1b84b2SDarrick J. Wong 	enum xfs_rmap_intent_type	op,
25327e1b84b2SDarrick J. Wong 	xfs_agblock_t			bno,
25337e1b84b2SDarrick J. Wong 	xfs_extlen_t			len,
25347e1b84b2SDarrick J. Wong 	const struct xfs_owner_info	*oinfo,
25357e1b84b2SDarrick J. Wong 	bool				unwritten)
25367e1b84b2SDarrick J. Wong {
25377e1b84b2SDarrick J. Wong 	switch (op) {
25387e1b84b2SDarrick J. Wong 	case XFS_RMAP_ALLOC:
25397e1b84b2SDarrick J. Wong 	case XFS_RMAP_MAP:
25407e1b84b2SDarrick J. Wong 		return xfs_rmap_map(rcur, bno, len, unwritten, oinfo);
25417e1b84b2SDarrick J. Wong 	case XFS_RMAP_MAP_SHARED:
25427e1b84b2SDarrick J. Wong 		return xfs_rmap_map_shared(rcur, bno, len, unwritten, oinfo);
25437e1b84b2SDarrick J. Wong 	case XFS_RMAP_FREE:
25447e1b84b2SDarrick J. Wong 	case XFS_RMAP_UNMAP:
25457e1b84b2SDarrick J. Wong 		return xfs_rmap_unmap(rcur, bno, len, unwritten, oinfo);
25467e1b84b2SDarrick J. Wong 	case XFS_RMAP_UNMAP_SHARED:
25477e1b84b2SDarrick J. Wong 		return xfs_rmap_unmap_shared(rcur, bno, len, unwritten, oinfo);
25487e1b84b2SDarrick J. Wong 	case XFS_RMAP_CONVERT:
25497e1b84b2SDarrick J. Wong 		return xfs_rmap_convert(rcur, bno, len, !unwritten, oinfo);
25507e1b84b2SDarrick J. Wong 	case XFS_RMAP_CONVERT_SHARED:
25517e1b84b2SDarrick J. Wong 		return xfs_rmap_convert_shared(rcur, bno, len, !unwritten,
25527e1b84b2SDarrick J. Wong 				oinfo);
25537e1b84b2SDarrick J. Wong 	default:
25547e1b84b2SDarrick J. Wong 		ASSERT(0);
25557e1b84b2SDarrick J. Wong 		return -EFSCORRUPTED;
25567e1b84b2SDarrick J. Wong 	}
25577e1b84b2SDarrick J. Wong }
25587e1b84b2SDarrick J. Wong 
25599c194644SDarrick J. Wong /*
25609c194644SDarrick J. Wong  * Process one of the deferred rmap operations.  We pass back the
25619c194644SDarrick J. Wong  * btree cursor to maintain our lock on the rmapbt between calls.
25629c194644SDarrick J. Wong  * This saves time and eliminates a buffer deadlock between the
25639c194644SDarrick J. Wong  * superblock and the AGF because we'll always grab them in the same
25649c194644SDarrick J. Wong  * order.
25659c194644SDarrick J. Wong  */
25669c194644SDarrick J. Wong int
xfs_rmap_finish_one(struct xfs_trans * tp,struct xfs_rmap_intent * ri,struct xfs_btree_cur ** pcur)25679c194644SDarrick J. Wong xfs_rmap_finish_one(
25689c194644SDarrick J. Wong 	struct xfs_trans		*tp,
25691534328bSDarrick J. Wong 	struct xfs_rmap_intent		*ri,
25709c194644SDarrick J. Wong 	struct xfs_btree_cur		**pcur)
25719c194644SDarrick J. Wong {
2572fbe8c7e1SDarrick J. Wong 	struct xfs_owner_info		oinfo;
25739c194644SDarrick J. Wong 	struct xfs_mount		*mp = tp->t_mountp;
2574905af726SChristoph Hellwig 	struct xfs_btree_cur		*rcur = *pcur;
25759c194644SDarrick J. Wong 	struct xfs_buf			*agbp = NULL;
25769c194644SDarrick J. Wong 	xfs_agblock_t			bno;
25779c194644SDarrick J. Wong 	bool				unwritten;
2578fbe8c7e1SDarrick J. Wong 	int				error = 0;
25799c194644SDarrick J. Wong 
2580fbe8c7e1SDarrick J. Wong 	trace_xfs_rmap_deferred(mp, ri);
25819c194644SDarrick J. Wong 
2582c13418e8SDarrick J. Wong 	if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
2583c13418e8SDarrick J. Wong 		return -EIO;
25849c194644SDarrick J. Wong 
25859c194644SDarrick J. Wong 	/*
25869c194644SDarrick J. Wong 	 * If we haven't gotten a cursor or the cursor AG doesn't match
25879c194644SDarrick J. Wong 	 * the startblock, get one now.
25889c194644SDarrick J. Wong 	 */
2589c13418e8SDarrick J. Wong 	if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
25908363b436SChristoph Hellwig 		xfs_btree_del_cursor(rcur, 0);
25919c194644SDarrick J. Wong 		rcur = NULL;
25929c194644SDarrick J. Wong 		*pcur = NULL;
25939c194644SDarrick J. Wong 	}
25949c194644SDarrick J. Wong 	if (rcur == NULL) {
25959c194644SDarrick J. Wong 		/*
25969c194644SDarrick J. Wong 		 * Refresh the freelist before we start changing the
25979c194644SDarrick J. Wong 		 * rmapbt, because a shape change could cause us to
25989c194644SDarrick J. Wong 		 * allocate blocks.
25999c194644SDarrick J. Wong 		 */
2600c13418e8SDarrick J. Wong 		error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
2601989d5ec3SDarrick J. Wong 		if (error) {
2602989d5ec3SDarrick J. Wong 			xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
2603c13418e8SDarrick J. Wong 			return error;
2604989d5ec3SDarrick J. Wong 		}
2605989d5ec3SDarrick J. Wong 		if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2606989d5ec3SDarrick J. Wong 			xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
2607c13418e8SDarrick J. Wong 			return -EFSCORRUPTED;
2608989d5ec3SDarrick J. Wong 		}
26099c194644SDarrick J. Wong 
2610905af726SChristoph Hellwig 		*pcur = rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
26119c194644SDarrick J. Wong 	}
26129c194644SDarrick J. Wong 
26131534328bSDarrick J. Wong 	xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
26141534328bSDarrick J. Wong 			ri->ri_bmap.br_startoff);
26151534328bSDarrick J. Wong 	unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
26161534328bSDarrick J. Wong 	bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
26179c194644SDarrick J. Wong 
26187e1b84b2SDarrick J. Wong 	error = __xfs_rmap_finish_intent(rcur, ri->ri_type, bno,
26197e1b84b2SDarrick J. Wong 			ri->ri_bmap.br_blockcount, &oinfo, unwritten);
26207e1b84b2SDarrick J. Wong 	if (error)
26219c194644SDarrick J. Wong 		return error;
26227e1b84b2SDarrick J. Wong 
26237e1b84b2SDarrick J. Wong 	xfs_rmap_update_hook(tp, ri->ri_pag, ri->ri_type, bno,
26247e1b84b2SDarrick J. Wong 			ri->ri_bmap.br_blockcount, unwritten, &oinfo);
26257e1b84b2SDarrick J. Wong 	return 0;
26269c194644SDarrick J. Wong }
26279c194644SDarrick J. Wong 
26289c194644SDarrick J. Wong /*
26299c194644SDarrick J. Wong  * Don't defer an rmap if we aren't an rmap filesystem.
26309c194644SDarrick J. Wong  */
26319c194644SDarrick J. Wong static bool
xfs_rmap_update_is_needed(struct xfs_mount * mp,int whichfork)26329c194644SDarrick J. Wong xfs_rmap_update_is_needed(
26333993baebSDarrick J. Wong 	struct xfs_mount	*mp,
26343993baebSDarrick J. Wong 	int			whichfork)
26359c194644SDarrick J. Wong {
263638c26bfdSDave Chinner 	return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
26379c194644SDarrick J. Wong }
26389c194644SDarrick J. Wong 
26399c194644SDarrick J. Wong /*
26409c194644SDarrick J. Wong  * Record a rmap intent; the list is kept sorted first by AG and then by
26419c194644SDarrick J. Wong  * increasing age.
26429c194644SDarrick J. Wong  */
2643bc46ac64SDarrick J. Wong static void
__xfs_rmap_add(struct xfs_trans * tp,enum xfs_rmap_intent_type type,uint64_t owner,int whichfork,struct xfs_bmbt_irec * bmap)26449c194644SDarrick J. Wong __xfs_rmap_add(
26450f37d178SBrian Foster 	struct xfs_trans		*tp,
26469c194644SDarrick J. Wong 	enum xfs_rmap_intent_type	type,
2647c8ce540dSDarrick J. Wong 	uint64_t			owner,
26489c194644SDarrick J. Wong 	int				whichfork,
26499c194644SDarrick J. Wong 	struct xfs_bmbt_irec		*bmap)
26509c194644SDarrick J. Wong {
26519c194644SDarrick J. Wong 	struct xfs_rmap_intent		*ri;
26529c194644SDarrick J. Wong 
26530b3a76e9SDave Chinner 	ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);
26549c194644SDarrick J. Wong 	INIT_LIST_HEAD(&ri->ri_list);
26559c194644SDarrick J. Wong 	ri->ri_type = type;
26569c194644SDarrick J. Wong 	ri->ri_owner = owner;
26579c194644SDarrick J. Wong 	ri->ri_whichfork = whichfork;
26589c194644SDarrick J. Wong 	ri->ri_bmap = *bmap;
26599c194644SDarrick J. Wong 
2660*ea7b0820SDarrick J. Wong 	xfs_rmap_defer_add(tp, ri);
26619c194644SDarrick J. Wong }
26629c194644SDarrick J. Wong 
26639c194644SDarrick J. Wong /* Map an extent into a file. */
2664bc46ac64SDarrick J. Wong void
xfs_rmap_map_extent(struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)26659c194644SDarrick J. Wong xfs_rmap_map_extent(
26660f37d178SBrian Foster 	struct xfs_trans	*tp,
26679c194644SDarrick J. Wong 	struct xfs_inode	*ip,
26689c194644SDarrick J. Wong 	int			whichfork,
26699c194644SDarrick J. Wong 	struct xfs_bmbt_irec	*PREV)
26709c194644SDarrick J. Wong {
2671d7884e6eSDarrick J. Wong 	enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2672d7884e6eSDarrick J. Wong 
26730f37d178SBrian Foster 	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2674bc46ac64SDarrick J. Wong 		return;
26759c194644SDarrick J. Wong 
2676d7884e6eSDarrick J. Wong 	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2677d7884e6eSDarrick J. Wong 		type = XFS_RMAP_MAP_SHARED;
2678d7884e6eSDarrick J. Wong 
2679d7884e6eSDarrick J. Wong 	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
26809c194644SDarrick J. Wong }
26819c194644SDarrick J. Wong 
26829c194644SDarrick J. Wong /* Unmap an extent out of a file. */
2683bc46ac64SDarrick J. Wong void
xfs_rmap_unmap_extent(struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)26849c194644SDarrick J. Wong xfs_rmap_unmap_extent(
26850f37d178SBrian Foster 	struct xfs_trans	*tp,
26869c194644SDarrick J. Wong 	struct xfs_inode	*ip,
26879c194644SDarrick J. Wong 	int			whichfork,
26889c194644SDarrick J. Wong 	struct xfs_bmbt_irec	*PREV)
26899c194644SDarrick J. Wong {
2690d7884e6eSDarrick J. Wong 	enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2691d7884e6eSDarrick J. Wong 
26920f37d178SBrian Foster 	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2693bc46ac64SDarrick J. Wong 		return;
26949c194644SDarrick J. Wong 
2695d7884e6eSDarrick J. Wong 	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2696d7884e6eSDarrick J. Wong 		type = XFS_RMAP_UNMAP_SHARED;
2697d7884e6eSDarrick J. Wong 
2698d7884e6eSDarrick J. Wong 	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
26999c194644SDarrick J. Wong }
27009c194644SDarrick J. Wong 
27010f37d178SBrian Foster /*
27020f37d178SBrian Foster  * Convert a data fork extent from unwritten to real or vice versa.
27030f37d178SBrian Foster  *
27040f37d178SBrian Foster  * Note that tp can be NULL here as no transaction is used for COW fork
27050f37d178SBrian Foster  * unwritten conversion.
27060f37d178SBrian Foster  */
2707bc46ac64SDarrick J. Wong void
xfs_rmap_convert_extent(struct xfs_mount * mp,struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)27089c194644SDarrick J. Wong xfs_rmap_convert_extent(
27099c194644SDarrick J. Wong 	struct xfs_mount	*mp,
27100f37d178SBrian Foster 	struct xfs_trans	*tp,
27119c194644SDarrick J. Wong 	struct xfs_inode	*ip,
27129c194644SDarrick J. Wong 	int			whichfork,
27139c194644SDarrick J. Wong 	struct xfs_bmbt_irec	*PREV)
27149c194644SDarrick J. Wong {
2715d7884e6eSDarrick J. Wong 	enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2716d7884e6eSDarrick J. Wong 
27173993baebSDarrick J. Wong 	if (!xfs_rmap_update_is_needed(mp, whichfork))
2718bc46ac64SDarrick J. Wong 		return;
27199c194644SDarrick J. Wong 
2720d7884e6eSDarrick J. Wong 	if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2721d7884e6eSDarrick J. Wong 		type = XFS_RMAP_CONVERT_SHARED;
2722d7884e6eSDarrick J. Wong 
2723d7884e6eSDarrick J. Wong 	__xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
27249c194644SDarrick J. Wong }
27259c194644SDarrick J. Wong 
27269c194644SDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */
2727bc46ac64SDarrick J. Wong void
xfs_rmap_alloc_extent(struct xfs_trans * tp,xfs_agnumber_t agno,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner)27289c194644SDarrick J. Wong xfs_rmap_alloc_extent(
27290f37d178SBrian Foster 	struct xfs_trans	*tp,
27309c194644SDarrick J. Wong 	xfs_agnumber_t		agno,
27319c194644SDarrick J. Wong 	xfs_agblock_t		bno,
27329c194644SDarrick J. Wong 	xfs_extlen_t		len,
2733c8ce540dSDarrick J. Wong 	uint64_t		owner)
27349c194644SDarrick J. Wong {
27359c194644SDarrick J. Wong 	struct xfs_bmbt_irec	bmap;
27369c194644SDarrick J. Wong 
27370f37d178SBrian Foster 	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2738bc46ac64SDarrick J. Wong 		return;
27399c194644SDarrick J. Wong 
27400f37d178SBrian Foster 	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
27419c194644SDarrick J. Wong 	bmap.br_blockcount = len;
27429c194644SDarrick J. Wong 	bmap.br_startoff = 0;
27439c194644SDarrick J. Wong 	bmap.br_state = XFS_EXT_NORM;
27449c194644SDarrick J. Wong 
2745bc46ac64SDarrick J. Wong 	__xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
27469c194644SDarrick J. Wong }
27479c194644SDarrick J. Wong 
27489c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */
2749bc46ac64SDarrick J. Wong void
xfs_rmap_free_extent(struct xfs_trans * tp,xfs_agnumber_t agno,xfs_agblock_t bno,xfs_extlen_t len,uint64_t owner)27509c194644SDarrick J. Wong xfs_rmap_free_extent(
27510f37d178SBrian Foster 	struct xfs_trans	*tp,
27529c194644SDarrick J. Wong 	xfs_agnumber_t		agno,
27539c194644SDarrick J. Wong 	xfs_agblock_t		bno,
27549c194644SDarrick J. Wong 	xfs_extlen_t		len,
2755c8ce540dSDarrick J. Wong 	uint64_t		owner)
27569c194644SDarrick J. Wong {
27579c194644SDarrick J. Wong 	struct xfs_bmbt_irec	bmap;
27589c194644SDarrick J. Wong 
27590f37d178SBrian Foster 	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2760bc46ac64SDarrick J. Wong 		return;
27619c194644SDarrick J. Wong 
27620f37d178SBrian Foster 	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
27639c194644SDarrick J. Wong 	bmap.br_blockcount = len;
27649c194644SDarrick J. Wong 	bmap.br_startoff = 0;
27659c194644SDarrick J. Wong 	bmap.br_state = XFS_EXT_NORM;
27669c194644SDarrick J. Wong 
2767bc46ac64SDarrick J. Wong 	__xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
27689c194644SDarrick J. Wong }
2769e89c0413SDarrick J. Wong 
2770e89c0413SDarrick J. Wong /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2771e89c0413SDarrick J. Wong int
xfs_rmap_compare(const struct xfs_rmap_irec * a,const struct xfs_rmap_irec * b)2772e89c0413SDarrick J. Wong xfs_rmap_compare(
2773e89c0413SDarrick J. Wong 	const struct xfs_rmap_irec	*a,
2774e89c0413SDarrick J. Wong 	const struct xfs_rmap_irec	*b)
2775e89c0413SDarrick J. Wong {
2776e89c0413SDarrick J. Wong 	__u64				oa;
2777e89c0413SDarrick J. Wong 	__u64				ob;
2778e89c0413SDarrick J. Wong 
2779e89c0413SDarrick J. Wong 	oa = xfs_rmap_irec_offset_pack(a);
2780e89c0413SDarrick J. Wong 	ob = xfs_rmap_irec_offset_pack(b);
2781e89c0413SDarrick J. Wong 
2782e89c0413SDarrick J. Wong 	if (a->rm_startblock < b->rm_startblock)
2783e89c0413SDarrick J. Wong 		return -1;
2784e89c0413SDarrick J. Wong 	else if (a->rm_startblock > b->rm_startblock)
2785e89c0413SDarrick J. Wong 		return 1;
2786e89c0413SDarrick J. Wong 	else if (a->rm_owner < b->rm_owner)
2787e89c0413SDarrick J. Wong 		return -1;
2788e89c0413SDarrick J. Wong 	else if (a->rm_owner > b->rm_owner)
2789e89c0413SDarrick J. Wong 		return 1;
2790e89c0413SDarrick J. Wong 	else if (oa < ob)
2791e89c0413SDarrick J. Wong 		return -1;
2792e89c0413SDarrick J. Wong 	else if (oa > ob)
2793e89c0413SDarrick J. Wong 		return 1;
2794e89c0413SDarrick J. Wong 	else
2795e89c0413SDarrick J. Wong 		return 0;
2796e89c0413SDarrick J. Wong }
2797ed7c52d4SDarrick J. Wong 
27986abc7aefSDarrick J. Wong /*
27996abc7aefSDarrick J. Wong  * Scan the physical storage part of the keyspace of the reverse mapping index
28006abc7aefSDarrick J. Wong  * and tell us if the area has no records, is fully mapped by records, or is
28016abc7aefSDarrick J. Wong  * partially filled.
28026abc7aefSDarrick J. Wong  */
2803ed7c52d4SDarrick J. Wong int
xfs_rmap_has_records(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,enum xbtree_recpacking * outcome)28046abc7aefSDarrick J. Wong xfs_rmap_has_records(
2805ed7c52d4SDarrick J. Wong 	struct xfs_btree_cur	*cur,
2806ed7c52d4SDarrick J. Wong 	xfs_agblock_t		bno,
2807ed7c52d4SDarrick J. Wong 	xfs_extlen_t		len,
28086abc7aefSDarrick J. Wong 	enum xbtree_recpacking	*outcome)
2809ed7c52d4SDarrick J. Wong {
28104a200a09SDarrick J. Wong 	union xfs_btree_key	mask = {
28114a200a09SDarrick J. Wong 		.rmap.rm_startblock = cpu_to_be32(-1U),
28124a200a09SDarrick J. Wong 	};
2813ed7c52d4SDarrick J. Wong 	union xfs_btree_irec	low;
2814ed7c52d4SDarrick J. Wong 	union xfs_btree_irec	high;
2815ed7c52d4SDarrick J. Wong 
2816ed7c52d4SDarrick J. Wong 	memset(&low, 0, sizeof(low));
2817ed7c52d4SDarrick J. Wong 	low.r.rm_startblock = bno;
2818ed7c52d4SDarrick J. Wong 	memset(&high, 0xFF, sizeof(high));
2819ed7c52d4SDarrick J. Wong 	high.r.rm_startblock = bno + len - 1;
2820ed7c52d4SDarrick J. Wong 
28214a200a09SDarrick J. Wong 	return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
2822ed7c52d4SDarrick J. Wong }
2823ed7c52d4SDarrick J. Wong 
282469115f77SDarrick J. Wong struct xfs_rmap_ownercount {
282569115f77SDarrick J. Wong 	/* Owner that we're looking for. */
282669115f77SDarrick J. Wong 	struct xfs_rmap_irec	good;
282769115f77SDarrick J. Wong 
282869115f77SDarrick J. Wong 	/* rmap search keys */
282969115f77SDarrick J. Wong 	struct xfs_rmap_irec	low;
283069115f77SDarrick J. Wong 	struct xfs_rmap_irec	high;
283169115f77SDarrick J. Wong 
283269115f77SDarrick J. Wong 	struct xfs_rmap_matches	*results;
283369115f77SDarrick J. Wong 
283469115f77SDarrick J. Wong 	/* Stop early if we find a nonmatch? */
283569115f77SDarrick J. Wong 	bool			stop_on_nonmatch;
283669115f77SDarrick J. Wong };
283769115f77SDarrick J. Wong 
283869115f77SDarrick J. Wong /* Does this rmap represent space that can have multiple owners? */
283969115f77SDarrick J. Wong static inline bool
xfs_rmap_shareable(struct xfs_mount * mp,const struct xfs_rmap_irec * rmap)284069115f77SDarrick J. Wong xfs_rmap_shareable(
284169115f77SDarrick J. Wong 	struct xfs_mount		*mp,
284269115f77SDarrick J. Wong 	const struct xfs_rmap_irec	*rmap)
284369115f77SDarrick J. Wong {
284469115f77SDarrick J. Wong 	if (!xfs_has_reflink(mp))
284569115f77SDarrick J. Wong 		return false;
284669115f77SDarrick J. Wong 	if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
284769115f77SDarrick J. Wong 		return false;
284869115f77SDarrick J. Wong 	if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
284969115f77SDarrick J. Wong 			      XFS_RMAP_BMBT_BLOCK))
285069115f77SDarrick J. Wong 		return false;
285169115f77SDarrick J. Wong 	return true;
285269115f77SDarrick J. Wong }
285369115f77SDarrick J. Wong 
285469115f77SDarrick J. Wong static inline void
xfs_rmap_ownercount_init(struct xfs_rmap_ownercount * roc,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo,struct xfs_rmap_matches * results)285569115f77SDarrick J. Wong xfs_rmap_ownercount_init(
285669115f77SDarrick J. Wong 	struct xfs_rmap_ownercount	*roc,
2857ed7c52d4SDarrick J. Wong 	xfs_agblock_t			bno,
2858ed7c52d4SDarrick J. Wong 	xfs_extlen_t			len,
285966e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo,
286069115f77SDarrick J. Wong 	struct xfs_rmap_matches		*results)
2861ed7c52d4SDarrick J. Wong {
286269115f77SDarrick J. Wong 	memset(roc, 0, sizeof(*roc));
286369115f77SDarrick J. Wong 	roc->results = results;
2864ed7c52d4SDarrick J. Wong 
286569115f77SDarrick J. Wong 	roc->low.rm_startblock = bno;
286669115f77SDarrick J. Wong 	memset(&roc->high, 0xFF, sizeof(roc->high));
286769115f77SDarrick J. Wong 	roc->high.rm_startblock = bno + len - 1;
2868ed7c52d4SDarrick J. Wong 
286969115f77SDarrick J. Wong 	memset(results, 0, sizeof(*results));
287069115f77SDarrick J. Wong 	roc->good.rm_startblock = bno;
287169115f77SDarrick J. Wong 	roc->good.rm_blockcount = len;
287269115f77SDarrick J. Wong 	roc->good.rm_owner = oinfo->oi_owner;
287369115f77SDarrick J. Wong 	roc->good.rm_offset = oinfo->oi_offset;
287469115f77SDarrick J. Wong 	if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
287569115f77SDarrick J. Wong 		roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
287669115f77SDarrick J. Wong 	if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
287769115f77SDarrick J. Wong 		roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2878ed7c52d4SDarrick J. Wong }
2879ed7c52d4SDarrick J. Wong 
288069115f77SDarrick J. Wong /* Figure out if this is a match for the owner. */
28814d4f86b4SDarrick J. Wong STATIC int
xfs_rmap_count_owners_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)288269115f77SDarrick J. Wong xfs_rmap_count_owners_helper(
28834d4f86b4SDarrick J. Wong 	struct xfs_btree_cur		*cur,
2884159eb69dSDarrick J. Wong 	const struct xfs_rmap_irec	*rec,
28854d4f86b4SDarrick J. Wong 	void				*priv)
28864d4f86b4SDarrick J. Wong {
288769115f77SDarrick J. Wong 	struct xfs_rmap_ownercount	*roc = priv;
288869115f77SDarrick J. Wong 	struct xfs_rmap_irec		check = *rec;
288969115f77SDarrick J. Wong 	unsigned int			keyflags;
289069115f77SDarrick J. Wong 	bool				filedata;
289169115f77SDarrick J. Wong 	int64_t				delta;
28924d4f86b4SDarrick J. Wong 
289369115f77SDarrick J. Wong 	filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
289469115f77SDarrick J. Wong 		   !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
289569115f77SDarrick J. Wong 
289669115f77SDarrick J. Wong 	/* Trim the part of check that comes before the comparison range. */
289769115f77SDarrick J. Wong 	delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
289869115f77SDarrick J. Wong 	if (delta > 0) {
289969115f77SDarrick J. Wong 		check.rm_startblock += delta;
290069115f77SDarrick J. Wong 		check.rm_blockcount -= delta;
290169115f77SDarrick J. Wong 		if (filedata)
290269115f77SDarrick J. Wong 			check.rm_offset += delta;
290369115f77SDarrick J. Wong 	}
290469115f77SDarrick J. Wong 
290569115f77SDarrick J. Wong 	/* Trim the part of check that comes after the comparison range. */
290669115f77SDarrick J. Wong 	delta = (check.rm_startblock + check.rm_blockcount) -
290769115f77SDarrick J. Wong 		(roc->good.rm_startblock + roc->good.rm_blockcount);
290869115f77SDarrick J. Wong 	if (delta > 0)
290969115f77SDarrick J. Wong 		check.rm_blockcount -= delta;
291069115f77SDarrick J. Wong 
291169115f77SDarrick J. Wong 	/* Don't care about unwritten status for establishing ownership. */
291269115f77SDarrick J. Wong 	keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
291369115f77SDarrick J. Wong 
291469115f77SDarrick J. Wong 	if (check.rm_startblock	== roc->good.rm_startblock &&
291569115f77SDarrick J. Wong 	    check.rm_blockcount	== roc->good.rm_blockcount &&
291669115f77SDarrick J. Wong 	    check.rm_owner	== roc->good.rm_owner &&
291769115f77SDarrick J. Wong 	    check.rm_offset	== roc->good.rm_offset &&
291869115f77SDarrick J. Wong 	    keyflags		== roc->good.rm_flags) {
291969115f77SDarrick J. Wong 		roc->results->matches++;
292069115f77SDarrick J. Wong 	} else {
292169115f77SDarrick J. Wong 		roc->results->non_owner_matches++;
292269115f77SDarrick J. Wong 		if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
292369115f77SDarrick J. Wong 		    xfs_rmap_shareable(cur->bc_mp, &check))
292469115f77SDarrick J. Wong 			roc->results->bad_non_owner_matches++;
292569115f77SDarrick J. Wong 	}
292669115f77SDarrick J. Wong 
292769115f77SDarrick J. Wong 	if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
2928e7ee96dfSDarrick J. Wong 		return -ECANCELED;
292969115f77SDarrick J. Wong 
293069115f77SDarrick J. Wong 	return 0;
293169115f77SDarrick J. Wong }
293269115f77SDarrick J. Wong 
293369115f77SDarrick J. Wong /* Count the number of owners and non-owners of this range of blocks. */
293469115f77SDarrick J. Wong int
xfs_rmap_count_owners(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo,struct xfs_rmap_matches * results)293569115f77SDarrick J. Wong xfs_rmap_count_owners(
293669115f77SDarrick J. Wong 	struct xfs_btree_cur		*cur,
293769115f77SDarrick J. Wong 	xfs_agblock_t			bno,
293869115f77SDarrick J. Wong 	xfs_extlen_t			len,
293969115f77SDarrick J. Wong 	const struct xfs_owner_info	*oinfo,
294069115f77SDarrick J. Wong 	struct xfs_rmap_matches		*results)
294169115f77SDarrick J. Wong {
294269115f77SDarrick J. Wong 	struct xfs_rmap_ownercount	roc;
294369115f77SDarrick J. Wong 	int				error;
294469115f77SDarrick J. Wong 
294569115f77SDarrick J. Wong 	xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
294669115f77SDarrick J. Wong 	error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
294769115f77SDarrick J. Wong 			xfs_rmap_count_owners_helper, &roc);
294869115f77SDarrick J. Wong 	if (error)
294969115f77SDarrick J. Wong 		return error;
295069115f77SDarrick J. Wong 
295169115f77SDarrick J. Wong 	/*
295269115f77SDarrick J. Wong 	 * There can't be any non-owner rmaps that conflict with the given
295369115f77SDarrick J. Wong 	 * owner if we didn't find any rmaps matching the owner.
295469115f77SDarrick J. Wong 	 */
295569115f77SDarrick J. Wong 	if (!results->matches)
295669115f77SDarrick J. Wong 		results->bad_non_owner_matches = 0;
295769115f77SDarrick J. Wong 
295869115f77SDarrick J. Wong 	return 0;
29594d4f86b4SDarrick J. Wong }
29604d4f86b4SDarrick J. Wong 
29614d4f86b4SDarrick J. Wong /*
29624d4f86b4SDarrick J. Wong  * Given an extent and some owner info, can we find records overlapping
29634d4f86b4SDarrick J. Wong  * the extent whose owner info does not match the given owner?
29644d4f86b4SDarrick J. Wong  */
29654d4f86b4SDarrick J. Wong int
xfs_rmap_has_other_keys(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,const struct xfs_owner_info * oinfo,bool * has_other)29664d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys(
29674d4f86b4SDarrick J. Wong 	struct xfs_btree_cur		*cur,
29684d4f86b4SDarrick J. Wong 	xfs_agblock_t			bno,
29694d4f86b4SDarrick J. Wong 	xfs_extlen_t			len,
297066e3237eSDarrick J. Wong 	const struct xfs_owner_info	*oinfo,
297169115f77SDarrick J. Wong 	bool				*has_other)
29724d4f86b4SDarrick J. Wong {
297369115f77SDarrick J. Wong 	struct xfs_rmap_matches		res;
297469115f77SDarrick J. Wong 	struct xfs_rmap_ownercount	roc;
29754d4f86b4SDarrick J. Wong 	int				error;
29764d4f86b4SDarrick J. Wong 
297769115f77SDarrick J. Wong 	xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
297869115f77SDarrick J. Wong 	roc.stop_on_nonmatch = true;
29794d4f86b4SDarrick J. Wong 
298069115f77SDarrick J. Wong 	error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
298169115f77SDarrick J. Wong 			xfs_rmap_count_owners_helper, &roc);
2982a71e4228SDarrick J. Wong 	if (error == -ECANCELED) {
298369115f77SDarrick J. Wong 		*has_other = true;
29847380e8feSDarrick J. Wong 		return 0;
29854d4f86b4SDarrick J. Wong 	}
298669115f77SDarrick J. Wong 	if (error)
2987a71e4228SDarrick J. Wong 		return error;
298869115f77SDarrick J. Wong 
298969115f77SDarrick J. Wong 	*has_other = false;
299069115f77SDarrick J. Wong 	return 0;
2991a71e4228SDarrick J. Wong }
2992a71e4228SDarrick J. Wong 
29937280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
29947280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_NULL,
29957280fedaSDarrick J. Wong };
29967280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
29977280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_UNKNOWN,
29987280fedaSDarrick J. Wong };
29997280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
30007280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_FS,
30017280fedaSDarrick J. Wong };
30027280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
30037280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_LOG,
30047280fedaSDarrick J. Wong };
30057280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
30067280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_AG,
30077280fedaSDarrick J. Wong };
30087280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
30097280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_INOBT,
30107280fedaSDarrick J. Wong };
30117280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
30127280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_INODES,
30137280fedaSDarrick J. Wong };
30147280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
30157280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_REFC,
30167280fedaSDarrick J. Wong };
30177280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
30187280fedaSDarrick J. Wong 	.oi_owner = XFS_RMAP_OWN_COW,
30197280fedaSDarrick J. Wong };
3020f3c799c2SDarrick J. Wong 
3021f3c799c2SDarrick J. Wong int __init
xfs_rmap_intent_init_cache(void)3022f3c799c2SDarrick J. Wong xfs_rmap_intent_init_cache(void)
3023f3c799c2SDarrick J. Wong {
3024f3c799c2SDarrick J. Wong 	xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
3025f3c799c2SDarrick J. Wong 			sizeof(struct xfs_rmap_intent),
3026f3c799c2SDarrick J. Wong 			0, 0, NULL);
3027f3c799c2SDarrick J. Wong 
3028f3c799c2SDarrick J. Wong 	return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
3029f3c799c2SDarrick J. Wong }
3030f3c799c2SDarrick J. Wong 
3031f3c799c2SDarrick J. Wong void
xfs_rmap_intent_destroy_cache(void)3032f3c799c2SDarrick J. Wong xfs_rmap_intent_destroy_cache(void)
3033f3c799c2SDarrick J. Wong {
3034f3c799c2SDarrick J. Wong 	kmem_cache_destroy(xfs_rmap_intent_cache);
3035f3c799c2SDarrick J. Wong 	xfs_rmap_intent_cache = NULL;
3036f3c799c2SDarrick J. Wong }
3037