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