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"
26673930c3SDarrick J. Wong
27f3c799c2SDarrick J. Wong struct kmem_cache *xfs_rmap_intent_cache;
28f3c799c2SDarrick J. Wong
294b8ed677SDarrick J. Wong /*
304b8ed677SDarrick J. Wong * Lookup the first record less than or equal to [bno, len, owner, offset]
314b8ed677SDarrick J. Wong * in the btree given by cur.
324b8ed677SDarrick J. Wong */
334b8ed677SDarrick 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)344b8ed677SDarrick J. Wong xfs_rmap_lookup_le(
354b8ed677SDarrick J. Wong struct xfs_btree_cur *cur,
364b8ed677SDarrick J. Wong xfs_agblock_t bno,
374b8ed677SDarrick J. Wong uint64_t owner,
384b8ed677SDarrick J. Wong uint64_t offset,
394b8ed677SDarrick J. Wong unsigned int flags,
405b7ca8b3SDarrick J. Wong struct xfs_rmap_irec *irec,
414b8ed677SDarrick J. Wong int *stat)
424b8ed677SDarrick J. Wong {
435b7ca8b3SDarrick J. Wong int get_stat = 0;
445b7ca8b3SDarrick J. Wong int error;
455b7ca8b3SDarrick J. Wong
464b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno;
475b7ca8b3SDarrick J. Wong cur->bc_rec.r.rm_blockcount = 0;
484b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner;
494b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset;
504b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags;
515b7ca8b3SDarrick J. Wong
525b7ca8b3SDarrick J. Wong error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
535b7ca8b3SDarrick J. Wong if (error || !(*stat) || !irec)
545b7ca8b3SDarrick J. Wong return error;
555b7ca8b3SDarrick J. Wong
565b7ca8b3SDarrick J. Wong error = xfs_rmap_get_rec(cur, irec, &get_stat);
575b7ca8b3SDarrick J. Wong if (error)
585b7ca8b3SDarrick J. Wong return error;
595b7ca8b3SDarrick J. Wong if (!get_stat)
605b7ca8b3SDarrick J. Wong return -EFSCORRUPTED;
615b7ca8b3SDarrick J. Wong
625b7ca8b3SDarrick J. Wong return 0;
634b8ed677SDarrick J. Wong }
644b8ed677SDarrick J. Wong
654b8ed677SDarrick J. Wong /*
664b8ed677SDarrick J. Wong * Lookup the record exactly matching [bno, len, owner, offset]
674b8ed677SDarrick J. Wong * in the btree given by cur.
684b8ed677SDarrick J. Wong */
694b8ed677SDarrick J. Wong int
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)704b8ed677SDarrick J. Wong xfs_rmap_lookup_eq(
714b8ed677SDarrick J. Wong struct xfs_btree_cur *cur,
724b8ed677SDarrick J. Wong xfs_agblock_t bno,
734b8ed677SDarrick J. Wong xfs_extlen_t len,
744b8ed677SDarrick J. Wong uint64_t owner,
754b8ed677SDarrick J. Wong uint64_t offset,
764b8ed677SDarrick J. Wong unsigned int flags,
774b8ed677SDarrick J. Wong int *stat)
784b8ed677SDarrick J. Wong {
794b8ed677SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno;
804b8ed677SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len;
814b8ed677SDarrick J. Wong cur->bc_rec.r.rm_owner = owner;
824b8ed677SDarrick J. Wong cur->bc_rec.r.rm_offset = offset;
834b8ed677SDarrick J. Wong cur->bc_rec.r.rm_flags = flags;
844b8ed677SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
854b8ed677SDarrick J. Wong }
864b8ed677SDarrick J. Wong
874b8ed677SDarrick J. Wong /*
884b8ed677SDarrick J. Wong * Update the record referred to by cur to the value given
894b8ed677SDarrick J. Wong * by [bno, len, owner, offset].
904b8ed677SDarrick J. Wong * This either works (return 0) or gets an EFSCORRUPTED error.
914b8ed677SDarrick J. Wong */
924b8ed677SDarrick J. Wong STATIC int
xfs_rmap_update(struct xfs_btree_cur * cur,struct xfs_rmap_irec * irec)934b8ed677SDarrick J. Wong xfs_rmap_update(
944b8ed677SDarrick J. Wong struct xfs_btree_cur *cur,
954b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec)
964b8ed677SDarrick J. Wong {
974b8ed677SDarrick J. Wong union xfs_btree_rec rec;
98abf09233SDarrick J. Wong int error;
99abf09233SDarrick J. Wong
10050f02fe3SDave Chinner trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
101abf09233SDarrick J. Wong irec->rm_startblock, irec->rm_blockcount,
102abf09233SDarrick J. Wong irec->rm_owner, irec->rm_offset, irec->rm_flags);
1034b8ed677SDarrick J. Wong
1044b8ed677SDarrick J. Wong rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
1054b8ed677SDarrick J. Wong rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
1064b8ed677SDarrick J. Wong rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
1074b8ed677SDarrick J. Wong rec.rmap.rm_offset = cpu_to_be64(
1084b8ed677SDarrick J. Wong xfs_rmap_irec_offset_pack(irec));
109abf09233SDarrick J. Wong error = xfs_btree_update(cur, &rec);
110abf09233SDarrick J. Wong if (error)
111abf09233SDarrick J. Wong trace_xfs_rmap_update_error(cur->bc_mp,
11250f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_);
113abf09233SDarrick J. Wong return error;
114abf09233SDarrick J. Wong }
115abf09233SDarrick J. Wong
116abf09233SDarrick 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)117abf09233SDarrick J. Wong xfs_rmap_insert(
118abf09233SDarrick J. Wong struct xfs_btree_cur *rcur,
119abf09233SDarrick J. Wong xfs_agblock_t agbno,
120abf09233SDarrick J. Wong xfs_extlen_t len,
121abf09233SDarrick J. Wong uint64_t owner,
122abf09233SDarrick J. Wong uint64_t offset,
123abf09233SDarrick J. Wong unsigned int flags)
124abf09233SDarrick J. Wong {
125abf09233SDarrick J. Wong int i;
126abf09233SDarrick J. Wong int error;
127abf09233SDarrick J. Wong
12850f02fe3SDave Chinner trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
129abf09233SDarrick J. Wong len, owner, offset, flags);
130abf09233SDarrick J. Wong
131abf09233SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
132abf09233SDarrick J. Wong if (error)
133abf09233SDarrick J. Wong goto done;
134f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
135f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
136f9e03706SDarrick J. Wong goto done;
137f9e03706SDarrick J. Wong }
138abf09233SDarrick J. Wong
139abf09233SDarrick J. Wong rcur->bc_rec.r.rm_startblock = agbno;
140abf09233SDarrick J. Wong rcur->bc_rec.r.rm_blockcount = len;
141abf09233SDarrick J. Wong rcur->bc_rec.r.rm_owner = owner;
142abf09233SDarrick J. Wong rcur->bc_rec.r.rm_offset = offset;
143abf09233SDarrick J. Wong rcur->bc_rec.r.rm_flags = flags;
144abf09233SDarrick J. Wong error = xfs_btree_insert(rcur, &i);
145abf09233SDarrick J. Wong if (error)
146abf09233SDarrick J. Wong goto done;
147f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
148f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
149f9e03706SDarrick J. Wong goto done;
150f9e03706SDarrick J. Wong }
151abf09233SDarrick J. Wong done:
152abf09233SDarrick J. Wong if (error)
153abf09233SDarrick J. Wong trace_xfs_rmap_insert_error(rcur->bc_mp,
15450f02fe3SDave Chinner rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
155abf09233SDarrick J. Wong return error;
1564b8ed677SDarrick J. Wong }
1574b8ed677SDarrick J. Wong
158ceeb9c83SDarrick 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)159ceeb9c83SDarrick J. Wong xfs_rmap_delete(
160ceeb9c83SDarrick J. Wong struct xfs_btree_cur *rcur,
161ceeb9c83SDarrick J. Wong xfs_agblock_t agbno,
162ceeb9c83SDarrick J. Wong xfs_extlen_t len,
163ceeb9c83SDarrick J. Wong uint64_t owner,
164ceeb9c83SDarrick J. Wong uint64_t offset,
165ceeb9c83SDarrick J. Wong unsigned int flags)
166ceeb9c83SDarrick J. Wong {
167ceeb9c83SDarrick J. Wong int i;
168ceeb9c83SDarrick J. Wong int error;
169ceeb9c83SDarrick J. Wong
17050f02fe3SDave Chinner trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
171ceeb9c83SDarrick J. Wong len, owner, offset, flags);
172ceeb9c83SDarrick J. Wong
173ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
174ceeb9c83SDarrick J. Wong if (error)
175ceeb9c83SDarrick J. Wong goto done;
176f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
177f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
178f9e03706SDarrick J. Wong goto done;
179f9e03706SDarrick J. Wong }
180ceeb9c83SDarrick J. Wong
181ceeb9c83SDarrick J. Wong error = xfs_btree_delete(rcur, &i);
182ceeb9c83SDarrick J. Wong if (error)
183ceeb9c83SDarrick J. Wong goto done;
184f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
185f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
186f9e03706SDarrick J. Wong goto done;
187f9e03706SDarrick J. Wong }
188ceeb9c83SDarrick J. Wong done:
189ceeb9c83SDarrick J. Wong if (error)
190ceeb9c83SDarrick J. Wong trace_xfs_rmap_delete_error(rcur->bc_mp,
19150f02fe3SDave Chinner rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
192ceeb9c83SDarrick J. Wong return error;
193ceeb9c83SDarrick J. Wong }
194ceeb9c83SDarrick J. Wong
19526788097SDarrick J. Wong /* Convert an internal btree record to an rmap record. */
19639ab26d5SDarrick J. Wong xfs_failaddr_t
xfs_rmap_btrec_to_irec(const union xfs_btree_rec * rec,struct xfs_rmap_irec * irec)1974b8ed677SDarrick J. Wong xfs_rmap_btrec_to_irec(
198159eb69dSDarrick J. Wong const union xfs_btree_rec *rec,
1994b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec)
2004b8ed677SDarrick J. Wong {
2014b8ed677SDarrick J. Wong irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
2024b8ed677SDarrick J. Wong irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
2034b8ed677SDarrick J. Wong irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
2044b8ed677SDarrick J. Wong return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
2054b8ed677SDarrick J. Wong irec);
2064b8ed677SDarrick J. Wong }
2074b8ed677SDarrick J. Wong
208c4e34172SDarrick J. Wong /* Simple checks for rmap records. */
209c4e34172SDarrick J. Wong xfs_failaddr_t
xfs_rmap_check_irec(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * irec)210c4e34172SDarrick J. Wong xfs_rmap_check_irec(
211c4e34172SDarrick J. Wong struct xfs_btree_cur *cur,
212c4e34172SDarrick J. Wong const struct xfs_rmap_irec *irec)
213c4e34172SDarrick J. Wong {
214c4e34172SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
2157d7d6d2fSDarrick J. Wong bool is_inode;
2167d7d6d2fSDarrick J. Wong bool is_unwritten;
2177d7d6d2fSDarrick J. Wong bool is_bmbt;
2187d7d6d2fSDarrick J. Wong bool is_attr;
219c4e34172SDarrick J. Wong
220c4e34172SDarrick J. Wong if (irec->rm_blockcount == 0)
221c4e34172SDarrick J. Wong return __this_address;
222c4e34172SDarrick J. Wong if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
223c4e34172SDarrick J. Wong if (irec->rm_owner != XFS_RMAP_OWN_FS)
224c4e34172SDarrick J. Wong return __this_address;
225c4e34172SDarrick J. Wong if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
226c4e34172SDarrick J. Wong return __this_address;
227c4e34172SDarrick J. Wong } else {
228c4e34172SDarrick J. Wong /* check for valid extent range, including overflow */
229c4e34172SDarrick J. Wong if (!xfs_verify_agbext(cur->bc_ag.pag, irec->rm_startblock,
230c4e34172SDarrick J. Wong irec->rm_blockcount))
231c4e34172SDarrick J. Wong return __this_address;
232c4e34172SDarrick J. Wong }
233c4e34172SDarrick J. Wong
234c4e34172SDarrick J. Wong if (!(xfs_verify_ino(mp, irec->rm_owner) ||
235c4e34172SDarrick J. Wong (irec->rm_owner <= XFS_RMAP_OWN_FS &&
236c4e34172SDarrick J. Wong irec->rm_owner >= XFS_RMAP_OWN_MIN)))
237c4e34172SDarrick J. Wong return __this_address;
238c4e34172SDarrick J. Wong
2397d7d6d2fSDarrick J. Wong /* Check flags. */
2407d7d6d2fSDarrick J. Wong is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
2417d7d6d2fSDarrick J. Wong is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
2427d7d6d2fSDarrick J. Wong is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
2437d7d6d2fSDarrick J. Wong is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
2447d7d6d2fSDarrick J. Wong
2457d7d6d2fSDarrick J. Wong if (is_bmbt && irec->rm_offset != 0)
2467d7d6d2fSDarrick J. Wong return __this_address;
2477d7d6d2fSDarrick J. Wong
2487d7d6d2fSDarrick J. Wong if (!is_inode && irec->rm_offset != 0)
2497d7d6d2fSDarrick J. Wong return __this_address;
2507d7d6d2fSDarrick J. Wong
2517d7d6d2fSDarrick J. Wong if (is_unwritten && (is_bmbt || !is_inode || is_attr))
2527d7d6d2fSDarrick J. Wong return __this_address;
2537d7d6d2fSDarrick J. Wong
2547d7d6d2fSDarrick J. Wong if (!is_inode && (is_bmbt || is_unwritten || is_attr))
2557d7d6d2fSDarrick J. Wong return __this_address;
2567d7d6d2fSDarrick J. Wong
257e774b2eaSDarrick J. Wong /* Check for a valid fork offset, if applicable. */
258e774b2eaSDarrick J. Wong if (is_inode && !is_bmbt &&
259e774b2eaSDarrick J. Wong !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
260e774b2eaSDarrick J. Wong return __this_address;
261e774b2eaSDarrick J. Wong
262c4e34172SDarrick J. Wong return NULL;
263c4e34172SDarrick J. Wong }
264c4e34172SDarrick J. Wong
265ee12eaaaSDarrick 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)266ee12eaaaSDarrick J. Wong xfs_rmap_complain_bad_rec(
267ee12eaaaSDarrick J. Wong struct xfs_btree_cur *cur,
268ee12eaaaSDarrick J. Wong xfs_failaddr_t fa,
269ee12eaaaSDarrick J. Wong const struct xfs_rmap_irec *irec)
270ee12eaaaSDarrick J. Wong {
271ee12eaaaSDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
272ee12eaaaSDarrick J. Wong
273ee12eaaaSDarrick J. Wong xfs_warn(mp,
274ee12eaaaSDarrick J. Wong "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
275ee12eaaaSDarrick J. Wong cur->bc_ag.pag->pag_agno, fa);
276ee12eaaaSDarrick J. Wong xfs_warn(mp,
277ee12eaaaSDarrick J. Wong "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
278ee12eaaaSDarrick J. Wong irec->rm_owner, irec->rm_flags, irec->rm_startblock,
279ee12eaaaSDarrick J. Wong irec->rm_blockcount);
280ee12eaaaSDarrick J. Wong return -EFSCORRUPTED;
281ee12eaaaSDarrick J. Wong }
282ee12eaaaSDarrick J. Wong
2834b8ed677SDarrick J. Wong /*
2844b8ed677SDarrick J. Wong * Get the data from the pointed-to record.
2854b8ed677SDarrick J. Wong */
2864b8ed677SDarrick J. Wong int
xfs_rmap_get_rec(struct xfs_btree_cur * cur,struct xfs_rmap_irec * irec,int * stat)2874b8ed677SDarrick J. Wong xfs_rmap_get_rec(
2884b8ed677SDarrick J. Wong struct xfs_btree_cur *cur,
2894b8ed677SDarrick J. Wong struct xfs_rmap_irec *irec,
2904b8ed677SDarrick J. Wong int *stat)
2914b8ed677SDarrick J. Wong {
2924b8ed677SDarrick J. Wong union xfs_btree_rec *rec;
293c4e34172SDarrick J. Wong xfs_failaddr_t fa;
2944b8ed677SDarrick J. Wong int error;
2954b8ed677SDarrick J. Wong
2964b8ed677SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat);
2974b8ed677SDarrick J. Wong if (error || !*stat)
2984b8ed677SDarrick J. Wong return error;
2994b8ed677SDarrick J. Wong
300c4e34172SDarrick J. Wong fa = xfs_rmap_btrec_to_irec(rec, irec);
301c4e34172SDarrick J. Wong if (!fa)
302c4e34172SDarrick J. Wong fa = xfs_rmap_check_irec(cur, irec);
303c4e34172SDarrick J. Wong if (fa)
304ee12eaaaSDarrick J. Wong return xfs_rmap_complain_bad_rec(cur, fa, irec);
3059e6c08d4SDave Chinner
3069e6c08d4SDave Chinner return 0;
3074b8ed677SDarrick J. Wong }
3084b8ed677SDarrick J. Wong
309ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info {
310ceeb9c83SDarrick J. Wong struct xfs_rmap_irec high;
311ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec;
312ceeb9c83SDarrick J. Wong };
313ceeb9c83SDarrick J. Wong
314ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */
315ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_find_left_neighbor_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)316ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper(
317ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur,
318159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec,
319ceeb9c83SDarrick J. Wong void *priv)
320ceeb9c83SDarrick J. Wong {
321ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv;
322ceeb9c83SDarrick J. Wong
323ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
32450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, rec->rm_startblock,
325ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
326ceeb9c83SDarrick J. Wong rec->rm_flags);
327ceeb9c83SDarrick J. Wong
328ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner)
32939ee2239SDarrick J. Wong return 0;
330ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
331ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
332ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
33339ee2239SDarrick J. Wong return 0;
334ceeb9c83SDarrick J. Wong
335ceeb9c83SDarrick J. Wong *info->irec = *rec;
336e7ee96dfSDarrick J. Wong return -ECANCELED;
337ceeb9c83SDarrick J. Wong }
338ceeb9c83SDarrick J. Wong
339ceeb9c83SDarrick J. Wong /*
340ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to
341ceeb9c83SDarrick J. Wong * return a match with the same owner and adjacent physical and logical
342ceeb9c83SDarrick J. Wong * block ranges.
343ceeb9c83SDarrick J. Wong */
3441edf8056SDarrick 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)345ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor(
346ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur,
347ceeb9c83SDarrick J. Wong xfs_agblock_t bno,
348ceeb9c83SDarrick J. Wong uint64_t owner,
349ceeb9c83SDarrick J. Wong uint64_t offset,
350ceeb9c83SDarrick J. Wong unsigned int flags,
351ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec,
352ceeb9c83SDarrick J. Wong int *stat)
353ceeb9c83SDarrick J. Wong {
354ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info;
3551edf8056SDarrick J. Wong int found = 0;
356ceeb9c83SDarrick J. Wong int error;
357ceeb9c83SDarrick J. Wong
358ceeb9c83SDarrick J. Wong *stat = 0;
359ceeb9c83SDarrick J. Wong if (bno == 0)
360ceeb9c83SDarrick J. Wong return 0;
361ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno - 1;
362ceeb9c83SDarrick J. Wong info.high.rm_owner = owner;
363ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
364ceeb9c83SDarrick J. Wong !(flags & XFS_RMAP_BMBT_BLOCK)) {
365ceeb9c83SDarrick J. Wong if (offset == 0)
366ceeb9c83SDarrick J. Wong return 0;
367ceeb9c83SDarrick J. Wong info.high.rm_offset = offset - 1;
368ceeb9c83SDarrick J. Wong } else
369ceeb9c83SDarrick J. Wong info.high.rm_offset = 0;
370ceeb9c83SDarrick J. Wong info.high.rm_flags = flags;
371ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0;
372ceeb9c83SDarrick J. Wong info.irec = irec;
373ceeb9c83SDarrick J. Wong
374ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
37550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
376ceeb9c83SDarrick J. Wong
3771edf8056SDarrick J. Wong /*
3781edf8056SDarrick J. Wong * Historically, we always used the range query to walk every reverse
3791edf8056SDarrick J. Wong * mapping that could possibly overlap the key that the caller asked
3801edf8056SDarrick J. Wong * for, and filter out the ones that don't. That is very slow when
3811edf8056SDarrick J. Wong * there are a lot of records.
3821edf8056SDarrick J. Wong *
3831edf8056SDarrick J. Wong * However, there are two scenarios where the classic btree search can
3841edf8056SDarrick J. Wong * produce correct results -- if the index contains a record that is an
3851edf8056SDarrick J. Wong * exact match for the lookup key; and if there are no other records
3861edf8056SDarrick J. Wong * between the record we want and the key we supplied.
3871edf8056SDarrick J. Wong *
3881edf8056SDarrick J. Wong * As an optimization, try a non-overlapped lookup first. This makes
3891edf8056SDarrick J. Wong * extent conversion and remap operations run a bit faster if the
3901edf8056SDarrick J. Wong * physical extents aren't being shared. If we don't find what we
3911edf8056SDarrick J. Wong * want, we fall back to the overlapped query.
3921edf8056SDarrick J. Wong */
3931edf8056SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
3941edf8056SDarrick J. Wong &found);
3951edf8056SDarrick J. Wong if (error)
3961edf8056SDarrick J. Wong return error;
3971edf8056SDarrick J. Wong if (found)
3981edf8056SDarrick J. Wong error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
3991edf8056SDarrick J. Wong if (!error)
400ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high,
401ceeb9c83SDarrick J. Wong xfs_rmap_find_left_neighbor_helper, &info);
4021edf8056SDarrick J. Wong if (error != -ECANCELED)
4031edf8056SDarrick J. Wong return error;
4041edf8056SDarrick J. Wong
4051edf8056SDarrick J. Wong *stat = 1;
406ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
40750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, irec->rm_startblock,
4081edf8056SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
4091edf8056SDarrick J. Wong irec->rm_flags);
4101edf8056SDarrick J. Wong return 0;
411ceeb9c83SDarrick J. Wong }
412ceeb9c83SDarrick J. Wong
413ceeb9c83SDarrick J. Wong /* For each rmap given, figure out if it matches the key we want. */
414ceeb9c83SDarrick J. Wong STATIC int
xfs_rmap_lookup_le_range_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)415ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper(
416ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur,
417159eb69dSDarrick J. Wong const struct xfs_rmap_irec *rec,
418ceeb9c83SDarrick J. Wong void *priv)
419ceeb9c83SDarrick J. Wong {
420ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info *info = priv;
421ceeb9c83SDarrick J. Wong
422ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
42350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, rec->rm_startblock,
424ceeb9c83SDarrick J. Wong rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
425ceeb9c83SDarrick J. Wong rec->rm_flags);
426ceeb9c83SDarrick J. Wong
427ceeb9c83SDarrick J. Wong if (rec->rm_owner != info->high.rm_owner)
42839ee2239SDarrick J. Wong return 0;
429ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
430ceeb9c83SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
431ceeb9c83SDarrick J. Wong (rec->rm_offset > info->high.rm_offset ||
432ceeb9c83SDarrick J. Wong rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
43339ee2239SDarrick J. Wong return 0;
434ceeb9c83SDarrick J. Wong
435ceeb9c83SDarrick J. Wong *info->irec = *rec;
436e7ee96dfSDarrick J. Wong return -ECANCELED;
437ceeb9c83SDarrick J. Wong }
438ceeb9c83SDarrick J. Wong
439ceeb9c83SDarrick J. Wong /*
440ceeb9c83SDarrick J. Wong * Find the record to the left of the given extent, being careful only to
441ceeb9c83SDarrick J. Wong * return a match with the same owner and overlapping physical and logical
442ceeb9c83SDarrick J. Wong * block ranges. This is the overlapping-interval version of
443ceeb9c83SDarrick J. Wong * xfs_rmap_lookup_le.
444ceeb9c83SDarrick J. Wong */
445ceeb9c83SDarrick 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)446ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range(
447ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur,
448ceeb9c83SDarrick J. Wong xfs_agblock_t bno,
449ceeb9c83SDarrick J. Wong uint64_t owner,
450ceeb9c83SDarrick J. Wong uint64_t offset,
451ceeb9c83SDarrick J. Wong unsigned int flags,
452ceeb9c83SDarrick J. Wong struct xfs_rmap_irec *irec,
453ceeb9c83SDarrick J. Wong int *stat)
454ceeb9c83SDarrick J. Wong {
455ceeb9c83SDarrick J. Wong struct xfs_find_left_neighbor_info info;
45675d893d1SDarrick J. Wong int found = 0;
457ceeb9c83SDarrick J. Wong int error;
458ceeb9c83SDarrick J. Wong
459ceeb9c83SDarrick J. Wong info.high.rm_startblock = bno;
460ceeb9c83SDarrick J. Wong info.high.rm_owner = owner;
461ceeb9c83SDarrick J. Wong if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
462ceeb9c83SDarrick J. Wong info.high.rm_offset = offset;
463ceeb9c83SDarrick J. Wong else
464ceeb9c83SDarrick J. Wong info.high.rm_offset = 0;
465ceeb9c83SDarrick J. Wong info.high.rm_flags = flags;
466ceeb9c83SDarrick J. Wong info.high.rm_blockcount = 0;
467ceeb9c83SDarrick J. Wong *stat = 0;
468ceeb9c83SDarrick J. Wong info.irec = irec;
469ceeb9c83SDarrick J. Wong
47075d893d1SDarrick J. Wong trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
47175d893d1SDarrick J. Wong bno, 0, owner, offset, flags);
47275d893d1SDarrick J. Wong
47375d893d1SDarrick J. Wong /*
47475d893d1SDarrick J. Wong * Historically, we always used the range query to walk every reverse
47575d893d1SDarrick J. Wong * mapping that could possibly overlap the key that the caller asked
47675d893d1SDarrick J. Wong * for, and filter out the ones that don't. That is very slow when
47775d893d1SDarrick J. Wong * there are a lot of records.
47875d893d1SDarrick J. Wong *
47975d893d1SDarrick J. Wong * However, there are two scenarios where the classic btree search can
48075d893d1SDarrick J. Wong * produce correct results -- if the index contains a record that is an
48175d893d1SDarrick J. Wong * exact match for the lookup key; and if there are no other records
48275d893d1SDarrick J. Wong * between the record we want and the key we supplied.
48375d893d1SDarrick J. Wong *
48475d893d1SDarrick J. Wong * As an optimization, try a non-overlapped lookup first. This makes
48575d893d1SDarrick J. Wong * scrub run much faster on most filesystems because bmbt records are
48675d893d1SDarrick J. Wong * usually an exact match for rmap records. If we don't find what we
48775d893d1SDarrick J. Wong * want, we fall back to the overlapped query.
48875d893d1SDarrick J. Wong */
48975d893d1SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
49075d893d1SDarrick J. Wong &found);
49175d893d1SDarrick J. Wong if (error)
49275d893d1SDarrick J. Wong return error;
49375d893d1SDarrick J. Wong if (found)
49475d893d1SDarrick J. Wong error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
49575d893d1SDarrick J. Wong if (!error)
496ceeb9c83SDarrick J. Wong error = xfs_rmap_query_range(cur, &info.high, &info.high,
497ceeb9c83SDarrick J. Wong xfs_rmap_lookup_le_range_helper, &info);
49875d893d1SDarrick J. Wong if (error != -ECANCELED)
49975d893d1SDarrick J. Wong return error;
50075d893d1SDarrick J. Wong
50175d893d1SDarrick J. Wong *stat = 1;
502ceeb9c83SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
50350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, irec->rm_startblock,
50475d893d1SDarrick J. Wong irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
50575d893d1SDarrick J. Wong irec->rm_flags);
50675d893d1SDarrick J. Wong return 0;
507ceeb9c83SDarrick J. Wong }
508ceeb9c83SDarrick J. Wong
509f922cd90SDarrick J. Wong /*
51068c58e9bSDarrick J. Wong * Perform all the relevant owner checks for a removal op. If we're doing an
51168c58e9bSDarrick J. Wong * unknown-owner removal then we have no owner information to check.
51268c58e9bSDarrick J. Wong */
51368c58e9bSDarrick J. Wong static int
xfs_rmap_free_check_owner(struct xfs_mount * mp,uint64_t ltoff,struct xfs_rmap_irec * rec,xfs_filblks_t len,uint64_t owner,uint64_t offset,unsigned int flags)51468c58e9bSDarrick J. Wong xfs_rmap_free_check_owner(
51568c58e9bSDarrick J. Wong struct xfs_mount *mp,
51668c58e9bSDarrick J. Wong uint64_t ltoff,
51768c58e9bSDarrick J. Wong struct xfs_rmap_irec *rec,
51868c58e9bSDarrick J. Wong xfs_filblks_t len,
51968c58e9bSDarrick J. Wong uint64_t owner,
52068c58e9bSDarrick J. Wong uint64_t offset,
52168c58e9bSDarrick J. Wong unsigned int flags)
52268c58e9bSDarrick J. Wong {
52368c58e9bSDarrick J. Wong int error = 0;
52468c58e9bSDarrick J. Wong
52568c58e9bSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN)
52668c58e9bSDarrick J. Wong return 0;
52768c58e9bSDarrick J. Wong
52868c58e9bSDarrick J. Wong /* Make sure the unwritten flag matches. */
529f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
530f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) !=
531f9e03706SDarrick J. Wong (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
532f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
533f9e03706SDarrick J. Wong goto out;
534f9e03706SDarrick J. Wong }
53568c58e9bSDarrick J. Wong
53668c58e9bSDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */
537f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
538f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
539f9e03706SDarrick J. Wong goto out;
540f9e03706SDarrick J. Wong }
54168c58e9bSDarrick J. Wong
54268c58e9bSDarrick J. Wong /* Check the offset, if necessary. */
54368c58e9bSDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(owner))
54468c58e9bSDarrick J. Wong goto out;
54568c58e9bSDarrick J. Wong
54668c58e9bSDarrick J. Wong if (flags & XFS_RMAP_BMBT_BLOCK) {
547f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
548f9e03706SDarrick J. Wong !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
549f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
550f9e03706SDarrick J. Wong goto out;
551f9e03706SDarrick J. Wong }
55268c58e9bSDarrick J. Wong } else {
553f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
554f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
555f9e03706SDarrick J. Wong goto out;
556f9e03706SDarrick J. Wong }
557f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
558f9e03706SDarrick J. Wong offset + len > ltoff + rec->rm_blockcount)) {
559f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
560f9e03706SDarrick J. Wong goto out;
561f9e03706SDarrick J. Wong }
56268c58e9bSDarrick J. Wong }
56368c58e9bSDarrick J. Wong
56468c58e9bSDarrick J. Wong out:
56568c58e9bSDarrick J. Wong return error;
56668c58e9bSDarrick J. Wong }
56768c58e9bSDarrick J. Wong
56868c58e9bSDarrick J. Wong /*
569f922cd90SDarrick J. Wong * Find the extent in the rmap btree and remove it.
570f922cd90SDarrick J. Wong *
571f922cd90SDarrick J. Wong * The record we find should always be an exact match for the extent that we're
572f922cd90SDarrick J. Wong * looking for, since we insert them into the btree without modification.
573f922cd90SDarrick J. Wong *
574f922cd90SDarrick J. Wong * Special Case #1: when growing the filesystem, we "free" an extent when
575f922cd90SDarrick J. Wong * growing the last AG. This extent is new space and so it is not tracked as
576f922cd90SDarrick J. Wong * used space in the btree. The growfs code will pass in an owner of
577f922cd90SDarrick J. Wong * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
578f922cd90SDarrick J. Wong * extent. We verify that - the extent lookup result in a record that does not
579f922cd90SDarrick J. Wong * overlap.
580f922cd90SDarrick J. Wong *
581f922cd90SDarrick J. Wong * Special Case #2: EFIs do not record the owner of the extent, so when
582f922cd90SDarrick J. Wong * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
583f922cd90SDarrick J. Wong * btree to ignore the owner (i.e. wildcard match) so we don't trigger
584f922cd90SDarrick J. Wong * corruption checks during log recovery.
585f922cd90SDarrick J. Wong */
586f922cd90SDarrick 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)587f922cd90SDarrick J. Wong xfs_rmap_unmap(
588f922cd90SDarrick J. Wong struct xfs_btree_cur *cur,
589f922cd90SDarrick J. Wong xfs_agblock_t bno,
590f922cd90SDarrick J. Wong xfs_extlen_t len,
591f922cd90SDarrick J. Wong bool unwritten,
59266e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
593f922cd90SDarrick J. Wong {
594f922cd90SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
595f922cd90SDarrick J. Wong struct xfs_rmap_irec ltrec;
596f922cd90SDarrick J. Wong uint64_t ltoff;
597f922cd90SDarrick J. Wong int error = 0;
598f922cd90SDarrick J. Wong int i;
599f922cd90SDarrick J. Wong uint64_t owner;
600f922cd90SDarrick J. Wong uint64_t offset;
601f922cd90SDarrick J. Wong unsigned int flags;
602f922cd90SDarrick J. Wong bool ignore_off;
603f922cd90SDarrick J. Wong
604f922cd90SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
605f922cd90SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
606f922cd90SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK);
607f922cd90SDarrick J. Wong if (unwritten)
608f922cd90SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN;
60950f02fe3SDave Chinner trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
610f922cd90SDarrick J. Wong unwritten, oinfo);
611f922cd90SDarrick J. Wong
612f922cd90SDarrick J. Wong /*
613f922cd90SDarrick J. Wong * We should always have a left record because there's a static record
614f922cd90SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
615f922cd90SDarrick J. Wong * will not ever be removed from the tree.
616f922cd90SDarrick J. Wong */
6175b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec, &i);
618f922cd90SDarrick J. Wong if (error)
619f922cd90SDarrick J. Wong goto out_error;
620f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
621f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
622f9e03706SDarrick J. Wong goto out_error;
623f9e03706SDarrick J. Wong }
624f922cd90SDarrick J. Wong
625f922cd90SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
62650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
627f922cd90SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
628f922cd90SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags);
629f922cd90SDarrick J. Wong ltoff = ltrec.rm_offset;
630f922cd90SDarrick J. Wong
631f922cd90SDarrick J. Wong /*
632f922cd90SDarrick J. Wong * For growfs, the incoming extent must be beyond the left record we
633f922cd90SDarrick J. Wong * just found as it is new space and won't be used by anyone. This is
634f922cd90SDarrick J. Wong * just a corruption check as we don't actually do anything with this
635f922cd90SDarrick J. Wong * extent. Note that we need to use >= instead of > because it might
636f922cd90SDarrick J. Wong * be the case that the "left" extent goes all the way to EOFS.
637f922cd90SDarrick J. Wong */
638f922cd90SDarrick J. Wong if (owner == XFS_RMAP_OWN_NULL) {
639f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
640f9e03706SDarrick J. Wong bno <
641f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount)) {
642f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
643f9e03706SDarrick J. Wong goto out_error;
644f9e03706SDarrick J. Wong }
645f922cd90SDarrick J. Wong goto out_done;
646f922cd90SDarrick J. Wong }
647f922cd90SDarrick J. Wong
64833df3a9cSDarrick J. Wong /*
64933df3a9cSDarrick J. Wong * If we're doing an unknown-owner removal for EFI recovery, we expect
65033df3a9cSDarrick J. Wong * to find the full range in the rmapbt or nothing at all. If we
65133df3a9cSDarrick J. Wong * don't find any rmaps overlapping either end of the range, we're
65233df3a9cSDarrick J. Wong * done. Hopefully this means that the EFI creator already queued
65333df3a9cSDarrick J. Wong * (and finished) a RUI to remove the rmap.
65433df3a9cSDarrick J. Wong */
65533df3a9cSDarrick J. Wong if (owner == XFS_RMAP_OWN_UNKNOWN &&
65633df3a9cSDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
65733df3a9cSDarrick J. Wong struct xfs_rmap_irec rtrec;
65833df3a9cSDarrick J. Wong
65933df3a9cSDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
66033df3a9cSDarrick J. Wong if (error)
66133df3a9cSDarrick J. Wong goto out_error;
66233df3a9cSDarrick J. Wong if (i == 0)
66333df3a9cSDarrick J. Wong goto out_done;
66433df3a9cSDarrick J. Wong error = xfs_rmap_get_rec(cur, &rtrec, &i);
66533df3a9cSDarrick J. Wong if (error)
66633df3a9cSDarrick J. Wong goto out_error;
667f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
668f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
669f9e03706SDarrick J. Wong goto out_error;
670f9e03706SDarrick J. Wong }
67133df3a9cSDarrick J. Wong if (rtrec.rm_startblock >= bno + len)
67233df3a9cSDarrick J. Wong goto out_done;
67333df3a9cSDarrick J. Wong }
67433df3a9cSDarrick J. Wong
675f922cd90SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */
676f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
677f9e03706SDarrick J. Wong ltrec.rm_startblock > bno ||
678f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <
679f9e03706SDarrick J. Wong bno + len)) {
680f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
681f9e03706SDarrick J. Wong goto out_error;
682f9e03706SDarrick J. Wong }
683f922cd90SDarrick J. Wong
68468c58e9bSDarrick J. Wong /* Check owner information. */
685a1f69417SEric Sandeen error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner,
68668c58e9bSDarrick J. Wong offset, flags);
68768c58e9bSDarrick J. Wong if (error)
68868c58e9bSDarrick J. Wong goto out_error;
689f922cd90SDarrick J. Wong
690f922cd90SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
691f922cd90SDarrick J. Wong /* exact match, simply remove the record from rmap tree */
69250f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
693f922cd90SDarrick J. Wong ltrec.rm_startblock, ltrec.rm_blockcount,
694f922cd90SDarrick J. Wong ltrec.rm_owner, ltrec.rm_offset,
695f922cd90SDarrick J. Wong ltrec.rm_flags);
696f922cd90SDarrick J. Wong error = xfs_btree_delete(cur, &i);
697f922cd90SDarrick J. Wong if (error)
698f922cd90SDarrick J. Wong goto out_error;
699f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
700f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
701f9e03706SDarrick J. Wong goto out_error;
702f9e03706SDarrick J. Wong }
703f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock == bno) {
704f922cd90SDarrick J. Wong /*
705f922cd90SDarrick J. Wong * overlap left hand side of extent: move the start, trim the
706f922cd90SDarrick J. Wong * length and update the current record.
707f922cd90SDarrick J. Wong *
708f922cd90SDarrick J. Wong * ltbno ltlen
709f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo|
710f922cd90SDarrick J. Wong * Freeing: |fffffffff|
711f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr|
712f922cd90SDarrick J. Wong * bno len
713f922cd90SDarrick J. Wong */
714f922cd90SDarrick J. Wong ltrec.rm_startblock += len;
715f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len;
716f922cd90SDarrick J. Wong if (!ignore_off)
717f922cd90SDarrick J. Wong ltrec.rm_offset += len;
718f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
719f922cd90SDarrick J. Wong if (error)
720f922cd90SDarrick J. Wong goto out_error;
721f922cd90SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
722f922cd90SDarrick J. Wong /*
723f922cd90SDarrick J. Wong * overlap right hand side of extent: trim the length and update
724f922cd90SDarrick J. Wong * the current record.
725f922cd90SDarrick J. Wong *
726f922cd90SDarrick J. Wong * ltbno ltlen
727f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo|
728f922cd90SDarrick J. Wong * Freeing: |fffffffff|
729f922cd90SDarrick J. Wong * Result: |rrrrrrrrrr|
730f922cd90SDarrick J. Wong * bno len
731f922cd90SDarrick J. Wong */
732f922cd90SDarrick J. Wong ltrec.rm_blockcount -= len;
733f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
734f922cd90SDarrick J. Wong if (error)
735f922cd90SDarrick J. Wong goto out_error;
736f922cd90SDarrick J. Wong } else {
737f922cd90SDarrick J. Wong
738f922cd90SDarrick J. Wong /*
739f922cd90SDarrick J. Wong * overlap middle of extent: trim the length of the existing
740f922cd90SDarrick J. Wong * record to the length of the new left-extent size, increment
741f922cd90SDarrick J. Wong * the insertion position so we can insert a new record
742f922cd90SDarrick J. Wong * containing the remaining right-extent space.
743f922cd90SDarrick J. Wong *
744f922cd90SDarrick J. Wong * ltbno ltlen
745f922cd90SDarrick J. Wong * Orig: |oooooooooooooooooooo|
746f922cd90SDarrick J. Wong * Freeing: |fffffffff|
747f922cd90SDarrick J. Wong * Result: |rrrrr| |rrrr|
748f922cd90SDarrick J. Wong * bno len
749f922cd90SDarrick J. Wong */
750f922cd90SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount;
751f922cd90SDarrick J. Wong
752f922cd90SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock;
753f922cd90SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
754f922cd90SDarrick J. Wong if (error)
755f922cd90SDarrick J. Wong goto out_error;
756f922cd90SDarrick J. Wong
757f922cd90SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
758f922cd90SDarrick J. Wong if (error)
759f922cd90SDarrick J. Wong goto out_error;
760f922cd90SDarrick J. Wong
761f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno + len;
762f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount = orig_len - len -
763f922cd90SDarrick J. Wong ltrec.rm_blockcount;
764f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner = ltrec.rm_owner;
765f922cd90SDarrick J. Wong if (ignore_off)
766f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = 0;
767f922cd90SDarrick J. Wong else
768f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset = offset + len;
769f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags = flags;
77050f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
771f922cd90SDarrick J. Wong cur->bc_rec.r.rm_startblock,
772f922cd90SDarrick J. Wong cur->bc_rec.r.rm_blockcount,
773f922cd90SDarrick J. Wong cur->bc_rec.r.rm_owner,
774f922cd90SDarrick J. Wong cur->bc_rec.r.rm_offset,
775f922cd90SDarrick J. Wong cur->bc_rec.r.rm_flags);
776f922cd90SDarrick J. Wong error = xfs_btree_insert(cur, &i);
777f922cd90SDarrick J. Wong if (error)
778f922cd90SDarrick J. Wong goto out_error;
779f922cd90SDarrick J. Wong }
780f922cd90SDarrick J. Wong
781f922cd90SDarrick J. Wong out_done:
78250f02fe3SDave Chinner trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
783f922cd90SDarrick J. Wong unwritten, oinfo);
784f922cd90SDarrick J. Wong out_error:
785f922cd90SDarrick J. Wong if (error)
78650f02fe3SDave Chinner trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
787f922cd90SDarrick J. Wong error, _RET_IP_);
788f922cd90SDarrick J. Wong return error;
789f922cd90SDarrick J. Wong }
790f922cd90SDarrick J. Wong
791f922cd90SDarrick J. Wong /*
792f922cd90SDarrick J. Wong * Remove a reference to an extent in the rmap btree.
793f922cd90SDarrick J. Wong */
794673930c3SDarrick 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)795673930c3SDarrick J. Wong xfs_rmap_free(
796673930c3SDarrick J. Wong struct xfs_trans *tp,
797673930c3SDarrick J. Wong struct xfs_buf *agbp,
798fa9c3c19SDave Chinner struct xfs_perag *pag,
799673930c3SDarrick J. Wong xfs_agblock_t bno,
800673930c3SDarrick J. Wong xfs_extlen_t len,
80166e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
802673930c3SDarrick J. Wong {
803673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp;
804f922cd90SDarrick J. Wong struct xfs_btree_cur *cur;
805f922cd90SDarrick J. Wong int error;
806673930c3SDarrick J. Wong
80738c26bfdSDave Chinner if (!xfs_has_rmapbt(mp))
808673930c3SDarrick J. Wong return 0;
809673930c3SDarrick J. Wong
810fa9c3c19SDave Chinner cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
811f922cd90SDarrick J. Wong
812f922cd90SDarrick J. Wong error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
813f922cd90SDarrick J. Wong
8140b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error);
815673930c3SDarrick J. Wong return error;
816673930c3SDarrick J. Wong }
817673930c3SDarrick J. Wong
8180a1b0b38SDarrick J. Wong /*
8190a1b0b38SDarrick J. Wong * A mergeable rmap must have the same owner and the same values for
8200a1b0b38SDarrick J. Wong * the unwritten, attr_fork, and bmbt flags. The startblock and
8210a1b0b38SDarrick J. Wong * offset are checked separately.
8220a1b0b38SDarrick J. Wong */
8230a1b0b38SDarrick J. Wong static bool
xfs_rmap_is_mergeable(struct xfs_rmap_irec * irec,uint64_t owner,unsigned int flags)8240a1b0b38SDarrick J. Wong xfs_rmap_is_mergeable(
8250a1b0b38SDarrick J. Wong struct xfs_rmap_irec *irec,
8260a1b0b38SDarrick J. Wong uint64_t owner,
8270a1b0b38SDarrick J. Wong unsigned int flags)
8280a1b0b38SDarrick J. Wong {
8290a1b0b38SDarrick J. Wong if (irec->rm_owner == XFS_RMAP_OWN_NULL)
8300a1b0b38SDarrick J. Wong return false;
8310a1b0b38SDarrick J. Wong if (irec->rm_owner != owner)
8320a1b0b38SDarrick J. Wong return false;
8330a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_UNWRITTEN) ^
8340a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_UNWRITTEN))
8350a1b0b38SDarrick J. Wong return false;
8360a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_ATTR_FORK) ^
8370a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_ATTR_FORK))
8380a1b0b38SDarrick J. Wong return false;
8390a1b0b38SDarrick J. Wong if ((flags & XFS_RMAP_BMBT_BLOCK) ^
8400a1b0b38SDarrick J. Wong (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
8410a1b0b38SDarrick J. Wong return false;
8420a1b0b38SDarrick J. Wong return true;
8430a1b0b38SDarrick J. Wong }
8440a1b0b38SDarrick J. Wong
8450a1b0b38SDarrick J. Wong /*
8460a1b0b38SDarrick J. Wong * When we allocate a new block, the first thing we do is add a reference to
8470a1b0b38SDarrick J. Wong * the extent in the rmap btree. This takes the form of a [agbno, length,
8480a1b0b38SDarrick J. Wong * owner, offset] record. Flags are encoded in the high bits of the offset
8490a1b0b38SDarrick J. Wong * field.
8500a1b0b38SDarrick J. Wong */
8510a1b0b38SDarrick 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)8520a1b0b38SDarrick J. Wong xfs_rmap_map(
8530a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur,
8540a1b0b38SDarrick J. Wong xfs_agblock_t bno,
8550a1b0b38SDarrick J. Wong xfs_extlen_t len,
8560a1b0b38SDarrick J. Wong bool unwritten,
85766e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
8580a1b0b38SDarrick J. Wong {
8590a1b0b38SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
8600a1b0b38SDarrick J. Wong struct xfs_rmap_irec ltrec;
8610a1b0b38SDarrick J. Wong struct xfs_rmap_irec gtrec;
8620a1b0b38SDarrick J. Wong int have_gt;
8630a1b0b38SDarrick J. Wong int have_lt;
8640a1b0b38SDarrick J. Wong int error = 0;
8650a1b0b38SDarrick J. Wong int i;
8660a1b0b38SDarrick J. Wong uint64_t owner;
8670a1b0b38SDarrick J. Wong uint64_t offset;
8680a1b0b38SDarrick J. Wong unsigned int flags = 0;
8690a1b0b38SDarrick J. Wong bool ignore_off;
8700a1b0b38SDarrick J. Wong
8710a1b0b38SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
8720a1b0b38SDarrick J. Wong ASSERT(owner != 0);
8730a1b0b38SDarrick J. Wong ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
8740a1b0b38SDarrick J. Wong (flags & XFS_RMAP_BMBT_BLOCK);
8750a1b0b38SDarrick J. Wong if (unwritten)
8760a1b0b38SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN;
87750f02fe3SDave Chinner trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
8780a1b0b38SDarrick J. Wong unwritten, oinfo);
87933df3a9cSDarrick J. Wong ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
8800a1b0b38SDarrick J. Wong
8810a1b0b38SDarrick J. Wong /*
8820a1b0b38SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent
8830a1b0b38SDarrick J. Wong * record for our insertion point. This will also give us the record for
8840a1b0b38SDarrick J. Wong * start block contiguity tests.
8850a1b0b38SDarrick J. Wong */
8865b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, <rec,
8870a1b0b38SDarrick J. Wong &have_lt);
8880a1b0b38SDarrick J. Wong if (error)
8890a1b0b38SDarrick J. Wong goto out_error;
890fa248de9SDarrick J. Wong if (have_lt) {
8910a1b0b38SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
89250f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
8930a1b0b38SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
8940a1b0b38SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags);
8950a1b0b38SDarrick J. Wong
8960a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(<rec, owner, flags))
8970a1b0b38SDarrick J. Wong have_lt = 0;
898fa248de9SDarrick J. Wong }
8990a1b0b38SDarrick J. Wong
900f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
901f9e03706SDarrick J. Wong have_lt != 0 &&
902f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
903f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
904f9e03706SDarrick J. Wong goto out_error;
905f9e03706SDarrick J. Wong }
9060a1b0b38SDarrick J. Wong
9070a1b0b38SDarrick J. Wong /*
9080a1b0b38SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our
9090a1b0b38SDarrick J. Wong * insertion point. This will give us the record for end block
9100a1b0b38SDarrick J. Wong * contiguity tests.
9110a1b0b38SDarrick J. Wong */
9120a1b0b38SDarrick J. Wong error = xfs_btree_increment(cur, 0, &have_gt);
9130a1b0b38SDarrick J. Wong if (error)
9140a1b0b38SDarrick J. Wong goto out_error;
9150a1b0b38SDarrick J. Wong if (have_gt) {
9160a1b0b38SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt);
9170a1b0b38SDarrick J. Wong if (error)
9180a1b0b38SDarrick J. Wong goto out_error;
919f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
920f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
921f9e03706SDarrick J. Wong goto out_error;
922f9e03706SDarrick J. Wong }
923f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
924f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
925f9e03706SDarrick J. Wong goto out_error;
926f9e03706SDarrick J. Wong }
9270a1b0b38SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
92850f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
9290a1b0b38SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner,
9300a1b0b38SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags);
9310a1b0b38SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags))
9320a1b0b38SDarrick J. Wong have_gt = 0;
9330a1b0b38SDarrick J. Wong }
9340a1b0b38SDarrick J. Wong
9350a1b0b38SDarrick J. Wong /*
9360a1b0b38SDarrick J. Wong * Note: cursor currently points one record to the right of ltrec, even
9370a1b0b38SDarrick J. Wong * if there is no record in the tree to the right.
9380a1b0b38SDarrick J. Wong */
9390a1b0b38SDarrick J. Wong if (have_lt &&
9400a1b0b38SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
9410a1b0b38SDarrick J. Wong (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
9420a1b0b38SDarrick J. Wong /*
9430a1b0b38SDarrick J. Wong * left edge contiguous, merge into left record.
9440a1b0b38SDarrick J. Wong *
9450a1b0b38SDarrick J. Wong * ltbno ltlen
9460a1b0b38SDarrick J. Wong * orig: |ooooooooo|
9470a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa|
9480a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr|
9490a1b0b38SDarrick J. Wong * bno len
9500a1b0b38SDarrick J. Wong */
9510a1b0b38SDarrick J. Wong ltrec.rm_blockcount += len;
9520a1b0b38SDarrick J. Wong if (have_gt &&
9530a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock &&
9540a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset) &&
9550a1b0b38SDarrick J. Wong (unsigned long)ltrec.rm_blockcount + len +
9560a1b0b38SDarrick J. Wong gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
9570a1b0b38SDarrick J. Wong /*
9580a1b0b38SDarrick J. Wong * right edge also contiguous, delete right record
9590a1b0b38SDarrick J. Wong * and merge into left record.
9600a1b0b38SDarrick J. Wong *
9610a1b0b38SDarrick J. Wong * ltbno ltlen gtbno gtlen
9620a1b0b38SDarrick J. Wong * orig: |ooooooooo| |ooooooooo|
9630a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa|
9640a1b0b38SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
9650a1b0b38SDarrick J. Wong */
9660a1b0b38SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount;
96750f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
9680a1b0b38SDarrick J. Wong gtrec.rm_startblock,
9690a1b0b38SDarrick J. Wong gtrec.rm_blockcount,
9700a1b0b38SDarrick J. Wong gtrec.rm_owner,
9710a1b0b38SDarrick J. Wong gtrec.rm_offset,
9720a1b0b38SDarrick J. Wong gtrec.rm_flags);
9730a1b0b38SDarrick J. Wong error = xfs_btree_delete(cur, &i);
9740a1b0b38SDarrick J. Wong if (error)
9750a1b0b38SDarrick J. Wong goto out_error;
976f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
977f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
978f9e03706SDarrick J. Wong goto out_error;
979f9e03706SDarrick J. Wong }
9800a1b0b38SDarrick J. Wong }
9810a1b0b38SDarrick J. Wong
9820a1b0b38SDarrick J. Wong /* point the cursor back to the left record and update */
9830a1b0b38SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &have_gt);
9840a1b0b38SDarrick J. Wong if (error)
9850a1b0b38SDarrick J. Wong goto out_error;
9860a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
9870a1b0b38SDarrick J. Wong if (error)
9880a1b0b38SDarrick J. Wong goto out_error;
9890a1b0b38SDarrick J. Wong } else if (have_gt &&
9900a1b0b38SDarrick J. Wong bno + len == gtrec.rm_startblock &&
9910a1b0b38SDarrick J. Wong (ignore_off || offset + len == gtrec.rm_offset)) {
9920a1b0b38SDarrick J. Wong /*
9930a1b0b38SDarrick J. Wong * right edge contiguous, merge into right record.
9940a1b0b38SDarrick J. Wong *
9950a1b0b38SDarrick J. Wong * gtbno gtlen
9960a1b0b38SDarrick J. Wong * Orig: |ooooooooo|
9970a1b0b38SDarrick J. Wong * adding: |aaaaaaaaa|
9980a1b0b38SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr|
9990a1b0b38SDarrick J. Wong * bno len
10000a1b0b38SDarrick J. Wong */
10010a1b0b38SDarrick J. Wong gtrec.rm_startblock = bno;
10020a1b0b38SDarrick J. Wong gtrec.rm_blockcount += len;
10030a1b0b38SDarrick J. Wong if (!ignore_off)
10040a1b0b38SDarrick J. Wong gtrec.rm_offset = offset;
10050a1b0b38SDarrick J. Wong error = xfs_rmap_update(cur, >rec);
10060a1b0b38SDarrick J. Wong if (error)
10070a1b0b38SDarrick J. Wong goto out_error;
10080a1b0b38SDarrick J. Wong } else {
10090a1b0b38SDarrick J. Wong /*
10100a1b0b38SDarrick J. Wong * no contiguous edge with identical owner, insert
10110a1b0b38SDarrick J. Wong * new record at current cursor position.
10120a1b0b38SDarrick J. Wong */
10130a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_startblock = bno;
10140a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_blockcount = len;
10150a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_owner = owner;
10160a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_offset = offset;
10170a1b0b38SDarrick J. Wong cur->bc_rec.r.rm_flags = flags;
101850f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
10190a1b0b38SDarrick J. Wong owner, offset, flags);
10200a1b0b38SDarrick J. Wong error = xfs_btree_insert(cur, &i);
10210a1b0b38SDarrick J. Wong if (error)
10220a1b0b38SDarrick J. Wong goto out_error;
1023f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1024f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1025f9e03706SDarrick J. Wong goto out_error;
1026f9e03706SDarrick J. Wong }
10270a1b0b38SDarrick J. Wong }
10280a1b0b38SDarrick J. Wong
102950f02fe3SDave Chinner trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
10300a1b0b38SDarrick J. Wong unwritten, oinfo);
10310a1b0b38SDarrick J. Wong out_error:
10320a1b0b38SDarrick J. Wong if (error)
103350f02fe3SDave Chinner trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
10340a1b0b38SDarrick J. Wong error, _RET_IP_);
10350a1b0b38SDarrick J. Wong return error;
10360a1b0b38SDarrick J. Wong }
10370a1b0b38SDarrick J. Wong
10380a1b0b38SDarrick J. Wong /*
10390a1b0b38SDarrick J. Wong * Add a reference to an extent in the rmap btree.
10400a1b0b38SDarrick J. Wong */
1041673930c3SDarrick 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)1042673930c3SDarrick J. Wong xfs_rmap_alloc(
1043673930c3SDarrick J. Wong struct xfs_trans *tp,
1044673930c3SDarrick J. Wong struct xfs_buf *agbp,
1045fa9c3c19SDave Chinner struct xfs_perag *pag,
1046673930c3SDarrick J. Wong xfs_agblock_t bno,
1047673930c3SDarrick J. Wong xfs_extlen_t len,
104866e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
1049673930c3SDarrick J. Wong {
1050673930c3SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp;
10510a1b0b38SDarrick J. Wong struct xfs_btree_cur *cur;
10520a1b0b38SDarrick J. Wong int error;
1053673930c3SDarrick J. Wong
105438c26bfdSDave Chinner if (!xfs_has_rmapbt(mp))
1055673930c3SDarrick J. Wong return 0;
1056673930c3SDarrick J. Wong
1057fa9c3c19SDave Chinner cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
10580a1b0b38SDarrick J. Wong error = xfs_rmap_map(cur, bno, len, false, oinfo);
10590a1b0b38SDarrick J. Wong
10600b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error);
1061673930c3SDarrick J. Wong return error;
1062673930c3SDarrick J. Wong }
1063c543838aSDarrick J. Wong
1064fb7d9267SDarrick J. Wong #define RMAP_LEFT_CONTIG (1 << 0)
1065fb7d9267SDarrick J. Wong #define RMAP_RIGHT_CONTIG (1 << 1)
1066fb7d9267SDarrick J. Wong #define RMAP_LEFT_FILLING (1 << 2)
1067fb7d9267SDarrick J. Wong #define RMAP_RIGHT_FILLING (1 << 3)
1068fb7d9267SDarrick J. Wong #define RMAP_LEFT_VALID (1 << 6)
1069fb7d9267SDarrick J. Wong #define RMAP_RIGHT_VALID (1 << 7)
1070fb7d9267SDarrick J. Wong
1071fb7d9267SDarrick J. Wong #define LEFT r[0]
1072fb7d9267SDarrick J. Wong #define RIGHT r[1]
1073fb7d9267SDarrick J. Wong #define PREV r[2]
1074fb7d9267SDarrick J. Wong #define NEW r[3]
1075fb7d9267SDarrick J. Wong
1076fb7d9267SDarrick J. Wong /*
1077fb7d9267SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa.
1078fb7d9267SDarrick J. Wong * Does not handle overlapping extents.
1079fb7d9267SDarrick J. Wong */
1080fb7d9267SDarrick 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)1081fb7d9267SDarrick J. Wong xfs_rmap_convert(
1082fb7d9267SDarrick J. Wong struct xfs_btree_cur *cur,
1083fb7d9267SDarrick J. Wong xfs_agblock_t bno,
1084fb7d9267SDarrick J. Wong xfs_extlen_t len,
1085fb7d9267SDarrick J. Wong bool unwritten,
108666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
1087fb7d9267SDarrick J. Wong {
1088fb7d9267SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
1089fb7d9267SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */
109066e3237eSDarrick J. Wong /* left is 0, right is 1, */
109166e3237eSDarrick J. Wong /* prev is 2, new is 3 */
1092fb7d9267SDarrick J. Wong uint64_t owner;
1093fb7d9267SDarrick J. Wong uint64_t offset;
1094fb7d9267SDarrick J. Wong uint64_t new_endoff;
1095fb7d9267SDarrick J. Wong unsigned int oldext;
1096fb7d9267SDarrick J. Wong unsigned int newext;
1097fb7d9267SDarrick J. Wong unsigned int flags = 0;
1098fb7d9267SDarrick J. Wong int i;
1099fb7d9267SDarrick J. Wong int state = 0;
1100fb7d9267SDarrick J. Wong int error;
1101fb7d9267SDarrick J. Wong
1102fb7d9267SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1103fb7d9267SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1104fb7d9267SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1105fb7d9267SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1106fb7d9267SDarrick J. Wong new_endoff = offset + len;
110750f02fe3SDave Chinner trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1108fb7d9267SDarrick J. Wong unwritten, oinfo);
1109fb7d9267SDarrick J. Wong
1110fb7d9267SDarrick J. Wong /*
1111fb7d9267SDarrick J. Wong * For the initial lookup, look for an exact match or the left-adjacent
1112fb7d9267SDarrick J. Wong * record for our insertion point. This will also give us the record for
1113fb7d9267SDarrick J. Wong * start block contiguity tests.
1114fb7d9267SDarrick J. Wong */
11155b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1116fb7d9267SDarrick J. Wong if (error)
1117fb7d9267SDarrick J. Wong goto done;
1118f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1119f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1120f9e03706SDarrick J. Wong goto done;
1121f9e03706SDarrick J. Wong }
1122fb7d9267SDarrick J. Wong
1123fb7d9267SDarrick J. Wong trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
112450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1125fb7d9267SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner,
1126fb7d9267SDarrick J. Wong PREV.rm_offset, PREV.rm_flags);
1127fb7d9267SDarrick J. Wong
1128fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset <= offset);
1129fb7d9267SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1130fb7d9267SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1131fb7d9267SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN;
1132fb7d9267SDarrick J. Wong
1133fb7d9267SDarrick J. Wong /*
1134fb7d9267SDarrick J. Wong * Set flags determining what part of the previous oldext allocation
1135fb7d9267SDarrick J. Wong * extent is being replaced by a newext allocation.
1136fb7d9267SDarrick J. Wong */
1137fb7d9267SDarrick J. Wong if (PREV.rm_offset == offset)
1138fb7d9267SDarrick J. Wong state |= RMAP_LEFT_FILLING;
1139fb7d9267SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1140fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_FILLING;
1141fb7d9267SDarrick J. Wong
1142fb7d9267SDarrick J. Wong /*
1143fb7d9267SDarrick J. Wong * Decrement the cursor to see if we have a left-adjacent record to our
1144fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block
1145fb7d9267SDarrick J. Wong * contiguity tests.
1146fb7d9267SDarrick J. Wong */
1147fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i);
1148fb7d9267SDarrick J. Wong if (error)
1149fb7d9267SDarrick J. Wong goto done;
1150fb7d9267SDarrick J. Wong if (i) {
1151fb7d9267SDarrick J. Wong state |= RMAP_LEFT_VALID;
1152fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &LEFT, &i);
1153fb7d9267SDarrick J. Wong if (error)
1154fb7d9267SDarrick J. Wong goto done;
1155f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1156f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1157f9e03706SDarrick J. Wong goto done;
1158f9e03706SDarrick J. Wong }
1159f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
1160f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount >
1161f9e03706SDarrick J. Wong bno)) {
1162f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1163f9e03706SDarrick J. Wong goto done;
1164f9e03706SDarrick J. Wong }
1165fb7d9267SDarrick J. Wong trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
116650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1167fb7d9267SDarrick J. Wong LEFT.rm_blockcount, LEFT.rm_owner,
1168fb7d9267SDarrick J. Wong LEFT.rm_offset, LEFT.rm_flags);
1169fb7d9267SDarrick J. Wong if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1170fb7d9267SDarrick J. Wong LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1171fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&LEFT, owner, newext))
1172fb7d9267SDarrick J. Wong state |= RMAP_LEFT_CONTIG;
1173fb7d9267SDarrick J. Wong }
1174fb7d9267SDarrick J. Wong
1175fb7d9267SDarrick J. Wong /*
1176fb7d9267SDarrick J. Wong * Increment the cursor to see if we have a right-adjacent record to our
1177fb7d9267SDarrick J. Wong * insertion point. This will give us the record for end block
1178fb7d9267SDarrick J. Wong * contiguity tests.
1179fb7d9267SDarrick J. Wong */
1180fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
1181fb7d9267SDarrick J. Wong if (error)
1182fb7d9267SDarrick J. Wong goto done;
1183f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1184f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1185f9e03706SDarrick J. Wong goto done;
1186f9e03706SDarrick J. Wong }
1187fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
1188fb7d9267SDarrick J. Wong if (error)
1189fb7d9267SDarrick J. Wong goto done;
1190fb7d9267SDarrick J. Wong if (i) {
1191fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_VALID;
1192fb7d9267SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1193fb7d9267SDarrick J. Wong if (error)
1194fb7d9267SDarrick J. Wong goto done;
1195f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1196f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1197f9e03706SDarrick J. Wong goto done;
1198f9e03706SDarrick J. Wong }
1199f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1200f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1201f9e03706SDarrick J. Wong goto done;
1202f9e03706SDarrick J. Wong }
1203fb7d9267SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
120450f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1205fb7d9267SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner,
1206fb7d9267SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags);
1207fb7d9267SDarrick J. Wong if (bno + len == RIGHT.rm_startblock &&
1208fb7d9267SDarrick J. Wong offset + len == RIGHT.rm_offset &&
1209fb7d9267SDarrick J. Wong xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1210fb7d9267SDarrick J. Wong state |= RMAP_RIGHT_CONTIG;
1211fb7d9267SDarrick J. Wong }
1212fb7d9267SDarrick J. Wong
1213fb7d9267SDarrick J. Wong /* check that left + prev + right is not too long */
1214fb7d9267SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1215fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1216fb7d9267SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1217fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1218fb7d9267SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len +
1219fb7d9267SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1220fb7d9267SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG;
1221fb7d9267SDarrick J. Wong
122250f02fe3SDave Chinner trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1223fb7d9267SDarrick J. Wong _RET_IP_);
1224fb7d9267SDarrick J. Wong
1225fb7d9267SDarrick J. Wong /* reset the cursor back to PREV */
12265b7ca8b3SDarrick J. Wong error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1227fb7d9267SDarrick J. Wong if (error)
1228fb7d9267SDarrick J. Wong goto done;
1229f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1230f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1231f9e03706SDarrick J. Wong goto done;
1232f9e03706SDarrick J. Wong }
1233fb7d9267SDarrick J. Wong
1234fb7d9267SDarrick J. Wong /*
1235fb7d9267SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits.
1236fb7d9267SDarrick J. Wong */
1237fb7d9267SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1238fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1239fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1240fb7d9267SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1241fb7d9267SDarrick J. Wong /*
1242fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext.
1243fb7d9267SDarrick J. Wong * The left and right neighbors are both contiguous with new.
1244fb7d9267SDarrick J. Wong */
1245fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
1246fb7d9267SDarrick J. Wong if (error)
1247fb7d9267SDarrick J. Wong goto done;
1248f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1249f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1250f9e03706SDarrick J. Wong goto done;
1251f9e03706SDarrick J. Wong }
125250f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1253fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount,
1254fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset,
1255fb7d9267SDarrick J. Wong RIGHT.rm_flags);
1256fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i);
1257fb7d9267SDarrick J. Wong if (error)
1258fb7d9267SDarrick J. Wong goto done;
1259f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1260f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1261f9e03706SDarrick J. Wong goto done;
1262f9e03706SDarrick J. Wong }
1263fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i);
1264fb7d9267SDarrick J. Wong if (error)
1265fb7d9267SDarrick J. Wong goto done;
1266f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1267f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1268f9e03706SDarrick J. Wong goto done;
1269f9e03706SDarrick J. Wong }
127050f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1271fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount,
1272fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset,
1273fb7d9267SDarrick J. Wong PREV.rm_flags);
1274fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i);
1275fb7d9267SDarrick J. Wong if (error)
1276fb7d9267SDarrick J. Wong goto done;
1277f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1278f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1279f9e03706SDarrick J. Wong goto done;
1280f9e03706SDarrick J. Wong }
1281fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i);
1282fb7d9267SDarrick J. Wong if (error)
1283fb7d9267SDarrick J. Wong goto done;
1284f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1285f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1286f9e03706SDarrick J. Wong goto done;
1287f9e03706SDarrick J. Wong }
1288fb7d9267SDarrick J. Wong NEW = LEFT;
1289fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1290fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1291fb7d9267SDarrick J. Wong if (error)
1292fb7d9267SDarrick J. Wong goto done;
1293fb7d9267SDarrick J. Wong break;
1294fb7d9267SDarrick J. Wong
1295fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1296fb7d9267SDarrick J. Wong /*
1297fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext.
1298fb7d9267SDarrick J. Wong * The left neighbor is contiguous, the right is not.
1299fb7d9267SDarrick J. Wong */
130050f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1301fb7d9267SDarrick J. Wong PREV.rm_startblock, PREV.rm_blockcount,
1302fb7d9267SDarrick J. Wong PREV.rm_owner, PREV.rm_offset,
1303fb7d9267SDarrick J. Wong PREV.rm_flags);
1304fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i);
1305fb7d9267SDarrick J. Wong if (error)
1306fb7d9267SDarrick J. Wong goto done;
1307f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1308f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1309f9e03706SDarrick J. Wong goto done;
1310f9e03706SDarrick J. Wong }
1311fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i);
1312fb7d9267SDarrick J. Wong if (error)
1313fb7d9267SDarrick J. Wong goto done;
1314f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1315f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1316f9e03706SDarrick J. Wong goto done;
1317f9e03706SDarrick J. Wong }
1318fb7d9267SDarrick J. Wong NEW = LEFT;
1319fb7d9267SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount;
1320fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1321fb7d9267SDarrick J. Wong if (error)
1322fb7d9267SDarrick J. Wong goto done;
1323fb7d9267SDarrick J. Wong break;
1324fb7d9267SDarrick J. Wong
1325fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1326fb7d9267SDarrick J. Wong /*
1327fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext.
1328fb7d9267SDarrick J. Wong * The right neighbor is contiguous, the left is not.
1329fb7d9267SDarrick J. Wong */
1330fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
1331fb7d9267SDarrick J. Wong if (error)
1332fb7d9267SDarrick J. Wong goto done;
1333f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1334f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1335f9e03706SDarrick J. Wong goto done;
1336f9e03706SDarrick J. Wong }
133750f02fe3SDave Chinner trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1338fb7d9267SDarrick J. Wong RIGHT.rm_startblock, RIGHT.rm_blockcount,
1339fb7d9267SDarrick J. Wong RIGHT.rm_owner, RIGHT.rm_offset,
1340fb7d9267SDarrick J. Wong RIGHT.rm_flags);
1341fb7d9267SDarrick J. Wong error = xfs_btree_delete(cur, &i);
1342fb7d9267SDarrick J. Wong if (error)
1343fb7d9267SDarrick J. Wong goto done;
1344f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1345f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1346f9e03706SDarrick J. Wong goto done;
1347f9e03706SDarrick J. Wong }
1348fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i);
1349fb7d9267SDarrick J. Wong if (error)
1350fb7d9267SDarrick J. Wong goto done;
1351f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1352f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1353f9e03706SDarrick J. Wong goto done;
1354f9e03706SDarrick J. Wong }
1355fb7d9267SDarrick J. Wong NEW = PREV;
1356fb7d9267SDarrick J. Wong NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1357fb7d9267SDarrick J. Wong NEW.rm_flags = newext;
1358fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1359fb7d9267SDarrick J. Wong if (error)
1360fb7d9267SDarrick J. Wong goto done;
1361fb7d9267SDarrick J. Wong break;
1362fb7d9267SDarrick J. Wong
1363fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1364fb7d9267SDarrick J. Wong /*
1365fb7d9267SDarrick J. Wong * Setting all of a previous oldext extent to newext.
1366fb7d9267SDarrick J. Wong * Neither the left nor right neighbors are contiguous with
1367fb7d9267SDarrick J. Wong * the new one.
1368fb7d9267SDarrick J. Wong */
1369fb7d9267SDarrick J. Wong NEW = PREV;
1370fb7d9267SDarrick J. Wong NEW.rm_flags = newext;
1371fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1372fb7d9267SDarrick J. Wong if (error)
1373fb7d9267SDarrick J. Wong goto done;
1374fb7d9267SDarrick J. Wong break;
1375fb7d9267SDarrick J. Wong
1376fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1377fb7d9267SDarrick J. Wong /*
1378fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext.
1379fb7d9267SDarrick J. Wong * The left neighbor is contiguous.
1380fb7d9267SDarrick J. Wong */
1381fb7d9267SDarrick J. Wong NEW = PREV;
1382fb7d9267SDarrick J. Wong NEW.rm_offset += len;
1383fb7d9267SDarrick J. Wong NEW.rm_startblock += len;
1384fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len;
1385fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1386fb7d9267SDarrick J. Wong if (error)
1387fb7d9267SDarrick J. Wong goto done;
1388fb7d9267SDarrick J. Wong error = xfs_btree_decrement(cur, 0, &i);
1389fb7d9267SDarrick J. Wong if (error)
1390fb7d9267SDarrick J. Wong goto done;
1391fb7d9267SDarrick J. Wong NEW = LEFT;
1392fb7d9267SDarrick J. Wong NEW.rm_blockcount += len;
1393fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1394fb7d9267SDarrick J. Wong if (error)
1395fb7d9267SDarrick J. Wong goto done;
1396fb7d9267SDarrick J. Wong break;
1397fb7d9267SDarrick J. Wong
1398fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING:
1399fb7d9267SDarrick J. Wong /*
1400fb7d9267SDarrick J. Wong * Setting the first part of a previous oldext extent to newext.
1401fb7d9267SDarrick J. Wong * The left neighbor is not contiguous.
1402fb7d9267SDarrick J. Wong */
1403fb7d9267SDarrick J. Wong NEW = PREV;
1404fb7d9267SDarrick J. Wong NEW.rm_startblock += len;
1405fb7d9267SDarrick J. Wong NEW.rm_offset += len;
1406fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len;
1407fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1408fb7d9267SDarrick J. Wong if (error)
1409fb7d9267SDarrick J. Wong goto done;
1410fb7d9267SDarrick J. Wong NEW.rm_startblock = bno;
1411fb7d9267SDarrick J. Wong NEW.rm_owner = owner;
1412fb7d9267SDarrick J. Wong NEW.rm_offset = offset;
1413fb7d9267SDarrick J. Wong NEW.rm_blockcount = len;
1414fb7d9267SDarrick J. Wong NEW.rm_flags = newext;
1415fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW;
141650f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1417fb7d9267SDarrick J. Wong len, owner, offset, newext);
1418fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i);
1419fb7d9267SDarrick J. Wong if (error)
1420fb7d9267SDarrick J. Wong goto done;
1421f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1422f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1423f9e03706SDarrick J. Wong goto done;
1424f9e03706SDarrick J. Wong }
1425fb7d9267SDarrick J. Wong break;
1426fb7d9267SDarrick J. Wong
1427fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1428fb7d9267SDarrick J. Wong /*
1429fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext.
1430fb7d9267SDarrick J. Wong * The right neighbor is contiguous with the new allocation.
1431fb7d9267SDarrick J. Wong */
1432fb7d9267SDarrick J. Wong NEW = PREV;
1433fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len;
1434fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1435fb7d9267SDarrick J. Wong if (error)
1436fb7d9267SDarrick J. Wong goto done;
1437fb7d9267SDarrick J. Wong error = xfs_btree_increment(cur, 0, &i);
1438fb7d9267SDarrick J. Wong if (error)
1439fb7d9267SDarrick J. Wong goto done;
1440fb7d9267SDarrick J. Wong NEW = RIGHT;
1441fb7d9267SDarrick J. Wong NEW.rm_offset = offset;
1442fb7d9267SDarrick J. Wong NEW.rm_startblock = bno;
1443fb7d9267SDarrick J. Wong NEW.rm_blockcount += len;
1444fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1445fb7d9267SDarrick J. Wong if (error)
1446fb7d9267SDarrick J. Wong goto done;
1447fb7d9267SDarrick J. Wong break;
1448fb7d9267SDarrick J. Wong
1449fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING:
1450fb7d9267SDarrick J. Wong /*
1451fb7d9267SDarrick J. Wong * Setting the last part of a previous oldext extent to newext.
1452fb7d9267SDarrick J. Wong * The right neighbor is not contiguous.
1453fb7d9267SDarrick J. Wong */
1454fb7d9267SDarrick J. Wong NEW = PREV;
1455fb7d9267SDarrick J. Wong NEW.rm_blockcount -= len;
1456fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1457fb7d9267SDarrick J. Wong if (error)
1458fb7d9267SDarrick J. Wong goto done;
1459fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1460fb7d9267SDarrick J. Wong oldext, &i);
1461fb7d9267SDarrick J. Wong if (error)
1462fb7d9267SDarrick J. Wong goto done;
1463f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) {
1464f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1465f9e03706SDarrick J. Wong goto done;
1466f9e03706SDarrick J. Wong }
1467fb7d9267SDarrick J. Wong NEW.rm_startblock = bno;
1468fb7d9267SDarrick J. Wong NEW.rm_owner = owner;
1469fb7d9267SDarrick J. Wong NEW.rm_offset = offset;
1470fb7d9267SDarrick J. Wong NEW.rm_blockcount = len;
1471fb7d9267SDarrick J. Wong NEW.rm_flags = newext;
1472fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW;
147350f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1474fb7d9267SDarrick J. Wong len, owner, offset, newext);
1475fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i);
1476fb7d9267SDarrick J. Wong if (error)
1477fb7d9267SDarrick J. Wong goto done;
1478f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1479f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1480f9e03706SDarrick J. Wong goto done;
1481f9e03706SDarrick J. Wong }
1482fb7d9267SDarrick J. Wong break;
1483fb7d9267SDarrick J. Wong
1484fb7d9267SDarrick J. Wong case 0:
1485fb7d9267SDarrick J. Wong /*
1486fb7d9267SDarrick J. Wong * Setting the middle part of a previous oldext extent to
1487fb7d9267SDarrick J. Wong * newext. Contiguity is impossible here.
1488fb7d9267SDarrick J. Wong * One extent becomes three extents.
1489fb7d9267SDarrick J. Wong */
1490fb7d9267SDarrick J. Wong /* new right extent - oldext */
1491fb7d9267SDarrick J. Wong NEW.rm_startblock = bno + len;
1492fb7d9267SDarrick J. Wong NEW.rm_owner = owner;
1493fb7d9267SDarrick J. Wong NEW.rm_offset = new_endoff;
1494fb7d9267SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1495fb7d9267SDarrick J. Wong new_endoff;
1496fb7d9267SDarrick J. Wong NEW.rm_flags = PREV.rm_flags;
1497fb7d9267SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
1498fb7d9267SDarrick J. Wong if (error)
1499fb7d9267SDarrick J. Wong goto done;
1500fb7d9267SDarrick J. Wong /* new left extent - oldext */
1501fb7d9267SDarrick J. Wong NEW = PREV;
1502fb7d9267SDarrick J. Wong NEW.rm_blockcount = offset - PREV.rm_offset;
1503fb7d9267SDarrick J. Wong cur->bc_rec.r = NEW;
150450f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1505fb7d9267SDarrick J. Wong NEW.rm_startblock, NEW.rm_blockcount,
1506fb7d9267SDarrick J. Wong NEW.rm_owner, NEW.rm_offset,
1507fb7d9267SDarrick J. Wong NEW.rm_flags);
1508fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i);
1509fb7d9267SDarrick J. Wong if (error)
1510fb7d9267SDarrick J. Wong goto done;
1511f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1512f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1513f9e03706SDarrick J. Wong goto done;
1514f9e03706SDarrick J. Wong }
1515fb7d9267SDarrick J. Wong /*
1516fb7d9267SDarrick J. Wong * Reset the cursor to the position of the new extent
1517fb7d9267SDarrick J. Wong * we are about to insert as we can't trust it after
1518fb7d9267SDarrick J. Wong * the previous insert.
1519fb7d9267SDarrick J. Wong */
1520fb7d9267SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1521fb7d9267SDarrick J. Wong oldext, &i);
1522fb7d9267SDarrick J. Wong if (error)
1523fb7d9267SDarrick J. Wong goto done;
1524f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 0)) {
1525f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1526f9e03706SDarrick J. Wong goto done;
1527f9e03706SDarrick J. Wong }
1528fb7d9267SDarrick J. Wong /* new middle extent - newext */
1529fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1530fb7d9267SDarrick J. Wong cur->bc_rec.r.rm_flags |= newext;
153150f02fe3SDave Chinner trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1532fb7d9267SDarrick J. Wong owner, offset, newext);
1533fb7d9267SDarrick J. Wong error = xfs_btree_insert(cur, &i);
1534fb7d9267SDarrick J. Wong if (error)
1535fb7d9267SDarrick J. Wong goto done;
1536f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1537f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1538f9e03706SDarrick J. Wong goto done;
1539f9e03706SDarrick J. Wong }
1540fb7d9267SDarrick J. Wong break;
1541fb7d9267SDarrick J. Wong
1542fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1543fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1544fb7d9267SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1545fb7d9267SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1546fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1547fb7d9267SDarrick J. Wong case RMAP_LEFT_CONTIG:
1548fb7d9267SDarrick J. Wong case RMAP_RIGHT_CONTIG:
1549fb7d9267SDarrick J. Wong /*
1550fb7d9267SDarrick J. Wong * These cases are all impossible.
1551fb7d9267SDarrick J. Wong */
1552fb7d9267SDarrick J. Wong ASSERT(0);
1553fb7d9267SDarrick J. Wong }
1554fb7d9267SDarrick J. Wong
155550f02fe3SDave Chinner trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1556fb7d9267SDarrick J. Wong unwritten, oinfo);
1557fb7d9267SDarrick J. Wong done:
1558fb7d9267SDarrick J. Wong if (error)
1559fb7d9267SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp,
156050f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1561fb7d9267SDarrick J. Wong return error;
1562fb7d9267SDarrick J. Wong }
1563fb7d9267SDarrick J. Wong
15643f165b33SDarrick J. Wong /*
15653f165b33SDarrick J. Wong * Convert an unwritten extent to a real extent or vice versa. If there is no
15663f165b33SDarrick J. Wong * possibility of overlapping extents, delegate to the simpler convert
15673f165b33SDarrick J. Wong * function.
15683f165b33SDarrick J. Wong */
15693f165b33SDarrick 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)15703f165b33SDarrick J. Wong xfs_rmap_convert_shared(
15713f165b33SDarrick J. Wong struct xfs_btree_cur *cur,
15723f165b33SDarrick J. Wong xfs_agblock_t bno,
15733f165b33SDarrick J. Wong xfs_extlen_t len,
15743f165b33SDarrick J. Wong bool unwritten,
157566e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
15763f165b33SDarrick J. Wong {
15773f165b33SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
15783f165b33SDarrick J. Wong struct xfs_rmap_irec r[4]; /* neighbor extent entries */
157966e3237eSDarrick J. Wong /* left is 0, right is 1, */
158066e3237eSDarrick J. Wong /* prev is 2, new is 3 */
15813f165b33SDarrick J. Wong uint64_t owner;
15823f165b33SDarrick J. Wong uint64_t offset;
15833f165b33SDarrick J. Wong uint64_t new_endoff;
15843f165b33SDarrick J. Wong unsigned int oldext;
15853f165b33SDarrick J. Wong unsigned int newext;
15863f165b33SDarrick J. Wong unsigned int flags = 0;
15873f165b33SDarrick J. Wong int i;
15883f165b33SDarrick J. Wong int state = 0;
15893f165b33SDarrick J. Wong int error;
15903f165b33SDarrick J. Wong
15913f165b33SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
15923f165b33SDarrick J. Wong ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
15933f165b33SDarrick J. Wong (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
15943f165b33SDarrick J. Wong oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
15953f165b33SDarrick J. Wong new_endoff = offset + len;
159650f02fe3SDave Chinner trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
15973f165b33SDarrick J. Wong unwritten, oinfo);
15983f165b33SDarrick J. Wong
15993f165b33SDarrick J. Wong /*
16003f165b33SDarrick J. Wong * For the initial lookup, look for and exact match or the left-adjacent
16013f165b33SDarrick J. Wong * record for our insertion point. This will also give us the record for
16023f165b33SDarrick J. Wong * start block contiguity tests.
16033f165b33SDarrick J. Wong */
1604ea843989SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
16053f165b33SDarrick J. Wong &PREV, &i);
160652101dfeSDarrick J. Wong if (error)
160752101dfeSDarrick J. Wong goto done;
1608f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1609f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1610f9e03706SDarrick J. Wong goto done;
1611f9e03706SDarrick J. Wong }
16123f165b33SDarrick J. Wong
16133f165b33SDarrick J. Wong ASSERT(PREV.rm_offset <= offset);
16143f165b33SDarrick J. Wong ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
16153f165b33SDarrick J. Wong ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
16163f165b33SDarrick J. Wong newext = ~oldext & XFS_RMAP_UNWRITTEN;
16173f165b33SDarrick J. Wong
16183f165b33SDarrick J. Wong /*
16193f165b33SDarrick J. Wong * Set flags determining what part of the previous oldext allocation
16203f165b33SDarrick J. Wong * extent is being replaced by a newext allocation.
16213f165b33SDarrick J. Wong */
16223f165b33SDarrick J. Wong if (PREV.rm_offset == offset)
16233f165b33SDarrick J. Wong state |= RMAP_LEFT_FILLING;
16243f165b33SDarrick J. Wong if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
16253f165b33SDarrick J. Wong state |= RMAP_RIGHT_FILLING;
16263f165b33SDarrick J. Wong
16273f165b33SDarrick J. Wong /* Is there a left record that abuts our range? */
16283f165b33SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
16293f165b33SDarrick J. Wong &LEFT, &i);
16303f165b33SDarrick J. Wong if (error)
16313f165b33SDarrick J. Wong goto done;
16323f165b33SDarrick J. Wong if (i) {
16333f165b33SDarrick J. Wong state |= RMAP_LEFT_VALID;
1634f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
1635f9e03706SDarrick J. Wong LEFT.rm_startblock + LEFT.rm_blockcount >
1636f9e03706SDarrick J. Wong bno)) {
1637f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1638f9e03706SDarrick J. Wong goto done;
1639f9e03706SDarrick J. Wong }
16403f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
16413f165b33SDarrick J. Wong state |= RMAP_LEFT_CONTIG;
16423f165b33SDarrick J. Wong }
16433f165b33SDarrick J. Wong
16443f165b33SDarrick J. Wong /* Is there a right record that abuts our range? */
16453f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
16463f165b33SDarrick J. Wong newext, &i);
16473f165b33SDarrick J. Wong if (error)
16483f165b33SDarrick J. Wong goto done;
16493f165b33SDarrick J. Wong if (i) {
16503f165b33SDarrick J. Wong state |= RMAP_RIGHT_VALID;
16513f165b33SDarrick J. Wong error = xfs_rmap_get_rec(cur, &RIGHT, &i);
16523f165b33SDarrick J. Wong if (error)
16533f165b33SDarrick J. Wong goto done;
1654f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1655f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1656f9e03706SDarrick J. Wong goto done;
1657f9e03706SDarrick J. Wong }
1658f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1659f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1660f9e03706SDarrick J. Wong goto done;
1661f9e03706SDarrick J. Wong }
16623f165b33SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
166350f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
16643f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner,
16653f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags);
16663f165b33SDarrick J. Wong if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
16673f165b33SDarrick J. Wong state |= RMAP_RIGHT_CONTIG;
16683f165b33SDarrick J. Wong }
16693f165b33SDarrick J. Wong
16703f165b33SDarrick J. Wong /* check that left + prev + right is not too long */
16713f165b33SDarrick J. Wong if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
16723f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
16733f165b33SDarrick J. Wong (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
16743f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
16753f165b33SDarrick J. Wong (unsigned long)LEFT.rm_blockcount + len +
16763f165b33SDarrick J. Wong RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
16773f165b33SDarrick J. Wong state &= ~RMAP_RIGHT_CONTIG;
16783f165b33SDarrick J. Wong
167950f02fe3SDave Chinner trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
16803f165b33SDarrick J. Wong _RET_IP_);
16813f165b33SDarrick J. Wong /*
16823f165b33SDarrick J. Wong * Switch out based on the FILLING and CONTIG state bits.
16833f165b33SDarrick J. Wong */
16843f165b33SDarrick J. Wong switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
16853f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
16863f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
16873f165b33SDarrick J. Wong RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
16883f165b33SDarrick J. Wong /*
16893f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext.
16903f165b33SDarrick J. Wong * The left and right neighbors are both contiguous with new.
16913f165b33SDarrick J. Wong */
16923f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
16933f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner,
16943f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags);
16953f165b33SDarrick J. Wong if (error)
16963f165b33SDarrick J. Wong goto done;
16973f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock,
16983f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner,
16993f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags);
17003f165b33SDarrick J. Wong if (error)
17013f165b33SDarrick J. Wong goto done;
17023f165b33SDarrick J. Wong NEW = LEFT;
17033f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
17043f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
17053f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
17063f165b33SDarrick J. Wong if (error)
17073f165b33SDarrick J. Wong goto done;
1708f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1709f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1710f9e03706SDarrick J. Wong goto done;
1711f9e03706SDarrick J. Wong }
17123f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
17133f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
17143f165b33SDarrick J. Wong if (error)
17153f165b33SDarrick J. Wong goto done;
17163f165b33SDarrick J. Wong break;
17173f165b33SDarrick J. Wong
17183f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
17193f165b33SDarrick J. Wong /*
17203f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext.
17213f165b33SDarrick J. Wong * The left neighbor is contiguous, the right is not.
17223f165b33SDarrick J. Wong */
17233f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, PREV.rm_startblock,
17243f165b33SDarrick J. Wong PREV.rm_blockcount, PREV.rm_owner,
17253f165b33SDarrick J. Wong PREV.rm_offset, PREV.rm_flags);
17263f165b33SDarrick J. Wong if (error)
17273f165b33SDarrick J. Wong goto done;
17283f165b33SDarrick J. Wong NEW = LEFT;
17293f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
17303f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
17313f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
17323f165b33SDarrick J. Wong if (error)
17333f165b33SDarrick J. Wong goto done;
1734f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1735f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1736f9e03706SDarrick J. Wong goto done;
1737f9e03706SDarrick J. Wong }
17383f165b33SDarrick J. Wong NEW.rm_blockcount += PREV.rm_blockcount;
17393f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
17403f165b33SDarrick J. Wong if (error)
17413f165b33SDarrick J. Wong goto done;
17423f165b33SDarrick J. Wong break;
17433f165b33SDarrick J. Wong
17443f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
17453f165b33SDarrick J. Wong /*
17463f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext.
17473f165b33SDarrick J. Wong * The right neighbor is contiguous, the left is not.
17483f165b33SDarrick J. Wong */
17493f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
17503f165b33SDarrick J. Wong RIGHT.rm_blockcount, RIGHT.rm_owner,
17513f165b33SDarrick J. Wong RIGHT.rm_offset, RIGHT.rm_flags);
17523f165b33SDarrick J. Wong if (error)
17533f165b33SDarrick J. Wong goto done;
17543f165b33SDarrick J. Wong NEW = PREV;
17553f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
17563f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
17573f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
17583f165b33SDarrick J. Wong if (error)
17593f165b33SDarrick J. Wong goto done;
1760f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1761f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1762f9e03706SDarrick J. Wong goto done;
1763f9e03706SDarrick J. Wong }
17643f165b33SDarrick J. Wong NEW.rm_blockcount += RIGHT.rm_blockcount;
17653f165b33SDarrick J. Wong NEW.rm_flags = RIGHT.rm_flags;
17663f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
17673f165b33SDarrick J. Wong if (error)
17683f165b33SDarrick J. Wong goto done;
17693f165b33SDarrick J. Wong break;
17703f165b33SDarrick J. Wong
17713f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
17723f165b33SDarrick J. Wong /*
17733f165b33SDarrick J. Wong * Setting all of a previous oldext extent to newext.
17743f165b33SDarrick J. Wong * Neither the left nor right neighbors are contiguous with
17753f165b33SDarrick J. Wong * the new one.
17763f165b33SDarrick J. Wong */
17773f165b33SDarrick J. Wong NEW = PREV;
17783f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
17793f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
17803f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
17813f165b33SDarrick J. Wong if (error)
17823f165b33SDarrick J. Wong goto done;
1783f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1784f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1785f9e03706SDarrick J. Wong goto done;
1786f9e03706SDarrick J. Wong }
17873f165b33SDarrick J. Wong NEW.rm_flags = newext;
17883f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
17893f165b33SDarrick J. Wong if (error)
17903f165b33SDarrick J. Wong goto done;
17913f165b33SDarrick J. Wong break;
17923f165b33SDarrick J. Wong
17933f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
17943f165b33SDarrick J. Wong /*
17953f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext.
17963f165b33SDarrick J. Wong * The left neighbor is contiguous.
17973f165b33SDarrick J. Wong */
17983f165b33SDarrick J. Wong NEW = PREV;
17993f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock,
18003f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18013f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags);
18023f165b33SDarrick J. Wong if (error)
18033f165b33SDarrick J. Wong goto done;
18043f165b33SDarrick J. Wong NEW.rm_offset += len;
18053f165b33SDarrick J. Wong NEW.rm_startblock += len;
18063f165b33SDarrick J. Wong NEW.rm_blockcount -= len;
18073f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock,
18083f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18093f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags);
18103f165b33SDarrick J. Wong if (error)
18113f165b33SDarrick J. Wong goto done;
18123f165b33SDarrick J. Wong NEW = LEFT;
18133f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18143f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18153f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
18163f165b33SDarrick J. Wong if (error)
18173f165b33SDarrick J. Wong goto done;
1818f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1819f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1820f9e03706SDarrick J. Wong goto done;
1821f9e03706SDarrick J. Wong }
18223f165b33SDarrick J. Wong NEW.rm_blockcount += len;
18233f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
18243f165b33SDarrick J. Wong if (error)
18253f165b33SDarrick J. Wong goto done;
18263f165b33SDarrick J. Wong break;
18273f165b33SDarrick J. Wong
18283f165b33SDarrick J. Wong case RMAP_LEFT_FILLING:
18293f165b33SDarrick J. Wong /*
18303f165b33SDarrick J. Wong * Setting the first part of a previous oldext extent to newext.
18313f165b33SDarrick J. Wong * The left neighbor is not contiguous.
18323f165b33SDarrick J. Wong */
18333f165b33SDarrick J. Wong NEW = PREV;
18343f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock,
18353f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18363f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags);
18373f165b33SDarrick J. Wong if (error)
18383f165b33SDarrick J. Wong goto done;
18393f165b33SDarrick J. Wong NEW.rm_offset += len;
18403f165b33SDarrick J. Wong NEW.rm_startblock += len;
18413f165b33SDarrick J. Wong NEW.rm_blockcount -= len;
18423f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock,
18433f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18443f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags);
18453f165b33SDarrick J. Wong if (error)
18463f165b33SDarrick J. Wong goto done;
18473f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
18483f165b33SDarrick J. Wong if (error)
18493f165b33SDarrick J. Wong goto done;
18503f165b33SDarrick J. Wong break;
18513f165b33SDarrick J. Wong
18523f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
18533f165b33SDarrick J. Wong /*
18543f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext.
18553f165b33SDarrick J. Wong * The right neighbor is contiguous with the new allocation.
18563f165b33SDarrick J. Wong */
18573f165b33SDarrick J. Wong NEW = PREV;
18583f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18593f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18603f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
18613f165b33SDarrick J. Wong if (error)
18623f165b33SDarrick J. Wong goto done;
1863f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1864f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1865f9e03706SDarrick J. Wong goto done;
1866f9e03706SDarrick J. Wong }
18673f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset;
18683f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
18693f165b33SDarrick J. Wong if (error)
18703f165b33SDarrick J. Wong goto done;
18713f165b33SDarrick J. Wong NEW = RIGHT;
18723f165b33SDarrick J. Wong error = xfs_rmap_delete(cur, NEW.rm_startblock,
18733f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18743f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags);
18753f165b33SDarrick J. Wong if (error)
18763f165b33SDarrick J. Wong goto done;
18773f165b33SDarrick J. Wong NEW.rm_offset = offset;
18783f165b33SDarrick J. Wong NEW.rm_startblock = bno;
18793f165b33SDarrick J. Wong NEW.rm_blockcount += len;
18803f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock,
18813f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18823f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags);
18833f165b33SDarrick J. Wong if (error)
18843f165b33SDarrick J. Wong goto done;
18853f165b33SDarrick J. Wong break;
18863f165b33SDarrick J. Wong
18873f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING:
18883f165b33SDarrick J. Wong /*
18893f165b33SDarrick J. Wong * Setting the last part of a previous oldext extent to newext.
18903f165b33SDarrick J. Wong * The right neighbor is not contiguous.
18913f165b33SDarrick J. Wong */
18923f165b33SDarrick J. Wong NEW = PREV;
18933f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
18943f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
18953f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
18963f165b33SDarrick J. Wong if (error)
18973f165b33SDarrick J. Wong goto done;
1898f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1899f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1900f9e03706SDarrick J. Wong goto done;
1901f9e03706SDarrick J. Wong }
19023f165b33SDarrick J. Wong NEW.rm_blockcount -= len;
19033f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
19043f165b33SDarrick J. Wong if (error)
19053f165b33SDarrick J. Wong goto done;
19063f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
19073f165b33SDarrick J. Wong if (error)
19083f165b33SDarrick J. Wong goto done;
19093f165b33SDarrick J. Wong break;
19103f165b33SDarrick J. Wong
19113f165b33SDarrick J. Wong case 0:
19123f165b33SDarrick J. Wong /*
19133f165b33SDarrick J. Wong * Setting the middle part of a previous oldext extent to
19143f165b33SDarrick J. Wong * newext. Contiguity is impossible here.
19153f165b33SDarrick J. Wong * One extent becomes three extents.
19163f165b33SDarrick J. Wong */
19173f165b33SDarrick J. Wong /* new right extent - oldext */
19183f165b33SDarrick J. Wong NEW.rm_startblock = bno + len;
19193f165b33SDarrick J. Wong NEW.rm_owner = owner;
19203f165b33SDarrick J. Wong NEW.rm_offset = new_endoff;
19213f165b33SDarrick J. Wong NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
19223f165b33SDarrick J. Wong new_endoff;
19233f165b33SDarrick J. Wong NEW.rm_flags = PREV.rm_flags;
19243f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock,
19253f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
19263f165b33SDarrick J. Wong NEW.rm_flags);
19273f165b33SDarrick J. Wong if (error)
19283f165b33SDarrick J. Wong goto done;
19293f165b33SDarrick J. Wong /* new left extent - oldext */
19303f165b33SDarrick J. Wong NEW = PREV;
19313f165b33SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
19323f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner,
19333f165b33SDarrick J. Wong NEW.rm_offset, NEW.rm_flags, &i);
19343f165b33SDarrick J. Wong if (error)
19353f165b33SDarrick J. Wong goto done;
1936f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
1937f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
1938f9e03706SDarrick J. Wong goto done;
1939f9e03706SDarrick J. Wong }
19403f165b33SDarrick J. Wong NEW.rm_blockcount = offset - NEW.rm_offset;
19413f165b33SDarrick J. Wong error = xfs_rmap_update(cur, &NEW);
19423f165b33SDarrick J. Wong if (error)
19433f165b33SDarrick J. Wong goto done;
19443f165b33SDarrick J. Wong /* new middle extent - newext */
19453f165b33SDarrick J. Wong NEW.rm_startblock = bno;
19463f165b33SDarrick J. Wong NEW.rm_blockcount = len;
19473f165b33SDarrick J. Wong NEW.rm_owner = owner;
19483f165b33SDarrick J. Wong NEW.rm_offset = offset;
19493f165b33SDarrick J. Wong NEW.rm_flags = newext;
19503f165b33SDarrick J. Wong error = xfs_rmap_insert(cur, NEW.rm_startblock,
19513f165b33SDarrick J. Wong NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
19523f165b33SDarrick J. Wong NEW.rm_flags);
19533f165b33SDarrick J. Wong if (error)
19543f165b33SDarrick J. Wong goto done;
19553f165b33SDarrick J. Wong break;
19563f165b33SDarrick J. Wong
19573f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
19583f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
19593f165b33SDarrick J. Wong case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
19603f165b33SDarrick J. Wong case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
19613f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
19623f165b33SDarrick J. Wong case RMAP_LEFT_CONTIG:
19633f165b33SDarrick J. Wong case RMAP_RIGHT_CONTIG:
19643f165b33SDarrick J. Wong /*
19653f165b33SDarrick J. Wong * These cases are all impossible.
19663f165b33SDarrick J. Wong */
19673f165b33SDarrick J. Wong ASSERT(0);
19683f165b33SDarrick J. Wong }
19693f165b33SDarrick J. Wong
197050f02fe3SDave Chinner trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
19713f165b33SDarrick J. Wong unwritten, oinfo);
19723f165b33SDarrick J. Wong done:
19733f165b33SDarrick J. Wong if (error)
19743f165b33SDarrick J. Wong trace_xfs_rmap_convert_error(cur->bc_mp,
197550f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_);
19763f165b33SDarrick J. Wong return error;
19773f165b33SDarrick J. Wong }
19783f165b33SDarrick J. Wong
1979fb7d9267SDarrick J. Wong #undef NEW
1980fb7d9267SDarrick J. Wong #undef LEFT
1981fb7d9267SDarrick J. Wong #undef RIGHT
1982fb7d9267SDarrick J. Wong #undef PREV
1983fb7d9267SDarrick J. Wong
1984ceeb9c83SDarrick J. Wong /*
1985ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and unmap it. For rmap extent types that
1986ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful
1987ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner.
1988ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields.
1989ceeb9c83SDarrick J. Wong *
1990ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent,
1991ceeb9c83SDarrick J. Wong * so we can call the regular _free function.
1992ceeb9c83SDarrick J. Wong */
1993ceeb9c83SDarrick 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)1994ceeb9c83SDarrick J. Wong xfs_rmap_unmap_shared(
1995ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur,
1996ceeb9c83SDarrick J. Wong xfs_agblock_t bno,
1997ceeb9c83SDarrick J. Wong xfs_extlen_t len,
1998ceeb9c83SDarrick J. Wong bool unwritten,
199966e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
2000ceeb9c83SDarrick J. Wong {
2001ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
2002ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec;
2003ceeb9c83SDarrick J. Wong uint64_t ltoff;
2004ceeb9c83SDarrick J. Wong int error = 0;
2005ceeb9c83SDarrick J. Wong int i;
2006ceeb9c83SDarrick J. Wong uint64_t owner;
2007ceeb9c83SDarrick J. Wong uint64_t offset;
2008ceeb9c83SDarrick J. Wong unsigned int flags;
2009ceeb9c83SDarrick J. Wong
2010ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2011ceeb9c83SDarrick J. Wong if (unwritten)
2012ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN;
201350f02fe3SDave Chinner trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
2014ceeb9c83SDarrick J. Wong unwritten, oinfo);
2015ceeb9c83SDarrick J. Wong
2016ceeb9c83SDarrick J. Wong /*
2017ceeb9c83SDarrick J. Wong * We should always have a left record because there's a static record
2018ceeb9c83SDarrick J. Wong * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2019ceeb9c83SDarrick J. Wong * will not ever be removed from the tree.
2020ceeb9c83SDarrick J. Wong */
2021ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2022ceeb9c83SDarrick J. Wong <rec, &i);
2023ceeb9c83SDarrick J. Wong if (error)
2024ceeb9c83SDarrick J. Wong goto out_error;
2025f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
2026f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2027f9e03706SDarrick J. Wong goto out_error;
2028f9e03706SDarrick J. Wong }
2029ceeb9c83SDarrick J. Wong ltoff = ltrec.rm_offset;
2030ceeb9c83SDarrick J. Wong
2031ceeb9c83SDarrick J. Wong /* Make sure the extent we found covers the entire freeing range. */
2032f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
2033f9e03706SDarrick J. Wong ltrec.rm_startblock > bno ||
2034f9e03706SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount <
2035f9e03706SDarrick J. Wong bno + len)) {
2036f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2037f9e03706SDarrick J. Wong goto out_error;
2038f9e03706SDarrick J. Wong }
2039ceeb9c83SDarrick J. Wong
2040ceeb9c83SDarrick J. Wong /* Make sure the owner matches what we expect to find in the tree. */
2041f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
2042f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2043f9e03706SDarrick J. Wong goto out_error;
2044f9e03706SDarrick J. Wong }
2045ceeb9c83SDarrick J. Wong
2046ceeb9c83SDarrick J. Wong /* Make sure the unwritten flag matches. */
2047f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp,
2048f9e03706SDarrick J. Wong (flags & XFS_RMAP_UNWRITTEN) !=
2049f9e03706SDarrick J. Wong (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2050f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2051f9e03706SDarrick J. Wong goto out_error;
2052f9e03706SDarrick J. Wong }
2053ceeb9c83SDarrick J. Wong
2054ceeb9c83SDarrick J. Wong /* Check the offset. */
2055f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2056f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2057f9e03706SDarrick J. Wong goto out_error;
2058f9e03706SDarrick J. Wong }
2059f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2060f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2061f9e03706SDarrick J. Wong goto out_error;
2062f9e03706SDarrick J. Wong }
2063ceeb9c83SDarrick J. Wong
2064ceeb9c83SDarrick J. Wong if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2065ceeb9c83SDarrick J. Wong /* Exact match, simply remove the record from rmap tree. */
2066ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2067ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
2068ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags);
2069ceeb9c83SDarrick J. Wong if (error)
2070ceeb9c83SDarrick J. Wong goto out_error;
2071ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock == bno) {
2072ceeb9c83SDarrick J. Wong /*
2073ceeb9c83SDarrick J. Wong * Overlap left hand side of extent: move the start, trim the
2074ceeb9c83SDarrick J. Wong * length and update the current record.
2075ceeb9c83SDarrick J. Wong *
2076ceeb9c83SDarrick J. Wong * ltbno ltlen
2077ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo|
2078ceeb9c83SDarrick J. Wong * Freeing: |fffffffff|
2079ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr|
2080ceeb9c83SDarrick J. Wong * bno len
2081ceeb9c83SDarrick J. Wong */
2082ceeb9c83SDarrick J. Wong
2083ceeb9c83SDarrick J. Wong /* Delete prev rmap. */
2084ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2085ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
2086ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags);
2087ceeb9c83SDarrick J. Wong if (error)
2088ceeb9c83SDarrick J. Wong goto out_error;
2089ceeb9c83SDarrick J. Wong
2090ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset. */
2091ceeb9c83SDarrick J. Wong ltrec.rm_startblock += len;
2092ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len;
2093ceeb9c83SDarrick J. Wong ltrec.rm_offset += len;
2094ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2095ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
2096ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags);
2097ceeb9c83SDarrick J. Wong if (error)
2098ceeb9c83SDarrick J. Wong goto out_error;
2099ceeb9c83SDarrick J. Wong } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2100ceeb9c83SDarrick J. Wong /*
2101ceeb9c83SDarrick J. Wong * Overlap right hand side of extent: trim the length and
2102ceeb9c83SDarrick J. Wong * update the current record.
2103ceeb9c83SDarrick J. Wong *
2104ceeb9c83SDarrick J. Wong * ltbno ltlen
2105ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo|
2106ceeb9c83SDarrick J. Wong * Freeing: |fffffffff|
2107ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrr|
2108ceeb9c83SDarrick J. Wong * bno len
2109ceeb9c83SDarrick J. Wong */
2110ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2111ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
2112ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i);
2113ceeb9c83SDarrick J. Wong if (error)
2114ceeb9c83SDarrick J. Wong goto out_error;
2115f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
2116f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2117f9e03706SDarrick J. Wong goto out_error;
2118f9e03706SDarrick J. Wong }
2119ceeb9c83SDarrick J. Wong ltrec.rm_blockcount -= len;
2120ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
2121ceeb9c83SDarrick J. Wong if (error)
2122ceeb9c83SDarrick J. Wong goto out_error;
2123ceeb9c83SDarrick J. Wong } else {
2124ceeb9c83SDarrick J. Wong /*
2125ceeb9c83SDarrick J. Wong * Overlap middle of extent: trim the length of the existing
2126ceeb9c83SDarrick J. Wong * record to the length of the new left-extent size, increment
2127ceeb9c83SDarrick J. Wong * the insertion position so we can insert a new record
2128ceeb9c83SDarrick J. Wong * containing the remaining right-extent space.
2129ceeb9c83SDarrick J. Wong *
2130ceeb9c83SDarrick J. Wong * ltbno ltlen
2131ceeb9c83SDarrick J. Wong * Orig: |oooooooooooooooooooo|
2132ceeb9c83SDarrick J. Wong * Freeing: |fffffffff|
2133ceeb9c83SDarrick J. Wong * Result: |rrrrr| |rrrr|
2134ceeb9c83SDarrick J. Wong * bno len
2135ceeb9c83SDarrick J. Wong */
2136ceeb9c83SDarrick J. Wong xfs_extlen_t orig_len = ltrec.rm_blockcount;
2137ceeb9c83SDarrick J. Wong
2138ceeb9c83SDarrick J. Wong /* Shrink the left side of the rmap */
2139ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2140ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
2141ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i);
2142ceeb9c83SDarrick J. Wong if (error)
2143ceeb9c83SDarrick J. Wong goto out_error;
2144f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
2145f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2146f9e03706SDarrick J. Wong goto out_error;
2147f9e03706SDarrick J. Wong }
2148ceeb9c83SDarrick J. Wong ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2149ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
2150ceeb9c83SDarrick J. Wong if (error)
2151ceeb9c83SDarrick J. Wong goto out_error;
2152ceeb9c83SDarrick J. Wong
2153ceeb9c83SDarrick J. Wong /* Add an rmap at the new offset */
2154ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno + len,
2155ceeb9c83SDarrick J. Wong orig_len - len - ltrec.rm_blockcount,
2156ceeb9c83SDarrick J. Wong ltrec.rm_owner, offset + len,
2157ceeb9c83SDarrick J. Wong ltrec.rm_flags);
2158ceeb9c83SDarrick J. Wong if (error)
2159ceeb9c83SDarrick J. Wong goto out_error;
2160ceeb9c83SDarrick J. Wong }
2161ceeb9c83SDarrick J. Wong
216250f02fe3SDave Chinner trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2163ceeb9c83SDarrick J. Wong unwritten, oinfo);
2164ceeb9c83SDarrick J. Wong out_error:
2165ceeb9c83SDarrick J. Wong if (error)
2166ceeb9c83SDarrick J. Wong trace_xfs_rmap_unmap_error(cur->bc_mp,
216750f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2168ceeb9c83SDarrick J. Wong return error;
2169ceeb9c83SDarrick J. Wong }
2170ceeb9c83SDarrick J. Wong
2171ceeb9c83SDarrick J. Wong /*
2172ceeb9c83SDarrick J. Wong * Find an extent in the rmap btree and map it. For rmap extent types that
2173ceeb9c83SDarrick J. Wong * can overlap (data fork rmaps on reflink filesystems) we must be careful
2174ceeb9c83SDarrick J. Wong * that the prev/next records in the btree might belong to another owner.
2175ceeb9c83SDarrick J. Wong * Therefore we must use delete+insert to alter any of the key fields.
2176ceeb9c83SDarrick J. Wong *
2177ceeb9c83SDarrick J. Wong * For every other situation there can only be one owner for a given extent,
2178ceeb9c83SDarrick J. Wong * so we can call the regular _alloc function.
2179ceeb9c83SDarrick J. Wong */
2180ceeb9c83SDarrick 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)2181ceeb9c83SDarrick J. Wong xfs_rmap_map_shared(
2182ceeb9c83SDarrick J. Wong struct xfs_btree_cur *cur,
2183ceeb9c83SDarrick J. Wong xfs_agblock_t bno,
2184ceeb9c83SDarrick J. Wong xfs_extlen_t len,
2185ceeb9c83SDarrick J. Wong bool unwritten,
218666e3237eSDarrick J. Wong const struct xfs_owner_info *oinfo)
2187ceeb9c83SDarrick J. Wong {
2188ceeb9c83SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp;
2189ceeb9c83SDarrick J. Wong struct xfs_rmap_irec ltrec;
2190ceeb9c83SDarrick J. Wong struct xfs_rmap_irec gtrec;
2191ceeb9c83SDarrick J. Wong int have_gt;
2192ceeb9c83SDarrick J. Wong int have_lt;
2193ceeb9c83SDarrick J. Wong int error = 0;
2194ceeb9c83SDarrick J. Wong int i;
2195ceeb9c83SDarrick J. Wong uint64_t owner;
2196ceeb9c83SDarrick J. Wong uint64_t offset;
2197ceeb9c83SDarrick J. Wong unsigned int flags = 0;
2198ceeb9c83SDarrick J. Wong
2199ceeb9c83SDarrick J. Wong xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2200ceeb9c83SDarrick J. Wong if (unwritten)
2201ceeb9c83SDarrick J. Wong flags |= XFS_RMAP_UNWRITTEN;
220250f02fe3SDave Chinner trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2203ceeb9c83SDarrick J. Wong unwritten, oinfo);
2204ceeb9c83SDarrick J. Wong
2205ceeb9c83SDarrick J. Wong /* Is there a left record that abuts our range? */
2206ceeb9c83SDarrick J. Wong error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2207ceeb9c83SDarrick J. Wong <rec, &have_lt);
2208ceeb9c83SDarrick J. Wong if (error)
2209ceeb9c83SDarrick J. Wong goto out_error;
2210ceeb9c83SDarrick J. Wong if (have_lt &&
2211ceeb9c83SDarrick J. Wong !xfs_rmap_is_mergeable(<rec, owner, flags))
2212ceeb9c83SDarrick J. Wong have_lt = 0;
2213ceeb9c83SDarrick J. Wong
2214ceeb9c83SDarrick J. Wong /* Is there a right record that abuts our range? */
2215ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2216ceeb9c83SDarrick J. Wong flags, &have_gt);
2217ceeb9c83SDarrick J. Wong if (error)
2218ceeb9c83SDarrick J. Wong goto out_error;
2219ceeb9c83SDarrick J. Wong if (have_gt) {
2220ceeb9c83SDarrick J. Wong error = xfs_rmap_get_rec(cur, >rec, &have_gt);
2221ceeb9c83SDarrick J. Wong if (error)
2222ceeb9c83SDarrick J. Wong goto out_error;
2223f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2224f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2225f9e03706SDarrick J. Wong goto out_error;
2226f9e03706SDarrick J. Wong }
2227ceeb9c83SDarrick J. Wong trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
222850f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2229ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner,
2230ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags);
2231ceeb9c83SDarrick J. Wong
2232ceeb9c83SDarrick J. Wong if (!xfs_rmap_is_mergeable(>rec, owner, flags))
2233ceeb9c83SDarrick J. Wong have_gt = 0;
2234ceeb9c83SDarrick J. Wong }
2235ceeb9c83SDarrick J. Wong
2236ceeb9c83SDarrick J. Wong if (have_lt &&
2237ceeb9c83SDarrick J. Wong ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2238ceeb9c83SDarrick J. Wong ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2239ceeb9c83SDarrick J. Wong /*
2240ceeb9c83SDarrick J. Wong * Left edge contiguous, merge into left record.
2241ceeb9c83SDarrick J. Wong *
2242ceeb9c83SDarrick J. Wong * ltbno ltlen
2243ceeb9c83SDarrick J. Wong * orig: |ooooooooo|
2244ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa|
2245ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrr|
2246ceeb9c83SDarrick J. Wong * bno len
2247ceeb9c83SDarrick J. Wong */
2248ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += len;
2249ceeb9c83SDarrick J. Wong if (have_gt &&
2250ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock &&
2251ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) {
2252ceeb9c83SDarrick J. Wong /*
2253ceeb9c83SDarrick J. Wong * Right edge also contiguous, delete right record
2254ceeb9c83SDarrick J. Wong * and merge into left record.
2255ceeb9c83SDarrick J. Wong *
2256ceeb9c83SDarrick J. Wong * ltbno ltlen gtbno gtlen
2257ceeb9c83SDarrick J. Wong * orig: |ooooooooo| |ooooooooo|
2258ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa|
2259ceeb9c83SDarrick J. Wong * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2260ceeb9c83SDarrick J. Wong */
2261ceeb9c83SDarrick J. Wong ltrec.rm_blockcount += gtrec.rm_blockcount;
2262ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2263ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner,
2264ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags);
2265ceeb9c83SDarrick J. Wong if (error)
2266ceeb9c83SDarrick J. Wong goto out_error;
2267ceeb9c83SDarrick J. Wong }
2268ceeb9c83SDarrick J. Wong
2269ceeb9c83SDarrick J. Wong /* Point the cursor back to the left record and update. */
2270ceeb9c83SDarrick J. Wong error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2271ceeb9c83SDarrick J. Wong ltrec.rm_blockcount, ltrec.rm_owner,
2272ceeb9c83SDarrick J. Wong ltrec.rm_offset, ltrec.rm_flags, &i);
2273ceeb9c83SDarrick J. Wong if (error)
2274ceeb9c83SDarrick J. Wong goto out_error;
2275f9e03706SDarrick J. Wong if (XFS_IS_CORRUPT(mp, i != 1)) {
2276f9e03706SDarrick J. Wong error = -EFSCORRUPTED;
2277f9e03706SDarrick J. Wong goto out_error;
2278f9e03706SDarrick J. Wong }
2279ceeb9c83SDarrick J. Wong
2280ceeb9c83SDarrick J. Wong error = xfs_rmap_update(cur, <rec);
2281ceeb9c83SDarrick J. Wong if (error)
2282ceeb9c83SDarrick J. Wong goto out_error;
2283ceeb9c83SDarrick J. Wong } else if (have_gt &&
2284ceeb9c83SDarrick J. Wong bno + len == gtrec.rm_startblock &&
2285ceeb9c83SDarrick J. Wong offset + len == gtrec.rm_offset) {
2286ceeb9c83SDarrick J. Wong /*
2287ceeb9c83SDarrick J. Wong * Right edge contiguous, merge into right record.
2288ceeb9c83SDarrick J. Wong *
2289ceeb9c83SDarrick J. Wong * gtbno gtlen
2290ceeb9c83SDarrick J. Wong * Orig: |ooooooooo|
2291ceeb9c83SDarrick J. Wong * adding: |aaaaaaaaa|
2292ceeb9c83SDarrick J. Wong * Result: |rrrrrrrrrrrrrrrrrrr|
2293ceeb9c83SDarrick J. Wong * bno len
2294ceeb9c83SDarrick J. Wong */
2295ceeb9c83SDarrick J. Wong /* Delete the old record. */
2296ceeb9c83SDarrick J. Wong error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2297ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner,
2298ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags);
2299ceeb9c83SDarrick J. Wong if (error)
2300ceeb9c83SDarrick J. Wong goto out_error;
2301ceeb9c83SDarrick J. Wong
2302ceeb9c83SDarrick J. Wong /* Move the start and re-add it. */
2303ceeb9c83SDarrick J. Wong gtrec.rm_startblock = bno;
2304ceeb9c83SDarrick J. Wong gtrec.rm_blockcount += len;
2305ceeb9c83SDarrick J. Wong gtrec.rm_offset = offset;
2306ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2307ceeb9c83SDarrick J. Wong gtrec.rm_blockcount, gtrec.rm_owner,
2308ceeb9c83SDarrick J. Wong gtrec.rm_offset, gtrec.rm_flags);
2309ceeb9c83SDarrick J. Wong if (error)
2310ceeb9c83SDarrick J. Wong goto out_error;
2311ceeb9c83SDarrick J. Wong } else {
2312ceeb9c83SDarrick J. Wong /*
2313ceeb9c83SDarrick J. Wong * No contiguous edge with identical owner, insert
2314ceeb9c83SDarrick J. Wong * new record at current cursor position.
2315ceeb9c83SDarrick J. Wong */
2316ceeb9c83SDarrick J. Wong error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2317ceeb9c83SDarrick J. Wong if (error)
2318ceeb9c83SDarrick J. Wong goto out_error;
2319ceeb9c83SDarrick J. Wong }
2320ceeb9c83SDarrick J. Wong
232150f02fe3SDave Chinner trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2322ceeb9c83SDarrick J. Wong unwritten, oinfo);
2323ceeb9c83SDarrick J. Wong out_error:
2324ceeb9c83SDarrick J. Wong if (error)
2325ceeb9c83SDarrick J. Wong trace_xfs_rmap_map_error(cur->bc_mp,
232650f02fe3SDave Chinner cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2327ceeb9c83SDarrick J. Wong return error;
2328ceeb9c83SDarrick J. Wong }
2329ceeb9c83SDarrick J. Wong
23304d4f86b4SDarrick J. Wong /* Insert a raw rmap into the rmapbt. */
23314d4f86b4SDarrick J. Wong int
xfs_rmap_map_raw(struct xfs_btree_cur * cur,struct xfs_rmap_irec * rmap)23324d4f86b4SDarrick J. Wong xfs_rmap_map_raw(
23334d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur,
23344d4f86b4SDarrick J. Wong struct xfs_rmap_irec *rmap)
23354d4f86b4SDarrick J. Wong {
23364d4f86b4SDarrick J. Wong struct xfs_owner_info oinfo;
23374d4f86b4SDarrick J. Wong
23384d4f86b4SDarrick J. Wong oinfo.oi_owner = rmap->rm_owner;
23394d4f86b4SDarrick J. Wong oinfo.oi_offset = rmap->rm_offset;
23404d4f86b4SDarrick J. Wong oinfo.oi_flags = 0;
23414d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
23424d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
23434d4f86b4SDarrick J. Wong if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
23444d4f86b4SDarrick J. Wong oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
23454d4f86b4SDarrick J. Wong
23464d4f86b4SDarrick J. Wong if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
23474d4f86b4SDarrick J. Wong return xfs_rmap_map(cur, rmap->rm_startblock,
23484d4f86b4SDarrick J. Wong rmap->rm_blockcount,
23494d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN,
23504d4f86b4SDarrick J. Wong &oinfo);
23514d4f86b4SDarrick J. Wong
23524d4f86b4SDarrick J. Wong return xfs_rmap_map_shared(cur, rmap->rm_startblock,
23534d4f86b4SDarrick J. Wong rmap->rm_blockcount,
23544d4f86b4SDarrick J. Wong rmap->rm_flags & XFS_RMAP_UNWRITTEN,
23554d4f86b4SDarrick J. Wong &oinfo);
23564d4f86b4SDarrick J. Wong }
23574d4f86b4SDarrick J. Wong
2358c543838aSDarrick J. Wong struct xfs_rmap_query_range_info {
2359c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn;
2360c543838aSDarrick J. Wong void *priv;
2361c543838aSDarrick J. Wong };
2362c543838aSDarrick J. Wong
2363c543838aSDarrick J. Wong /* Format btree record and pass to our callback. */
2364c543838aSDarrick J. Wong STATIC int
xfs_rmap_query_range_helper(struct xfs_btree_cur * cur,const union xfs_btree_rec * rec,void * priv)2365c543838aSDarrick J. Wong xfs_rmap_query_range_helper(
2366c543838aSDarrick J. Wong struct xfs_btree_cur *cur,
2367159eb69dSDarrick J. Wong const union xfs_btree_rec *rec,
2368c543838aSDarrick J. Wong void *priv)
2369c543838aSDarrick J. Wong {
2370c543838aSDarrick J. Wong struct xfs_rmap_query_range_info *query = priv;
2371c543838aSDarrick J. Wong struct xfs_rmap_irec irec;
2372ee12eaaaSDarrick J. Wong xfs_failaddr_t fa;
2373c543838aSDarrick J. Wong
2374ee12eaaaSDarrick J. Wong fa = xfs_rmap_btrec_to_irec(rec, &irec);
2375ee12eaaaSDarrick J. Wong if (!fa)
2376ee12eaaaSDarrick J. Wong fa = xfs_rmap_check_irec(cur, &irec);
2377ee12eaaaSDarrick J. Wong if (fa)
2378ee12eaaaSDarrick J. Wong return xfs_rmap_complain_bad_rec(cur, fa, &irec);
237939ab26d5SDarrick J. Wong
2380c543838aSDarrick J. Wong return query->fn(cur, &irec, query->priv);
2381c543838aSDarrick J. Wong }
2382c543838aSDarrick J. Wong
2383c543838aSDarrick J. Wong /* Find all rmaps between two keys. */
2384c543838aSDarrick 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)2385c543838aSDarrick J. Wong xfs_rmap_query_range(
2386c543838aSDarrick J. Wong struct xfs_btree_cur *cur,
238704dcb474SDarrick J. Wong const struct xfs_rmap_irec *low_rec,
238804dcb474SDarrick J. Wong const struct xfs_rmap_irec *high_rec,
2389c543838aSDarrick J. Wong xfs_rmap_query_range_fn fn,
2390c543838aSDarrick J. Wong void *priv)
2391c543838aSDarrick J. Wong {
2392c543838aSDarrick J. Wong union xfs_btree_irec low_brec = { .r = *low_rec };
2393c543838aSDarrick J. Wong union xfs_btree_irec high_brec = { .r = *high_rec };
2394c543838aSDarrick J. Wong struct xfs_rmap_query_range_info query = { .priv = priv, .fn = fn };
2395c543838aSDarrick J. Wong
2396c543838aSDarrick J. Wong return xfs_btree_query_range(cur, &low_brec, &high_brec,
2397c543838aSDarrick J. Wong xfs_rmap_query_range_helper, &query);
2398c543838aSDarrick J. Wong }
2399c543838aSDarrick J. Wong
2400c543838aSDarrick J. Wong /* Find all rmaps. */
2401c543838aSDarrick J. Wong int
xfs_rmap_query_all(struct xfs_btree_cur * cur,xfs_rmap_query_range_fn fn,void * priv)2402e9a2599aSDarrick J. Wong xfs_rmap_query_all(
2403e9a2599aSDarrick J. Wong struct xfs_btree_cur *cur,
2404e9a2599aSDarrick J. Wong xfs_rmap_query_range_fn fn,
2405e9a2599aSDarrick J. Wong void *priv)
2406e9a2599aSDarrick J. Wong {
2407e9a2599aSDarrick J. Wong struct xfs_rmap_query_range_info query;
2408e9a2599aSDarrick J. Wong
2409e9a2599aSDarrick J. Wong query.priv = priv;
2410e9a2599aSDarrick J. Wong query.fn = fn;
2411e9a2599aSDarrick J. Wong return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2412e9a2599aSDarrick J. Wong }
2413e9a2599aSDarrick J. Wong
2414e9a2599aSDarrick J. Wong /* Clean up after calling xfs_rmap_finish_one. */
2415e9a2599aSDarrick J. Wong void
xfs_rmap_finish_one_cleanup(struct xfs_trans * tp,struct xfs_btree_cur * rcur,int error)2416c543838aSDarrick J. Wong xfs_rmap_finish_one_cleanup(
24179c194644SDarrick J. Wong struct xfs_trans *tp,
24189c194644SDarrick J. Wong struct xfs_btree_cur *rcur,
24199c194644SDarrick J. Wong int error)
24209c194644SDarrick J. Wong {
24219c194644SDarrick J. Wong struct xfs_buf *agbp;
24229c194644SDarrick J. Wong
24239c194644SDarrick J. Wong if (rcur == NULL)
24249c194644SDarrick J. Wong return;
24259c194644SDarrick J. Wong agbp = rcur->bc_ag.agbp;
24269c194644SDarrick J. Wong xfs_btree_del_cursor(rcur, error);
24279c194644SDarrick J. Wong if (error)
24289c194644SDarrick J. Wong xfs_trans_brelse(tp, agbp);
2429576af732SDave Chinner }
24300b04b6b8SDarrick J. Wong
24319c194644SDarrick J. Wong /*
24329c194644SDarrick J. Wong * Process one of the deferred rmap operations. We pass back the
24339c194644SDarrick J. Wong * btree cursor to maintain our lock on the rmapbt between calls.
24349c194644SDarrick J. Wong * This saves time and eliminates a buffer deadlock between the
24359c194644SDarrick J. Wong * superblock and the AGF because we'll always grab them in the same
24369c194644SDarrick J. Wong * order.
24379c194644SDarrick J. Wong */
24389c194644SDarrick J. Wong int
xfs_rmap_finish_one(struct xfs_trans * tp,struct xfs_rmap_intent * ri,struct xfs_btree_cur ** pcur)24399c194644SDarrick J. Wong xfs_rmap_finish_one(
24409c194644SDarrick J. Wong struct xfs_trans *tp,
24419c194644SDarrick J. Wong struct xfs_rmap_intent *ri,
24429c194644SDarrick J. Wong struct xfs_btree_cur **pcur)
24439c194644SDarrick J. Wong {
24449c194644SDarrick J. Wong struct xfs_mount *mp = tp->t_mountp;
24451534328bSDarrick J. Wong struct xfs_btree_cur *rcur;
24469c194644SDarrick J. Wong struct xfs_buf *agbp = NULL;
24479c194644SDarrick J. Wong int error = 0;
24489c194644SDarrick J. Wong struct xfs_owner_info oinfo;
24499c194644SDarrick J. Wong xfs_agblock_t bno;
24509c194644SDarrick J. Wong bool unwritten;
24519c194644SDarrick J. Wong
24529c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock);
24539c194644SDarrick J. Wong
24549c194644SDarrick J. Wong trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno,
24559c194644SDarrick J. Wong ri->ri_owner, ri->ri_whichfork,
24561534328bSDarrick J. Wong ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
24579c194644SDarrick J. Wong ri->ri_bmap.br_state);
2458c13418e8SDarrick J. Wong
24591534328bSDarrick J. Wong if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
24601534328bSDarrick J. Wong return -EIO;
24611534328bSDarrick J. Wong
24629c194644SDarrick J. Wong /*
2463c13418e8SDarrick J. Wong * If we haven't gotten a cursor or the cursor AG doesn't match
2464c13418e8SDarrick J. Wong * the startblock, get one now.
24659c194644SDarrick J. Wong */
24669c194644SDarrick J. Wong rcur = *pcur;
24679c194644SDarrick J. Wong if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
24689c194644SDarrick J. Wong xfs_rmap_finish_one_cleanup(tp, rcur, 0);
24699c194644SDarrick J. Wong rcur = NULL;
24709c194644SDarrick J. Wong *pcur = NULL;
2471c13418e8SDarrick J. Wong }
24729c194644SDarrick J. Wong if (rcur == NULL) {
24739c194644SDarrick J. Wong /*
24749c194644SDarrick J. Wong * Refresh the freelist before we start changing the
24759c194644SDarrick J. Wong * rmapbt, because a shape change could cause us to
24769c194644SDarrick J. Wong * allocate blocks.
24779c194644SDarrick J. Wong */
24789c194644SDarrick J. Wong error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
24799c194644SDarrick J. Wong if (error)
24809c194644SDarrick J. Wong return error;
24819c194644SDarrick J. Wong if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
2482c13418e8SDarrick J. Wong return -EFSCORRUPTED;
24839c194644SDarrick J. Wong
2484c13418e8SDarrick J. Wong rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
2485c13418e8SDarrick J. Wong }
2486c13418e8SDarrick J. Wong *pcur = rcur;
24879c194644SDarrick J. Wong
2488c13418e8SDarrick J. Wong xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
24899c194644SDarrick J. Wong ri->ri_bmap.br_startoff);
24909c194644SDarrick J. Wong unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
24919c194644SDarrick J. Wong bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
24921534328bSDarrick J. Wong
24931534328bSDarrick J. Wong switch (ri->ri_type) {
24941534328bSDarrick J. Wong case XFS_RMAP_ALLOC:
24951534328bSDarrick J. Wong case XFS_RMAP_MAP:
24969c194644SDarrick J. Wong error = xfs_rmap_map(rcur, bno, ri->ri_bmap.br_blockcount,
24971534328bSDarrick J. Wong unwritten, &oinfo);
24989c194644SDarrick J. Wong break;
24999c194644SDarrick J. Wong case XFS_RMAP_MAP_SHARED:
25001534328bSDarrick J. Wong error = xfs_rmap_map_shared(rcur, bno,
25011534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, unwritten, &oinfo);
25029c194644SDarrick J. Wong break;
2503ceeb9c83SDarrick J. Wong case XFS_RMAP_FREE:
25041534328bSDarrick J. Wong case XFS_RMAP_UNMAP:
25051534328bSDarrick J. Wong error = xfs_rmap_unmap(rcur, bno, ri->ri_bmap.br_blockcount,
2506ceeb9c83SDarrick J. Wong unwritten, &oinfo);
25079c194644SDarrick J. Wong break;
25089c194644SDarrick J. Wong case XFS_RMAP_UNMAP_SHARED:
25091534328bSDarrick J. Wong error = xfs_rmap_unmap_shared(rcur, bno,
25101534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, unwritten, &oinfo);
25119c194644SDarrick J. Wong break;
2512ceeb9c83SDarrick J. Wong case XFS_RMAP_CONVERT:
25131534328bSDarrick J. Wong error = xfs_rmap_convert(rcur, bno, ri->ri_bmap.br_blockcount,
25141534328bSDarrick J. Wong !unwritten, &oinfo);
2515ceeb9c83SDarrick J. Wong break;
25169c194644SDarrick J. Wong case XFS_RMAP_CONVERT_SHARED:
25171534328bSDarrick J. Wong error = xfs_rmap_convert_shared(rcur, bno,
25181534328bSDarrick J. Wong ri->ri_bmap.br_blockcount, !unwritten, &oinfo);
25199c194644SDarrick J. Wong break;
25203f165b33SDarrick J. Wong default:
25211534328bSDarrick J. Wong ASSERT(0);
25221534328bSDarrick J. Wong error = -EFSCORRUPTED;
25233f165b33SDarrick J. Wong }
25249c194644SDarrick J. Wong
25259c194644SDarrick J. Wong return error;
25269c194644SDarrick J. Wong }
25279c194644SDarrick J. Wong
2528c13418e8SDarrick J. Wong /*
25299c194644SDarrick J. Wong * Don't defer an rmap if we aren't an rmap filesystem.
25309c194644SDarrick J. Wong */
25319c194644SDarrick J. Wong static bool
xfs_rmap_update_is_needed(struct xfs_mount * mp,int whichfork)25329c194644SDarrick J. Wong xfs_rmap_update_is_needed(
25339c194644SDarrick J. Wong struct xfs_mount *mp,
25349c194644SDarrick J. Wong int whichfork)
25359c194644SDarrick J. Wong {
25369c194644SDarrick J. Wong return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
25373993baebSDarrick J. Wong }
25383993baebSDarrick J. Wong
25399c194644SDarrick J. Wong /*
254038c26bfdSDave Chinner * Record a rmap intent; the list is kept sorted first by AG and then by
25419c194644SDarrick J. Wong * increasing age.
25429c194644SDarrick J. Wong */
25439c194644SDarrick 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)25449c194644SDarrick J. Wong __xfs_rmap_add(
25459c194644SDarrick J. Wong struct xfs_trans *tp,
25469c194644SDarrick J. Wong enum xfs_rmap_intent_type type,
2547bc46ac64SDarrick J. Wong uint64_t owner,
25489c194644SDarrick J. Wong int whichfork,
25490f37d178SBrian Foster struct xfs_bmbt_irec *bmap)
25509c194644SDarrick J. Wong {
2551c8ce540dSDarrick J. Wong struct xfs_rmap_intent *ri;
25529c194644SDarrick J. Wong
25539c194644SDarrick J. Wong trace_xfs_rmap_defer(tp->t_mountp,
25549c194644SDarrick J. Wong XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
25559c194644SDarrick J. Wong type,
25569c194644SDarrick J. Wong XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
25570f37d178SBrian Foster owner, whichfork,
25580f37d178SBrian Foster bmap->br_startoff,
25599c194644SDarrick J. Wong bmap->br_blockcount,
25600f37d178SBrian Foster bmap->br_state);
25619c194644SDarrick J. Wong
25629c194644SDarrick J. Wong ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
25639c194644SDarrick J. Wong INIT_LIST_HEAD(&ri->ri_list);
25649c194644SDarrick J. Wong ri->ri_type = type;
25659c194644SDarrick J. Wong ri->ri_owner = owner;
2566f3c799c2SDarrick J. Wong ri->ri_whichfork = whichfork;
25679c194644SDarrick J. Wong ri->ri_bmap = *bmap;
25689c194644SDarrick J. Wong
25699c194644SDarrick J. Wong xfs_rmap_update_get_group(tp->t_mountp, ri);
25709c194644SDarrick J. Wong xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
25719c194644SDarrick J. Wong }
25729c194644SDarrick J. Wong
2573c13418e8SDarrick J. Wong /* Map an extent into a file. */
25740f37d178SBrian Foster void
xfs_rmap_map_extent(struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)25759c194644SDarrick J. Wong xfs_rmap_map_extent(
25769c194644SDarrick J. Wong struct xfs_trans *tp,
25779c194644SDarrick J. Wong struct xfs_inode *ip,
2578bc46ac64SDarrick J. Wong int whichfork,
25799c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV)
25800f37d178SBrian Foster {
25819c194644SDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
25829c194644SDarrick J. Wong
25839c194644SDarrick J. Wong if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
25849c194644SDarrick J. Wong return;
2585d7884e6eSDarrick J. Wong
2586d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
25870f37d178SBrian Foster type = XFS_RMAP_MAP_SHARED;
2588bc46ac64SDarrick J. Wong
25899c194644SDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2590d7884e6eSDarrick J. Wong }
2591d7884e6eSDarrick J. Wong
2592d7884e6eSDarrick J. Wong /* Unmap an extent out of a file. */
2593d7884e6eSDarrick J. Wong void
xfs_rmap_unmap_extent(struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)25949c194644SDarrick J. Wong xfs_rmap_unmap_extent(
25959c194644SDarrick J. Wong struct xfs_trans *tp,
25969c194644SDarrick J. Wong struct xfs_inode *ip,
2597bc46ac64SDarrick J. Wong int whichfork,
25989c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV)
25990f37d178SBrian Foster {
26009c194644SDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
26019c194644SDarrick J. Wong
26029c194644SDarrick J. Wong if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
26039c194644SDarrick J. Wong return;
2604d7884e6eSDarrick J. Wong
2605d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
26060f37d178SBrian Foster type = XFS_RMAP_UNMAP_SHARED;
2607bc46ac64SDarrick J. Wong
26089c194644SDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2609d7884e6eSDarrick J. Wong }
2610d7884e6eSDarrick J. Wong
2611d7884e6eSDarrick J. Wong /*
2612d7884e6eSDarrick J. Wong * Convert a data fork extent from unwritten to real or vice versa.
26139c194644SDarrick J. Wong *
26149c194644SDarrick J. Wong * Note that tp can be NULL here as no transaction is used for COW fork
26150f37d178SBrian Foster * unwritten conversion.
26160f37d178SBrian Foster */
26170f37d178SBrian Foster void
xfs_rmap_convert_extent(struct xfs_mount * mp,struct xfs_trans * tp,struct xfs_inode * ip,int whichfork,struct xfs_bmbt_irec * PREV)26180f37d178SBrian Foster xfs_rmap_convert_extent(
26190f37d178SBrian Foster struct xfs_mount *mp,
26200f37d178SBrian Foster struct xfs_trans *tp,
2621bc46ac64SDarrick J. Wong struct xfs_inode *ip,
26229c194644SDarrick J. Wong int whichfork,
26239c194644SDarrick J. Wong struct xfs_bmbt_irec *PREV)
26240f37d178SBrian Foster {
26259c194644SDarrick J. Wong enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
26269c194644SDarrick J. Wong
26279c194644SDarrick J. Wong if (!xfs_rmap_update_is_needed(mp, whichfork))
26289c194644SDarrick J. Wong return;
2629d7884e6eSDarrick J. Wong
2630d7884e6eSDarrick J. Wong if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
26313993baebSDarrick J. Wong type = XFS_RMAP_CONVERT_SHARED;
2632bc46ac64SDarrick J. Wong
26339c194644SDarrick J. Wong __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2634d7884e6eSDarrick J. Wong }
2635d7884e6eSDarrick J. Wong
2636d7884e6eSDarrick J. Wong /* Schedule the creation of an rmap for non-file data. */
2637d7884e6eSDarrick 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)26389c194644SDarrick J. Wong xfs_rmap_alloc_extent(
26399c194644SDarrick J. Wong struct xfs_trans *tp,
26409c194644SDarrick J. Wong xfs_agnumber_t agno,
2641bc46ac64SDarrick J. Wong xfs_agblock_t bno,
26429c194644SDarrick J. Wong xfs_extlen_t len,
26430f37d178SBrian Foster uint64_t owner)
26449c194644SDarrick J. Wong {
26459c194644SDarrick J. Wong struct xfs_bmbt_irec bmap;
26469c194644SDarrick J. Wong
2647c8ce540dSDarrick J. Wong if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
26489c194644SDarrick J. Wong return;
26499c194644SDarrick J. Wong
26509c194644SDarrick J. Wong bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
26510f37d178SBrian Foster bmap.br_blockcount = len;
2652bc46ac64SDarrick J. Wong bmap.br_startoff = 0;
26539c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM;
26540f37d178SBrian Foster
26559c194644SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
26569c194644SDarrick J. Wong }
26579c194644SDarrick J. Wong
26589c194644SDarrick J. Wong /* Schedule the deletion of an rmap for non-file data. */
2659bc46ac64SDarrick 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)26609c194644SDarrick J. Wong xfs_rmap_free_extent(
26619c194644SDarrick J. Wong struct xfs_trans *tp,
26629c194644SDarrick J. Wong xfs_agnumber_t agno,
2663bc46ac64SDarrick J. Wong xfs_agblock_t bno,
26649c194644SDarrick J. Wong xfs_extlen_t len,
26650f37d178SBrian Foster uint64_t owner)
26669c194644SDarrick J. Wong {
26679c194644SDarrick J. Wong struct xfs_bmbt_irec bmap;
26689c194644SDarrick J. Wong
2669c8ce540dSDarrick J. Wong if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
26709c194644SDarrick J. Wong return;
26719c194644SDarrick J. Wong
26729c194644SDarrick J. Wong bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
26730f37d178SBrian Foster bmap.br_blockcount = len;
2674bc46ac64SDarrick J. Wong bmap.br_startoff = 0;
26759c194644SDarrick J. Wong bmap.br_state = XFS_EXT_NORM;
26760f37d178SBrian Foster
26779c194644SDarrick J. Wong __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
26789c194644SDarrick J. Wong }
26799c194644SDarrick J. Wong
26809c194644SDarrick J. Wong /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2681bc46ac64SDarrick J. Wong int
xfs_rmap_compare(const struct xfs_rmap_irec * a,const struct xfs_rmap_irec * b)26829c194644SDarrick J. Wong xfs_rmap_compare(
2683e89c0413SDarrick J. Wong const struct xfs_rmap_irec *a,
2684e89c0413SDarrick J. Wong const struct xfs_rmap_irec *b)
2685e89c0413SDarrick J. Wong {
2686e89c0413SDarrick J. Wong __u64 oa;
2687e89c0413SDarrick J. Wong __u64 ob;
2688e89c0413SDarrick J. Wong
2689e89c0413SDarrick J. Wong oa = xfs_rmap_irec_offset_pack(a);
2690e89c0413SDarrick J. Wong ob = xfs_rmap_irec_offset_pack(b);
2691e89c0413SDarrick J. Wong
2692e89c0413SDarrick J. Wong if (a->rm_startblock < b->rm_startblock)
2693e89c0413SDarrick J. Wong return -1;
2694e89c0413SDarrick J. Wong else if (a->rm_startblock > b->rm_startblock)
2695e89c0413SDarrick J. Wong return 1;
2696e89c0413SDarrick J. Wong else if (a->rm_owner < b->rm_owner)
2697e89c0413SDarrick J. Wong return -1;
2698e89c0413SDarrick J. Wong else if (a->rm_owner > b->rm_owner)
2699e89c0413SDarrick J. Wong return 1;
2700e89c0413SDarrick J. Wong else if (oa < ob)
2701e89c0413SDarrick J. Wong return -1;
2702e89c0413SDarrick J. Wong else if (oa > ob)
2703e89c0413SDarrick J. Wong return 1;
2704e89c0413SDarrick J. Wong else
2705e89c0413SDarrick J. Wong return 0;
2706e89c0413SDarrick J. Wong }
2707e89c0413SDarrick J. Wong
2708e89c0413SDarrick J. Wong /*
2709e89c0413SDarrick J. Wong * Scan the physical storage part of the keyspace of the reverse mapping index
2710e89c0413SDarrick J. Wong * and tell us if the area has no records, is fully mapped by records, or is
2711ed7c52d4SDarrick J. Wong * partially filled.
27126abc7aefSDarrick J. Wong */
27136abc7aefSDarrick J. Wong int
xfs_rmap_has_records(struct xfs_btree_cur * cur,xfs_agblock_t bno,xfs_extlen_t len,enum xbtree_recpacking * outcome)27146abc7aefSDarrick J. Wong xfs_rmap_has_records(
27156abc7aefSDarrick J. Wong struct xfs_btree_cur *cur,
27166abc7aefSDarrick J. Wong xfs_agblock_t bno,
2717ed7c52d4SDarrick J. Wong xfs_extlen_t len,
27186abc7aefSDarrick J. Wong enum xbtree_recpacking *outcome)
2719ed7c52d4SDarrick J. Wong {
2720ed7c52d4SDarrick J. Wong union xfs_btree_key mask = {
2721ed7c52d4SDarrick J. Wong .rmap.rm_startblock = cpu_to_be32(-1U),
27226abc7aefSDarrick J. Wong };
2723ed7c52d4SDarrick J. Wong union xfs_btree_irec low;
27244a200a09SDarrick J. Wong union xfs_btree_irec high;
27254a200a09SDarrick J. Wong
27264a200a09SDarrick J. Wong memset(&low, 0, sizeof(low));
2727ed7c52d4SDarrick J. Wong low.r.rm_startblock = bno;
2728ed7c52d4SDarrick J. Wong memset(&high, 0xFF, sizeof(high));
2729ed7c52d4SDarrick J. Wong high.r.rm_startblock = bno + len - 1;
2730ed7c52d4SDarrick J. Wong
2731ed7c52d4SDarrick J. Wong return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
2732ed7c52d4SDarrick J. Wong }
2733ed7c52d4SDarrick J. Wong
2734ed7c52d4SDarrick J. Wong struct xfs_rmap_ownercount {
27354a200a09SDarrick J. Wong /* Owner that we're looking for. */
2736ed7c52d4SDarrick J. Wong struct xfs_rmap_irec good;
2737ed7c52d4SDarrick J. Wong
2738*69115f77SDarrick J. Wong /* rmap search keys */
2739*69115f77SDarrick J. Wong struct xfs_rmap_irec low;
2740*69115f77SDarrick J. Wong struct xfs_rmap_irec high;
2741*69115f77SDarrick J. Wong
2742*69115f77SDarrick J. Wong struct xfs_rmap_matches *results;
2743*69115f77SDarrick J. Wong
2744*69115f77SDarrick J. Wong /* Stop early if we find a nonmatch? */
2745*69115f77SDarrick J. Wong bool stop_on_nonmatch;
2746*69115f77SDarrick J. Wong };
2747*69115f77SDarrick J. Wong
2748*69115f77SDarrick J. Wong /* Does this rmap represent space that can have multiple owners? */
2749*69115f77SDarrick J. Wong static inline bool
xfs_rmap_shareable(struct xfs_mount * mp,const struct xfs_rmap_irec * rmap)2750*69115f77SDarrick J. Wong xfs_rmap_shareable(
2751*69115f77SDarrick J. Wong struct xfs_mount *mp,
2752*69115f77SDarrick J. Wong const struct xfs_rmap_irec *rmap)
2753*69115f77SDarrick J. Wong {
2754*69115f77SDarrick J. Wong if (!xfs_has_reflink(mp))
2755*69115f77SDarrick J. Wong return false;
2756*69115f77SDarrick J. Wong if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2757*69115f77SDarrick J. Wong return false;
2758*69115f77SDarrick J. Wong if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
2759*69115f77SDarrick J. Wong XFS_RMAP_BMBT_BLOCK))
2760*69115f77SDarrick J. Wong return false;
2761*69115f77SDarrick J. Wong return true;
2762*69115f77SDarrick J. Wong }
2763*69115f77SDarrick J. Wong
2764*69115f77SDarrick 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)2765*69115f77SDarrick J. Wong xfs_rmap_ownercount_init(
2766*69115f77SDarrick J. Wong struct xfs_rmap_ownercount *roc,
2767*69115f77SDarrick J. Wong xfs_agblock_t bno,
2768*69115f77SDarrick J. Wong xfs_extlen_t len,
2769*69115f77SDarrick J. Wong const struct xfs_owner_info *oinfo,
2770*69115f77SDarrick J. Wong struct xfs_rmap_matches *results)
2771ed7c52d4SDarrick J. Wong {
2772ed7c52d4SDarrick J. Wong memset(roc, 0, sizeof(*roc));
277366e3237eSDarrick J. Wong roc->results = results;
2774*69115f77SDarrick J. Wong
2775ed7c52d4SDarrick J. Wong roc->low.rm_startblock = bno;
2776*69115f77SDarrick J. Wong memset(&roc->high, 0xFF, sizeof(roc->high));
2777*69115f77SDarrick J. Wong roc->high.rm_startblock = bno + len - 1;
2778ed7c52d4SDarrick J. Wong
2779*69115f77SDarrick J. Wong memset(results, 0, sizeof(*results));
2780*69115f77SDarrick J. Wong roc->good.rm_startblock = bno;
2781*69115f77SDarrick J. Wong roc->good.rm_blockcount = len;
2782ed7c52d4SDarrick J. Wong roc->good.rm_owner = oinfo->oi_owner;
2783*69115f77SDarrick J. Wong roc->good.rm_offset = oinfo->oi_offset;
2784*69115f77SDarrick J. Wong if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
2785*69115f77SDarrick J. Wong roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
2786*69115f77SDarrick J. Wong if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
2787*69115f77SDarrick J. Wong roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2788*69115f77SDarrick J. Wong }
2789*69115f77SDarrick J. Wong
2790*69115f77SDarrick J. Wong /* Figure out if this is a match for the owner. */
2791*69115f77SDarrick J. Wong STATIC int
xfs_rmap_count_owners_helper(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)2792ed7c52d4SDarrick J. Wong xfs_rmap_count_owners_helper(
2793ed7c52d4SDarrick J. Wong struct xfs_btree_cur *cur,
2794*69115f77SDarrick J. Wong const struct xfs_rmap_irec *rec,
27954d4f86b4SDarrick J. Wong void *priv)
2796*69115f77SDarrick J. Wong {
27974d4f86b4SDarrick J. Wong struct xfs_rmap_ownercount *roc = priv;
2798159eb69dSDarrick J. Wong struct xfs_rmap_irec check = *rec;
27994d4f86b4SDarrick J. Wong unsigned int keyflags;
28004d4f86b4SDarrick J. Wong bool filedata;
2801*69115f77SDarrick J. Wong int64_t delta;
2802*69115f77SDarrick J. Wong
2803*69115f77SDarrick J. Wong filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
2804*69115f77SDarrick J. Wong !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
2805*69115f77SDarrick J. Wong
28064d4f86b4SDarrick J. Wong /* Trim the part of check that comes before the comparison range. */
2807*69115f77SDarrick J. Wong delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
2808*69115f77SDarrick J. Wong if (delta > 0) {
2809*69115f77SDarrick J. Wong check.rm_startblock += delta;
2810*69115f77SDarrick J. Wong check.rm_blockcount -= delta;
2811*69115f77SDarrick J. Wong if (filedata)
2812*69115f77SDarrick J. Wong check.rm_offset += delta;
2813*69115f77SDarrick J. Wong }
2814*69115f77SDarrick J. Wong
2815*69115f77SDarrick J. Wong /* Trim the part of check that comes after the comparison range. */
2816*69115f77SDarrick J. Wong delta = (check.rm_startblock + check.rm_blockcount) -
2817*69115f77SDarrick J. Wong (roc->good.rm_startblock + roc->good.rm_blockcount);
2818*69115f77SDarrick J. Wong if (delta > 0)
2819*69115f77SDarrick J. Wong check.rm_blockcount -= delta;
2820*69115f77SDarrick J. Wong
2821*69115f77SDarrick J. Wong /* Don't care about unwritten status for establishing ownership. */
2822*69115f77SDarrick J. Wong keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
2823*69115f77SDarrick J. Wong
2824*69115f77SDarrick J. Wong if (check.rm_startblock == roc->good.rm_startblock &&
2825*69115f77SDarrick J. Wong check.rm_blockcount == roc->good.rm_blockcount &&
2826*69115f77SDarrick J. Wong check.rm_owner == roc->good.rm_owner &&
2827*69115f77SDarrick J. Wong check.rm_offset == roc->good.rm_offset &&
2828*69115f77SDarrick J. Wong keyflags == roc->good.rm_flags) {
2829*69115f77SDarrick J. Wong roc->results->matches++;
2830*69115f77SDarrick J. Wong } else {
2831*69115f77SDarrick J. Wong roc->results->non_owner_matches++;
2832*69115f77SDarrick J. Wong if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
2833*69115f77SDarrick J. Wong xfs_rmap_shareable(cur->bc_mp, &check))
2834*69115f77SDarrick J. Wong roc->results->bad_non_owner_matches++;
2835*69115f77SDarrick J. Wong }
2836*69115f77SDarrick J. Wong
2837*69115f77SDarrick J. Wong if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
2838*69115f77SDarrick J. Wong return -ECANCELED;
2839*69115f77SDarrick J. Wong
2840*69115f77SDarrick J. Wong return 0;
2841*69115f77SDarrick J. Wong }
2842e7ee96dfSDarrick J. Wong
2843*69115f77SDarrick J. Wong /* Count the number of owners and non-owners of this range of blocks. */
2844*69115f77SDarrick 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)2845*69115f77SDarrick J. Wong xfs_rmap_count_owners(
2846*69115f77SDarrick J. Wong struct xfs_btree_cur *cur,
2847*69115f77SDarrick J. Wong xfs_agblock_t bno,
2848*69115f77SDarrick J. Wong xfs_extlen_t len,
2849*69115f77SDarrick J. Wong const struct xfs_owner_info *oinfo,
2850*69115f77SDarrick J. Wong struct xfs_rmap_matches *results)
2851*69115f77SDarrick J. Wong {
2852*69115f77SDarrick J. Wong struct xfs_rmap_ownercount roc;
2853*69115f77SDarrick J. Wong int error;
2854*69115f77SDarrick J. Wong
2855*69115f77SDarrick J. Wong xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
2856*69115f77SDarrick J. Wong error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2857*69115f77SDarrick J. Wong xfs_rmap_count_owners_helper, &roc);
2858*69115f77SDarrick J. Wong if (error)
2859*69115f77SDarrick J. Wong return error;
2860*69115f77SDarrick J. Wong
2861*69115f77SDarrick J. Wong /*
2862*69115f77SDarrick J. Wong * There can't be any non-owner rmaps that conflict with the given
2863*69115f77SDarrick J. Wong * owner if we didn't find any rmaps matching the owner.
2864*69115f77SDarrick J. Wong */
2865*69115f77SDarrick J. Wong if (!results->matches)
2866*69115f77SDarrick J. Wong results->bad_non_owner_matches = 0;
2867*69115f77SDarrick J. Wong
2868*69115f77SDarrick J. Wong return 0;
2869*69115f77SDarrick J. Wong }
2870*69115f77SDarrick J. Wong
2871*69115f77SDarrick J. Wong /*
2872*69115f77SDarrick J. Wong * Given an extent and some owner info, can we find records overlapping
28734d4f86b4SDarrick J. Wong * the extent whose owner info does not match the given owner?
28744d4f86b4SDarrick J. Wong */
28754d4f86b4SDarrick 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)28764d4f86b4SDarrick J. Wong xfs_rmap_has_other_keys(
28774d4f86b4SDarrick J. Wong struct xfs_btree_cur *cur,
28784d4f86b4SDarrick J. Wong xfs_agblock_t bno,
28794d4f86b4SDarrick J. Wong xfs_extlen_t len,
28804d4f86b4SDarrick J. Wong const struct xfs_owner_info *oinfo,
28814d4f86b4SDarrick J. Wong bool *has_other)
28824d4f86b4SDarrick J. Wong {
28834d4f86b4SDarrick J. Wong struct xfs_rmap_matches res;
288466e3237eSDarrick J. Wong struct xfs_rmap_ownercount roc;
2885*69115f77SDarrick J. Wong int error;
28864d4f86b4SDarrick J. Wong
2887*69115f77SDarrick J. Wong xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
2888*69115f77SDarrick J. Wong roc.stop_on_nonmatch = true;
28894d4f86b4SDarrick J. Wong
28904d4f86b4SDarrick J. Wong error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2891*69115f77SDarrick J. Wong xfs_rmap_count_owners_helper, &roc);
2892*69115f77SDarrick J. Wong if (error == -ECANCELED) {
28934d4f86b4SDarrick J. Wong *has_other = true;
2894*69115f77SDarrick J. Wong return 0;
2895*69115f77SDarrick J. Wong }
2896a71e4228SDarrick J. Wong if (error)
2897*69115f77SDarrick J. Wong return error;
28987380e8feSDarrick J. Wong
28994d4f86b4SDarrick J. Wong *has_other = false;
2900*69115f77SDarrick J. Wong return 0;
2901a71e4228SDarrick J. Wong }
2902*69115f77SDarrick J. Wong
2903*69115f77SDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2904*69115f77SDarrick J. Wong .oi_owner = XFS_RMAP_OWN_NULL,
2905a71e4228SDarrick J. Wong };
2906a71e4228SDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
29077280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_UNKNOWN,
29087280fedaSDarrick J. Wong };
29097280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
29107280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_FS,
29117280fedaSDarrick J. Wong };
29127280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
29137280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_LOG,
29147280fedaSDarrick J. Wong };
29157280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
29167280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_AG,
29177280fedaSDarrick J. Wong };
29187280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
29197280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INOBT,
29207280fedaSDarrick J. Wong };
29217280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
29227280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_INODES,
29237280fedaSDarrick J. Wong };
29247280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
29257280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_REFC,
29267280fedaSDarrick J. Wong };
29277280fedaSDarrick J. Wong const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
29287280fedaSDarrick J. Wong .oi_owner = XFS_RMAP_OWN_COW,
29297280fedaSDarrick J. Wong };
29307280fedaSDarrick J. Wong
29317280fedaSDarrick J. Wong int __init
xfs_rmap_intent_init_cache(void)29327280fedaSDarrick J. Wong xfs_rmap_intent_init_cache(void)
29337280fedaSDarrick J. Wong {
2934f3c799c2SDarrick J. Wong xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
2935f3c799c2SDarrick J. Wong sizeof(struct xfs_rmap_intent),
2936f3c799c2SDarrick J. Wong 0, 0, NULL);
2937f3c799c2SDarrick J. Wong
2938f3c799c2SDarrick J. Wong return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
2939f3c799c2SDarrick J. Wong }
2940f3c799c2SDarrick J. Wong
2941f3c799c2SDarrick J. Wong void
xfs_rmap_intent_destroy_cache(void)2942f3c799c2SDarrick J. Wong xfs_rmap_intent_destroy_cache(void)
2943f3c799c2SDarrick J. Wong {
2944f3c799c2SDarrick J. Wong kmem_cache_destroy(xfs_rmap_intent_cache);
2945f3c799c2SDarrick J. Wong xfs_rmap_intent_cache = NULL;
2946f3c799c2SDarrick J. Wong }
2947f3c799c2SDarrick J. Wong