]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_rmap.c
xfsprogs: Release v6.15.0
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_rmap.c
CommitLineData
37b3b4d6 1// SPDX-License-Identifier: GPL-2.0
631ac87a
DW
2/*
3 * Copyright (c) 2014 Red Hat, Inc.
4 * All Rights Reserved.
631ac87a
DW
5 */
6#include "libxfs_priv.h"
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
12#include "xfs_bit.h"
631ac87a 13#include "xfs_mount.h"
7635c486 14#include "xfs_sb.h"
631ac87a 15#include "xfs_defer.h"
631ac87a
DW
16#include "xfs_btree.h"
17#include "xfs_trans.h"
18#include "xfs_alloc.h"
19#include "xfs_rmap.h"
631bda23 20#include "xfs_rmap_btree.h"
631ac87a 21#include "xfs_trace.h"
2cf10e4c 22#include "xfs_errortag.h"
d7f80320 23#include "xfs_inode.h"
f93d2173 24#include "xfs_ag.h"
e30bad41 25#include "xfs_health.h"
f8a9e37d 26#include "defer_item.h"
edbc7b47 27#include "xfs_rtgroup.h"
5cc11f59 28#include "xfs_rtrmap_btree.h"
631ac87a 29
1577541c
DW
30struct kmem_cache *xfs_rmap_intent_cache;
31
936ca687
DW
32/*
33 * Lookup the first record less than or equal to [bno, len, owner, offset]
34 * in the btree given by cur.
35 */
36int
37xfs_rmap_lookup_le(
38 struct xfs_btree_cur *cur,
39 xfs_agblock_t bno,
936ca687
DW
40 uint64_t owner,
41 uint64_t offset,
42 unsigned int flags,
4a195282 43 struct xfs_rmap_irec *irec,
936ca687
DW
44 int *stat)
45{
4a195282
DW
46 int get_stat = 0;
47 int error;
48
936ca687 49 cur->bc_rec.r.rm_startblock = bno;
4a195282 50 cur->bc_rec.r.rm_blockcount = 0;
936ca687
DW
51 cur->bc_rec.r.rm_owner = owner;
52 cur->bc_rec.r.rm_offset = offset;
53 cur->bc_rec.r.rm_flags = flags;
4a195282
DW
54
55 error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
56 if (error || !(*stat) || !irec)
57 return error;
58
59 error = xfs_rmap_get_rec(cur, irec, &get_stat);
60 if (error)
61 return error;
e30bad41
DW
62 if (!get_stat) {
63 xfs_btree_mark_sick(cur);
4a195282 64 return -EFSCORRUPTED;
e30bad41 65 }
4a195282
DW
66
67 return 0;
936ca687
DW
68}
69
70/*
71 * Lookup the record exactly matching [bno, len, owner, offset]
72 * in the btree given by cur.
73 */
74int
75xfs_rmap_lookup_eq(
76 struct xfs_btree_cur *cur,
77 xfs_agblock_t bno,
78 xfs_extlen_t len,
79 uint64_t owner,
80 uint64_t offset,
81 unsigned int flags,
82 int *stat)
83{
84 cur->bc_rec.r.rm_startblock = bno;
85 cur->bc_rec.r.rm_blockcount = len;
86 cur->bc_rec.r.rm_owner = owner;
87 cur->bc_rec.r.rm_offset = offset;
88 cur->bc_rec.r.rm_flags = flags;
89 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
90}
91
92/*
93 * Update the record referred to by cur to the value given
94 * by [bno, len, owner, offset].
95 * This either works (return 0) or gets an EFSCORRUPTED error.
96 */
97STATIC int
98xfs_rmap_update(
99 struct xfs_btree_cur *cur,
100 struct xfs_rmap_irec *irec)
101{
102 union xfs_btree_rec rec;
b26675c4
DW
103 int error;
104
18c3bc7f 105 trace_xfs_rmap_update(cur, irec->rm_startblock, irec->rm_blockcount,
b26675c4 106 irec->rm_owner, irec->rm_offset, irec->rm_flags);
936ca687
DW
107
108 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
109 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
110 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
111 rec.rmap.rm_offset = cpu_to_be64(
112 xfs_rmap_irec_offset_pack(irec));
b26675c4
DW
113 error = xfs_btree_update(cur, &rec);
114 if (error)
ff6e47b3 115 trace_xfs_rmap_update_error(cur, error, _RET_IP_);
b26675c4
DW
116 return error;
117}
118
119int
120xfs_rmap_insert(
121 struct xfs_btree_cur *rcur,
122 xfs_agblock_t agbno,
123 xfs_extlen_t len,
124 uint64_t owner,
125 uint64_t offset,
126 unsigned int flags)
127{
128 int i;
129 int error;
130
18c3bc7f 131 trace_xfs_rmap_insert(rcur, agbno, len, owner, offset, flags);
b26675c4
DW
132
133 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
134 if (error)
135 goto done;
fbb4fa7f 136 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
4467a60a 137 xfs_btree_mark_sick(rcur);
fbb4fa7f
DW
138 error = -EFSCORRUPTED;
139 goto done;
140 }
b26675c4
DW
141
142 rcur->bc_rec.r.rm_startblock = agbno;
143 rcur->bc_rec.r.rm_blockcount = len;
144 rcur->bc_rec.r.rm_owner = owner;
145 rcur->bc_rec.r.rm_offset = offset;
146 rcur->bc_rec.r.rm_flags = flags;
147 error = xfs_btree_insert(rcur, &i);
148 if (error)
149 goto done;
fbb4fa7f 150 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
4467a60a 151 xfs_btree_mark_sick(rcur);
fbb4fa7f
DW
152 error = -EFSCORRUPTED;
153 goto done;
154 }
b26675c4
DW
155done:
156 if (error)
ff6e47b3 157 trace_xfs_rmap_insert_error(rcur, error, _RET_IP_);
b26675c4 158 return error;
936ca687
DW
159}
160
6c6bdf6f
DW
161STATIC int
162xfs_rmap_delete(
163 struct xfs_btree_cur *rcur,
164 xfs_agblock_t agbno,
165 xfs_extlen_t len,
166 uint64_t owner,
167 uint64_t offset,
168 unsigned int flags)
169{
170 int i;
171 int error;
172
18c3bc7f 173 trace_xfs_rmap_delete(rcur, agbno, len, owner, offset, flags);
6c6bdf6f
DW
174
175 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
176 if (error)
177 goto done;
fbb4fa7f 178 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
4467a60a 179 xfs_btree_mark_sick(rcur);
fbb4fa7f
DW
180 error = -EFSCORRUPTED;
181 goto done;
182 }
6c6bdf6f
DW
183
184 error = xfs_btree_delete(rcur, &i);
185 if (error)
186 goto done;
fbb4fa7f 187 if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
4467a60a 188 xfs_btree_mark_sick(rcur);
fbb4fa7f
DW
189 error = -EFSCORRUPTED;
190 goto done;
191 }
6c6bdf6f
DW
192done:
193 if (error)
ff6e47b3 194 trace_xfs_rmap_delete_error(rcur, error, _RET_IP_);
6c6bdf6f
DW
195 return error;
196}
197
50bb67d6 198/* Convert an internal btree record to an rmap record. */
8d444a7a 199xfs_failaddr_t
936ca687 200xfs_rmap_btrec_to_irec(
e62318a3
DW
201 const union xfs_btree_rec *rec,
202 struct xfs_rmap_irec *irec)
936ca687 203{
936ca687
DW
204 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
205 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
206 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
207 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
208 irec);
209}
210
fd1d74cd
DW
211/* Simple checks for rmap records. */
212xfs_failaddr_t
213xfs_rmap_check_irec(
048c5321 214 struct xfs_perag *pag,
fd1d74cd
DW
215 const struct xfs_rmap_irec *irec)
216{
6a271c73 217 struct xfs_mount *mp = pag_mount(pag);
7e7856ce
DW
218 bool is_inode;
219 bool is_unwritten;
220 bool is_bmbt;
221 bool is_attr;
fd1d74cd
DW
222
223 if (irec->rm_blockcount == 0)
224 return __this_address;
225 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
226 if (irec->rm_owner != XFS_RMAP_OWN_FS)
227 return __this_address;
228 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
229 return __this_address;
230 } else {
231 /* check for valid extent range, including overflow */
048c5321
DW
232 if (!xfs_verify_agbext(pag, irec->rm_startblock,
233 irec->rm_blockcount))
fd1d74cd
DW
234 return __this_address;
235 }
236
237 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
238 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
239 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
240 return __this_address;
241
7e7856ce
DW
242 /* Check flags. */
243 is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
244 is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
245 is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
246 is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
247
248 if (is_bmbt && irec->rm_offset != 0)
249 return __this_address;
250
251 if (!is_inode && irec->rm_offset != 0)
252 return __this_address;
253
254 if (is_unwritten && (is_bmbt || !is_inode || is_attr))
255 return __this_address;
256
257 if (!is_inode && (is_bmbt || is_unwritten || is_attr))
258 return __this_address;
259
b3c8146e
DW
260 /* Check for a valid fork offset, if applicable. */
261 if (is_inode && !is_bmbt &&
262 !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
263 return __this_address;
264
fd1d74cd
DW
265 return NULL;
266}
267
edbc7b47
DW
268static xfs_failaddr_t
269xfs_rtrmap_check_meta_irec(
270 struct xfs_rtgroup *rtg,
271 const struct xfs_rmap_irec *irec)
272{
273 struct xfs_mount *mp = rtg_mount(rtg);
274
275 if (irec->rm_offset != 0)
276 return __this_address;
277 if (irec->rm_flags & XFS_RMAP_UNWRITTEN)
278 return __this_address;
279
280 switch (irec->rm_owner) {
281 case XFS_RMAP_OWN_FS:
282 if (irec->rm_startblock != 0)
283 return __this_address;
284 if (irec->rm_blockcount != mp->m_sb.sb_rextsize)
285 return __this_address;
286 return NULL;
3209f6f1
DW
287 case XFS_RMAP_OWN_COW:
288 if (!xfs_has_rtreflink(mp))
289 return __this_address;
290 if (!xfs_verify_rgbext(rtg, irec->rm_startblock,
291 irec->rm_blockcount))
292 return __this_address;
293 return NULL;
edbc7b47
DW
294 default:
295 return __this_address;
296 }
297
298 return NULL;
299}
300
301static xfs_failaddr_t
302xfs_rtrmap_check_inode_irec(
303 struct xfs_rtgroup *rtg,
304 const struct xfs_rmap_irec *irec)
305{
306 struct xfs_mount *mp = rtg_mount(rtg);
307
308 if (!xfs_verify_ino(mp, irec->rm_owner))
309 return __this_address;
310 if (!xfs_verify_rgbext(rtg, irec->rm_startblock, irec->rm_blockcount))
311 return __this_address;
312 if (!xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
313 return __this_address;
314 return NULL;
315}
316
317xfs_failaddr_t
318xfs_rtrmap_check_irec(
319 struct xfs_rtgroup *rtg,
320 const struct xfs_rmap_irec *irec)
321{
322 if (irec->rm_blockcount == 0)
323 return __this_address;
324 if (irec->rm_flags & (XFS_RMAP_BMBT_BLOCK | XFS_RMAP_ATTR_FORK))
325 return __this_address;
326 if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
327 return xfs_rtrmap_check_meta_irec(rtg, irec);
328 return xfs_rtrmap_check_inode_irec(rtg, irec);
329}
330
9ff7cce7
DW
331static inline xfs_failaddr_t
332xfs_rmap_check_btrec(
333 struct xfs_btree_cur *cur,
334 const struct xfs_rmap_irec *irec)
335{
57f34d77
DW
336 if (xfs_btree_is_rtrmap(cur->bc_ops) ||
337 xfs_btree_is_mem_rtrmap(cur->bc_ops))
edbc7b47 338 return xfs_rtrmap_check_irec(to_rtg(cur->bc_group), irec);
1fa5e300 339 return xfs_rmap_check_irec(to_perag(cur->bc_group), irec);
9ff7cce7
DW
340}
341
e70bf9ba
DW
342static inline int
343xfs_rmap_complain_bad_rec(
344 struct xfs_btree_cur *cur,
345 xfs_failaddr_t fa,
346 const struct xfs_rmap_irec *irec)
347{
348 struct xfs_mount *mp = cur->bc_mp;
349
9ff7cce7
DW
350 if (xfs_btree_is_mem_rmap(cur->bc_ops))
351 xfs_warn(mp,
352 "In-Memory Reverse Mapping BTree record corruption detected at %pS!", fa);
edbc7b47
DW
353 else if (xfs_btree_is_rtrmap(cur->bc_ops))
354 xfs_warn(mp,
355 "RT Reverse Mapping BTree record corruption in rtgroup %u detected at %pS!",
356 cur->bc_group->xg_gno, fa);
9ff7cce7
DW
357 else
358 xfs_warn(mp,
359 "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
1fa5e300 360 cur->bc_group->xg_gno, fa);
e70bf9ba
DW
361 xfs_warn(mp,
362 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
363 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
364 irec->rm_blockcount);
e30bad41 365 xfs_btree_mark_sick(cur);
e70bf9ba
DW
366 return -EFSCORRUPTED;
367}
368
936ca687
DW
369/*
370 * Get the data from the pointed-to record.
371 */
372int
373xfs_rmap_get_rec(
374 struct xfs_btree_cur *cur,
375 struct xfs_rmap_irec *irec,
376 int *stat)
377{
378 union xfs_btree_rec *rec;
fd1d74cd 379 xfs_failaddr_t fa;
936ca687
DW
380 int error;
381
382 error = xfs_btree_get_rec(cur, &rec, stat);
383 if (error || !*stat)
384 return error;
385
fd1d74cd
DW
386 fa = xfs_rmap_btrec_to_irec(rec, irec);
387 if (!fa)
9ff7cce7 388 fa = xfs_rmap_check_btrec(cur, irec);
fd1d74cd 389 if (fa)
e70bf9ba 390 return xfs_rmap_complain_bad_rec(cur, fa, irec);
ec291989
DC
391
392 return 0;
936ca687
DW
393}
394
6c6bdf6f
DW
395struct xfs_find_left_neighbor_info {
396 struct xfs_rmap_irec high;
397 struct xfs_rmap_irec *irec;
6c6bdf6f
DW
398};
399
400/* For each rmap given, figure out if it matches the key we want. */
401STATIC int
402xfs_rmap_find_left_neighbor_helper(
e62318a3
DW
403 struct xfs_btree_cur *cur,
404 const struct xfs_rmap_irec *rec,
405 void *priv)
6c6bdf6f
DW
406{
407 struct xfs_find_left_neighbor_info *info = priv;
408
18c3bc7f 409 trace_xfs_rmap_find_left_neighbor_candidate(cur, rec->rm_startblock,
6c6bdf6f
DW
410 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
411 rec->rm_flags);
412
413 if (rec->rm_owner != info->high.rm_owner)
7dd6dee1 414 return 0;
6c6bdf6f
DW
415 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
416 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
417 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
7dd6dee1 418 return 0;
6c6bdf6f
DW
419
420 *info->irec = *rec;
a0f17dde 421 return -ECANCELED;
6c6bdf6f
DW
422}
423
424/*
425 * Find the record to the left of the given extent, being careful only to
426 * return a match with the same owner and adjacent physical and logical
427 * block ranges.
428 */
92798496 429STATIC int
6c6bdf6f
DW
430xfs_rmap_find_left_neighbor(
431 struct xfs_btree_cur *cur,
432 xfs_agblock_t bno,
433 uint64_t owner,
434 uint64_t offset,
435 unsigned int flags,
436 struct xfs_rmap_irec *irec,
437 int *stat)
438{
439 struct xfs_find_left_neighbor_info info;
92798496 440 int found = 0;
6c6bdf6f
DW
441 int error;
442
443 *stat = 0;
444 if (bno == 0)
445 return 0;
446 info.high.rm_startblock = bno - 1;
447 info.high.rm_owner = owner;
448 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
449 !(flags & XFS_RMAP_BMBT_BLOCK)) {
450 if (offset == 0)
451 return 0;
452 info.high.rm_offset = offset - 1;
453 } else
454 info.high.rm_offset = 0;
455 info.high.rm_flags = flags;
456 info.high.rm_blockcount = 0;
457 info.irec = irec;
6c6bdf6f 458
18c3bc7f
DW
459 trace_xfs_rmap_find_left_neighbor_query(cur, bno, 0, owner, offset,
460 flags);
6c6bdf6f 461
92798496
DW
462 /*
463 * Historically, we always used the range query to walk every reverse
464 * mapping that could possibly overlap the key that the caller asked
465 * for, and filter out the ones that don't. That is very slow when
466 * there are a lot of records.
467 *
468 * However, there are two scenarios where the classic btree search can
469 * produce correct results -- if the index contains a record that is an
470 * exact match for the lookup key; and if there are no other records
471 * between the record we want and the key we supplied.
472 *
473 * As an optimization, try a non-overlapped lookup first. This makes
474 * extent conversion and remap operations run a bit faster if the
475 * physical extents aren't being shared. If we don't find what we
476 * want, we fall back to the overlapped query.
477 */
478 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
479 &found);
480 if (error)
481 return error;
482 if (found)
483 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
484 if (!error)
485 error = xfs_rmap_query_range(cur, &info.high, &info.high,
486 xfs_rmap_find_left_neighbor_helper, &info);
487 if (error != -ECANCELED)
488 return error;
489
490 *stat = 1;
18c3bc7f 491 trace_xfs_rmap_find_left_neighbor_result(cur, irec->rm_startblock,
92798496
DW
492 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
493 irec->rm_flags);
494 return 0;
6c6bdf6f
DW
495}
496
497/* For each rmap given, figure out if it matches the key we want. */
498STATIC int
499xfs_rmap_lookup_le_range_helper(
e62318a3
DW
500 struct xfs_btree_cur *cur,
501 const struct xfs_rmap_irec *rec,
502 void *priv)
6c6bdf6f
DW
503{
504 struct xfs_find_left_neighbor_info *info = priv;
505
18c3bc7f 506 trace_xfs_rmap_lookup_le_range_candidate(cur, rec->rm_startblock,
6c6bdf6f
DW
507 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
508 rec->rm_flags);
509
510 if (rec->rm_owner != info->high.rm_owner)
7dd6dee1 511 return 0;
6c6bdf6f
DW
512 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
513 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
514 (rec->rm_offset > info->high.rm_offset ||
515 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
7dd6dee1 516 return 0;
6c6bdf6f
DW
517
518 *info->irec = *rec;
a0f17dde 519 return -ECANCELED;
6c6bdf6f
DW
520}
521
522/*
523 * Find the record to the left of the given extent, being careful only to
524 * return a match with the same owner and overlapping physical and logical
525 * block ranges. This is the overlapping-interval version of
526 * xfs_rmap_lookup_le.
527 */
528int
529xfs_rmap_lookup_le_range(
530 struct xfs_btree_cur *cur,
531 xfs_agblock_t bno,
532 uint64_t owner,
533 uint64_t offset,
534 unsigned int flags,
535 struct xfs_rmap_irec *irec,
536 int *stat)
537{
538 struct xfs_find_left_neighbor_info info;
8b03b413 539 int found = 0;
6c6bdf6f
DW
540 int error;
541
542 info.high.rm_startblock = bno;
543 info.high.rm_owner = owner;
544 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
545 info.high.rm_offset = offset;
546 else
547 info.high.rm_offset = 0;
548 info.high.rm_flags = flags;
549 info.high.rm_blockcount = 0;
550 *stat = 0;
551 info.irec = irec;
6c6bdf6f 552
18c3bc7f 553 trace_xfs_rmap_lookup_le_range(cur, bno, 0, owner, offset, flags);
8b03b413
DW
554
555 /*
556 * Historically, we always used the range query to walk every reverse
557 * mapping that could possibly overlap the key that the caller asked
558 * for, and filter out the ones that don't. That is very slow when
559 * there are a lot of records.
560 *
561 * However, there are two scenarios where the classic btree search can
562 * produce correct results -- if the index contains a record that is an
563 * exact match for the lookup key; and if there are no other records
564 * between the record we want and the key we supplied.
565 *
566 * As an optimization, try a non-overlapped lookup first. This makes
567 * scrub run much faster on most filesystems because bmbt records are
568 * usually an exact match for rmap records. If we don't find what we
569 * want, we fall back to the overlapped query.
570 */
571 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
572 &found);
573 if (error)
574 return error;
575 if (found)
576 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
577 if (!error)
578 error = xfs_rmap_query_range(cur, &info.high, &info.high,
579 xfs_rmap_lookup_le_range_helper, &info);
580 if (error != -ECANCELED)
581 return error;
582
583 *stat = 1;
18c3bc7f 584 trace_xfs_rmap_lookup_le_range_result(cur, irec->rm_startblock,
8b03b413
DW
585 irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
586 irec->rm_flags);
587 return 0;
6c6bdf6f
DW
588}
589
19f9a63a
DW
590/*
591 * Perform all the relevant owner checks for a removal op. If we're doing an
592 * unknown-owner removal then we have no owner information to check.
593 */
594static int
595xfs_rmap_free_check_owner(
4467a60a 596 struct xfs_btree_cur *cur,
19f9a63a
DW
597 uint64_t ltoff,
598 struct xfs_rmap_irec *rec,
cf20a9c6 599 xfs_extlen_t len,
19f9a63a
DW
600 uint64_t owner,
601 uint64_t offset,
602 unsigned int flags)
603{
4467a60a 604 struct xfs_mount *mp = cur->bc_mp;
19f9a63a
DW
605 int error = 0;
606
607 if (owner == XFS_RMAP_OWN_UNKNOWN)
608 return 0;
609
610 /* Make sure the unwritten flag matches. */
fbb4fa7f
DW
611 if (XFS_IS_CORRUPT(mp,
612 (flags & XFS_RMAP_UNWRITTEN) !=
613 (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
4467a60a 614 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
615 error = -EFSCORRUPTED;
616 goto out;
617 }
19f9a63a
DW
618
619 /* Make sure the owner matches what we expect to find in the tree. */
fbb4fa7f 620 if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
4467a60a 621 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
622 error = -EFSCORRUPTED;
623 goto out;
624 }
19f9a63a
DW
625
626 /* Check the offset, if necessary. */
627 if (XFS_RMAP_NON_INODE_OWNER(owner))
628 goto out;
629
630 if (flags & XFS_RMAP_BMBT_BLOCK) {
fbb4fa7f
DW
631 if (XFS_IS_CORRUPT(mp,
632 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
4467a60a 633 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
634 error = -EFSCORRUPTED;
635 goto out;
636 }
19f9a63a 637 } else {
fbb4fa7f 638 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
4467a60a 639 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
640 error = -EFSCORRUPTED;
641 goto out;
642 }
643 if (XFS_IS_CORRUPT(mp,
644 offset + len > ltoff + rec->rm_blockcount)) {
4467a60a 645 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
646 error = -EFSCORRUPTED;
647 goto out;
648 }
19f9a63a
DW
649 }
650
651out:
652 return error;
653}
654
ae81ebf2
DW
655/*
656 * Find the extent in the rmap btree and remove it.
657 *
658 * The record we find should always be an exact match for the extent that we're
659 * looking for, since we insert them into the btree without modification.
660 *
661 * Special Case #1: when growing the filesystem, we "free" an extent when
662 * growing the last AG. This extent is new space and so it is not tracked as
663 * used space in the btree. The growfs code will pass in an owner of
664 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
665 * extent. We verify that - the extent lookup result in a record that does not
666 * overlap.
667 *
668 * Special Case #2: EFIs do not record the owner of the extent, so when
669 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
670 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
671 * corruption checks during log recovery.
672 */
673STATIC int
674xfs_rmap_unmap(
5837e73b
DW
675 struct xfs_btree_cur *cur,
676 xfs_agblock_t bno,
677 xfs_extlen_t len,
678 bool unwritten,
679 const struct xfs_owner_info *oinfo)
ae81ebf2 680{
5837e73b
DW
681 struct xfs_mount *mp = cur->bc_mp;
682 struct xfs_rmap_irec ltrec;
683 uint64_t ltoff;
684 int error = 0;
685 int i;
686 uint64_t owner;
687 uint64_t offset;
688 unsigned int flags;
689 bool ignore_off;
ae81ebf2
DW
690
691 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
692 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
693 (flags & XFS_RMAP_BMBT_BLOCK);
694 if (unwritten)
695 flags |= XFS_RMAP_UNWRITTEN;
18c3bc7f 696 trace_xfs_rmap_unmap(cur, bno, len, unwritten, oinfo);
ae81ebf2
DW
697
698 /*
699 * We should always have a left record because there's a static record
700 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
701 * will not ever be removed from the tree.
702 */
4a195282 703 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec, &i);
ae81ebf2
DW
704 if (error)
705 goto out_error;
fbb4fa7f 706 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 707 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
708 error = -EFSCORRUPTED;
709 goto out_error;
710 }
ae81ebf2 711
18c3bc7f
DW
712 trace_xfs_rmap_lookup_le_range_result(cur, ltrec.rm_startblock,
713 ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset,
714 ltrec.rm_flags);
ae81ebf2
DW
715 ltoff = ltrec.rm_offset;
716
717 /*
718 * For growfs, the incoming extent must be beyond the left record we
719 * just found as it is new space and won't be used by anyone. This is
720 * just a corruption check as we don't actually do anything with this
721 * extent. Note that we need to use >= instead of > because it might
722 * be the case that the "left" extent goes all the way to EOFS.
723 */
724 if (owner == XFS_RMAP_OWN_NULL) {
fbb4fa7f
DW
725 if (XFS_IS_CORRUPT(mp,
726 bno <
727 ltrec.rm_startblock + ltrec.rm_blockcount)) {
4467a60a 728 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
729 error = -EFSCORRUPTED;
730 goto out_error;
731 }
ae81ebf2
DW
732 goto out_done;
733 }
734
3ee858aa
DW
735 /*
736 * If we're doing an unknown-owner removal for EFI recovery, we expect
737 * to find the full range in the rmapbt or nothing at all. If we
738 * don't find any rmaps overlapping either end of the range, we're
739 * done. Hopefully this means that the EFI creator already queued
740 * (and finished) a RUI to remove the rmap.
741 */
742 if (owner == XFS_RMAP_OWN_UNKNOWN &&
743 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
744 struct xfs_rmap_irec rtrec;
745
746 error = xfs_btree_increment(cur, 0, &i);
747 if (error)
748 goto out_error;
749 if (i == 0)
750 goto out_done;
751 error = xfs_rmap_get_rec(cur, &rtrec, &i);
752 if (error)
753 goto out_error;
fbb4fa7f 754 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 755 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
756 error = -EFSCORRUPTED;
757 goto out_error;
758 }
3ee858aa
DW
759 if (rtrec.rm_startblock >= bno + len)
760 goto out_done;
761 }
762
ae81ebf2 763 /* Make sure the extent we found covers the entire freeing range. */
fbb4fa7f
DW
764 if (XFS_IS_CORRUPT(mp,
765 ltrec.rm_startblock > bno ||
766 ltrec.rm_startblock + ltrec.rm_blockcount <
767 bno + len)) {
4467a60a 768 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
769 error = -EFSCORRUPTED;
770 goto out_error;
771 }
ae81ebf2 772
19f9a63a 773 /* Check owner information. */
4467a60a 774 error = xfs_rmap_free_check_owner(cur, ltoff, &ltrec, len, owner,
19f9a63a
DW
775 offset, flags);
776 if (error)
777 goto out_error;
ae81ebf2
DW
778
779 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
780 /* exact match, simply remove the record from rmap tree */
18c3bc7f
DW
781 trace_xfs_rmap_delete(cur, ltrec.rm_startblock,
782 ltrec.rm_blockcount, ltrec.rm_owner,
783 ltrec.rm_offset, ltrec.rm_flags);
ae81ebf2
DW
784 error = xfs_btree_delete(cur, &i);
785 if (error)
786 goto out_error;
fbb4fa7f 787 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 788 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
789 error = -EFSCORRUPTED;
790 goto out_error;
791 }
ae81ebf2
DW
792 } else if (ltrec.rm_startblock == bno) {
793 /*
794 * overlap left hand side of extent: move the start, trim the
795 * length and update the current record.
796 *
797 * ltbno ltlen
798 * Orig: |oooooooooooooooooooo|
799 * Freeing: |fffffffff|
800 * Result: |rrrrrrrrrr|
801 * bno len
802 */
803 ltrec.rm_startblock += len;
804 ltrec.rm_blockcount -= len;
805 if (!ignore_off)
806 ltrec.rm_offset += len;
807 error = xfs_rmap_update(cur, &ltrec);
808 if (error)
809 goto out_error;
810 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
811 /*
812 * overlap right hand side of extent: trim the length and update
813 * the current record.
814 *
815 * ltbno ltlen
816 * Orig: |oooooooooooooooooooo|
817 * Freeing: |fffffffff|
818 * Result: |rrrrrrrrrr|
819 * bno len
820 */
821 ltrec.rm_blockcount -= len;
822 error = xfs_rmap_update(cur, &ltrec);
823 if (error)
824 goto out_error;
825 } else {
826
827 /*
828 * overlap middle of extent: trim the length of the existing
829 * record to the length of the new left-extent size, increment
830 * the insertion position so we can insert a new record
831 * containing the remaining right-extent space.
832 *
833 * ltbno ltlen
834 * Orig: |oooooooooooooooooooo|
835 * Freeing: |fffffffff|
836 * Result: |rrrrr| |rrrr|
837 * bno len
838 */
839 xfs_extlen_t orig_len = ltrec.rm_blockcount;
840
841 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
842 error = xfs_rmap_update(cur, &ltrec);
843 if (error)
844 goto out_error;
845
846 error = xfs_btree_increment(cur, 0, &i);
847 if (error)
848 goto out_error;
849
850 cur->bc_rec.r.rm_startblock = bno + len;
851 cur->bc_rec.r.rm_blockcount = orig_len - len -
852 ltrec.rm_blockcount;
853 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
854 if (ignore_off)
855 cur->bc_rec.r.rm_offset = 0;
856 else
857 cur->bc_rec.r.rm_offset = offset + len;
858 cur->bc_rec.r.rm_flags = flags;
18c3bc7f 859 trace_xfs_rmap_insert(cur, cur->bc_rec.r.rm_startblock,
ae81ebf2
DW
860 cur->bc_rec.r.rm_blockcount,
861 cur->bc_rec.r.rm_owner,
862 cur->bc_rec.r.rm_offset,
863 cur->bc_rec.r.rm_flags);
864 error = xfs_btree_insert(cur, &i);
865 if (error)
866 goto out_error;
867 }
868
869out_done:
18c3bc7f 870 trace_xfs_rmap_unmap_done(cur, bno, len, unwritten, oinfo);
ae81ebf2
DW
871out_error:
872 if (error)
ff6e47b3 873 trace_xfs_rmap_unmap_error(cur, error, _RET_IP_);
ae81ebf2
DW
874 return error;
875}
876
a2fd18b4
DW
877#ifdef CONFIG_XFS_LIVE_HOOKS
878/*
879 * Use a static key here to reduce the overhead of rmapbt live updates. If
880 * the compiler supports jump labels, the static branch will be replaced by a
881 * nop sled when there are no hook users. Online fsck is currently the only
882 * caller, so this is a reasonable tradeoff.
883 *
884 * Note: Patching the kernel code requires taking the cpu hotplug lock. Other
885 * parts of the kernel allocate memory with that lock held, which means that
886 * XFS callers cannot hold any locks that might be used by memory reclaim or
887 * writeback when calling the static_branch_{inc,dec} functions.
888 */
889DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_rmap_hooks_switch);
890
891void
892xfs_rmap_hook_disable(void)
893{
894 xfs_hooks_switch_off(&xfs_rmap_hooks_switch);
895}
896
897void
898xfs_rmap_hook_enable(void)
899{
900 xfs_hooks_switch_on(&xfs_rmap_hooks_switch);
901}
902
903/* Call downstream hooks for a reverse mapping update. */
904static inline void
905xfs_rmap_update_hook(
906 struct xfs_trans *tp,
21cc7c27 907 struct xfs_group *xg,
a2fd18b4
DW
908 enum xfs_rmap_intent_type op,
909 xfs_agblock_t startblock,
910 xfs_extlen_t blockcount,
911 bool unwritten,
912 const struct xfs_owner_info *oinfo)
913{
914 if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch)) {
915 struct xfs_rmap_update_params p = {
916 .startblock = startblock,
917 .blockcount = blockcount,
918 .unwritten = unwritten,
919 .oinfo = *oinfo, /* struct copy */
920 };
921
21cc7c27
CH
922 if (xg)
923 xfs_hooks_call(&xg->xg_rmap_update_hooks, op, &p);
a2fd18b4
DW
924 }
925}
926
927/* Call the specified function during a reverse mapping update. */
928int
929xfs_rmap_hook_add(
21cc7c27 930 struct xfs_group *xg,
a2fd18b4
DW
931 struct xfs_rmap_hook *hook)
932{
21cc7c27 933 return xfs_hooks_add(&xg->xg_rmap_update_hooks, &hook->rmap_hook);
a2fd18b4
DW
934}
935
936/* Stop calling the specified function during a reverse mapping update. */
937void
938xfs_rmap_hook_del(
21cc7c27 939 struct xfs_group *xg,
a2fd18b4
DW
940 struct xfs_rmap_hook *hook)
941{
21cc7c27 942 xfs_hooks_del(&xg->xg_rmap_update_hooks, &hook->rmap_hook);
a2fd18b4
DW
943}
944
945/* Configure rmap update hook functions. */
946void
947xfs_rmap_hook_setup(
948 struct xfs_rmap_hook *hook,
949 notifier_fn_t mod_fn)
950{
951 xfs_hook_setup(&hook->rmap_hook, mod_fn);
952}
953#else
954# define xfs_rmap_update_hook(t, p, o, s, b, u, oi) do { } while (0)
955#endif /* CONFIG_XFS_LIVE_HOOKS */
956
ae81ebf2
DW
957/*
958 * Remove a reference to an extent in the rmap btree.
959 */
631ac87a
DW
960int
961xfs_rmap_free(
5837e73b
DW
962 struct xfs_trans *tp,
963 struct xfs_buf *agbp,
195c248c 964 struct xfs_perag *pag,
5837e73b
DW
965 xfs_agblock_t bno,
966 xfs_extlen_t len,
967 const struct xfs_owner_info *oinfo)
631ac87a 968{
5837e73b
DW
969 struct xfs_mount *mp = tp->t_mountp;
970 struct xfs_btree_cur *cur;
971 int error;
631ac87a 972
b16a427a 973 if (!xfs_has_rmapbt(mp))
631ac87a
DW
974 return 0;
975
195c248c 976 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
21cc7c27
CH
977 xfs_rmap_update_hook(tp, pag_group(pag), XFS_RMAP_UNMAP, bno, len,
978 false, oinfo);
ae81ebf2 979 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
ae81ebf2 980
660265b7 981 xfs_btree_del_cursor(cur, error);
631ac87a
DW
982 return error;
983}
984
631bda23
DW
985/*
986 * A mergeable rmap must have the same owner and the same values for
987 * the unwritten, attr_fork, and bmbt flags. The startblock and
988 * offset are checked separately.
989 */
990static bool
991xfs_rmap_is_mergeable(
992 struct xfs_rmap_irec *irec,
993 uint64_t owner,
994 unsigned int flags)
995{
996 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
997 return false;
998 if (irec->rm_owner != owner)
999 return false;
1000 if ((flags & XFS_RMAP_UNWRITTEN) ^
1001 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
1002 return false;
1003 if ((flags & XFS_RMAP_ATTR_FORK) ^
1004 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
1005 return false;
1006 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
1007 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
1008 return false;
1009 return true;
1010}
1011
1012/*
1013 * When we allocate a new block, the first thing we do is add a reference to
1014 * the extent in the rmap btree. This takes the form of a [agbno, length,
1015 * owner, offset] record. Flags are encoded in the high bits of the offset
1016 * field.
1017 */
1018STATIC int
1019xfs_rmap_map(
5837e73b
DW
1020 struct xfs_btree_cur *cur,
1021 xfs_agblock_t bno,
1022 xfs_extlen_t len,
1023 bool unwritten,
1024 const struct xfs_owner_info *oinfo)
631bda23 1025{
5837e73b
DW
1026 struct xfs_mount *mp = cur->bc_mp;
1027 struct xfs_rmap_irec ltrec;
1028 struct xfs_rmap_irec gtrec;
1029 int have_gt;
1030 int have_lt;
1031 int error = 0;
1032 int i;
1033 uint64_t owner;
1034 uint64_t offset;
1035 unsigned int flags = 0;
1036 bool ignore_off;
631bda23
DW
1037
1038 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1039 ASSERT(owner != 0);
1040 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
1041 (flags & XFS_RMAP_BMBT_BLOCK);
1042 if (unwritten)
1043 flags |= XFS_RMAP_UNWRITTEN;
18c3bc7f 1044 trace_xfs_rmap_map(cur, bno, len, unwritten, oinfo);
3ee858aa 1045 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
631bda23
DW
1046
1047 /*
1048 * For the initial lookup, look for an exact match or the left-adjacent
1049 * record for our insertion point. This will also give us the record for
1050 * start block contiguity tests.
1051 */
4a195282 1052 error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec,
631bda23
DW
1053 &have_lt);
1054 if (error)
1055 goto out_error;
a6ad7ea8 1056 if (have_lt) {
18c3bc7f 1057 trace_xfs_rmap_lookup_le_range_result(cur, ltrec.rm_startblock,
a6ad7ea8
DW
1058 ltrec.rm_blockcount, ltrec.rm_owner,
1059 ltrec.rm_offset, ltrec.rm_flags);
631bda23 1060
a6ad7ea8
DW
1061 if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
1062 have_lt = 0;
1063 }
631bda23 1064
fbb4fa7f
DW
1065 if (XFS_IS_CORRUPT(mp,
1066 have_lt != 0 &&
1067 ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
4467a60a 1068 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1069 error = -EFSCORRUPTED;
1070 goto out_error;
1071 }
631bda23
DW
1072
1073 /*
1074 * Increment the cursor to see if we have a right-adjacent record to our
1075 * insertion point. This will give us the record for end block
1076 * contiguity tests.
1077 */
1078 error = xfs_btree_increment(cur, 0, &have_gt);
1079 if (error)
1080 goto out_error;
1081 if (have_gt) {
1082 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
1083 if (error)
1084 goto out_error;
fbb4fa7f 1085 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
4467a60a 1086 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1087 error = -EFSCORRUPTED;
1088 goto out_error;
1089 }
1090 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
4467a60a 1091 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1092 error = -EFSCORRUPTED;
1093 goto out_error;
1094 }
18c3bc7f
DW
1095 trace_xfs_rmap_find_right_neighbor_result(cur,
1096 gtrec.rm_startblock, gtrec.rm_blockcount,
1097 gtrec.rm_owner, gtrec.rm_offset,
1098 gtrec.rm_flags);
631bda23
DW
1099 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
1100 have_gt = 0;
1101 }
1102
1103 /*
1104 * Note: cursor currently points one record to the right of ltrec, even
1105 * if there is no record in the tree to the right.
1106 */
1107 if (have_lt &&
1108 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1109 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
1110 /*
1111 * left edge contiguous, merge into left record.
1112 *
1113 * ltbno ltlen
1114 * orig: |ooooooooo|
1115 * adding: |aaaaaaaaa|
1116 * result: |rrrrrrrrrrrrrrrrrrr|
1117 * bno len
1118 */
1119 ltrec.rm_blockcount += len;
1120 if (have_gt &&
1121 bno + len == gtrec.rm_startblock &&
1122 (ignore_off || offset + len == gtrec.rm_offset) &&
1123 (unsigned long)ltrec.rm_blockcount + len +
1124 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
1125 /*
1126 * right edge also contiguous, delete right record
1127 * and merge into left record.
1128 *
1129 * ltbno ltlen gtbno gtlen
1130 * orig: |ooooooooo| |ooooooooo|
1131 * adding: |aaaaaaaaa|
1132 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1133 */
1134 ltrec.rm_blockcount += gtrec.rm_blockcount;
18c3bc7f
DW
1135 trace_xfs_rmap_delete(cur, gtrec.rm_startblock,
1136 gtrec.rm_blockcount, gtrec.rm_owner,
1137 gtrec.rm_offset, gtrec.rm_flags);
631bda23
DW
1138 error = xfs_btree_delete(cur, &i);
1139 if (error)
1140 goto out_error;
fbb4fa7f 1141 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1142 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1143 error = -EFSCORRUPTED;
1144 goto out_error;
1145 }
631bda23
DW
1146 }
1147
1148 /* point the cursor back to the left record and update */
1149 error = xfs_btree_decrement(cur, 0, &have_gt);
1150 if (error)
1151 goto out_error;
1152 error = xfs_rmap_update(cur, &ltrec);
1153 if (error)
1154 goto out_error;
1155 } else if (have_gt &&
1156 bno + len == gtrec.rm_startblock &&
1157 (ignore_off || offset + len == gtrec.rm_offset)) {
1158 /*
1159 * right edge contiguous, merge into right record.
1160 *
1161 * gtbno gtlen
1162 * Orig: |ooooooooo|
1163 * adding: |aaaaaaaaa|
1164 * Result: |rrrrrrrrrrrrrrrrrrr|
1165 * bno len
1166 */
1167 gtrec.rm_startblock = bno;
1168 gtrec.rm_blockcount += len;
1169 if (!ignore_off)
1170 gtrec.rm_offset = offset;
1171 error = xfs_rmap_update(cur, &gtrec);
1172 if (error)
1173 goto out_error;
1174 } else {
1175 /*
1176 * no contiguous edge with identical owner, insert
1177 * new record at current cursor position.
1178 */
1179 cur->bc_rec.r.rm_startblock = bno;
1180 cur->bc_rec.r.rm_blockcount = len;
1181 cur->bc_rec.r.rm_owner = owner;
1182 cur->bc_rec.r.rm_offset = offset;
1183 cur->bc_rec.r.rm_flags = flags;
18c3bc7f 1184 trace_xfs_rmap_insert(cur, bno, len, owner, offset, flags);
631bda23
DW
1185 error = xfs_btree_insert(cur, &i);
1186 if (error)
1187 goto out_error;
fbb4fa7f 1188 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1189 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1190 error = -EFSCORRUPTED;
1191 goto out_error;
1192 }
631bda23
DW
1193 }
1194
18c3bc7f 1195 trace_xfs_rmap_map_done(cur, bno, len, unwritten, oinfo);
631bda23
DW
1196out_error:
1197 if (error)
ff6e47b3 1198 trace_xfs_rmap_map_error(cur, error, _RET_IP_);
631bda23
DW
1199 return error;
1200}
1201
1202/*
1203 * Add a reference to an extent in the rmap btree.
1204 */
631ac87a
DW
1205int
1206xfs_rmap_alloc(
5837e73b
DW
1207 struct xfs_trans *tp,
1208 struct xfs_buf *agbp,
195c248c 1209 struct xfs_perag *pag,
5837e73b
DW
1210 xfs_agblock_t bno,
1211 xfs_extlen_t len,
1212 const struct xfs_owner_info *oinfo)
631ac87a 1213{
5837e73b
DW
1214 struct xfs_mount *mp = tp->t_mountp;
1215 struct xfs_btree_cur *cur;
1216 int error;
631ac87a 1217
b16a427a 1218 if (!xfs_has_rmapbt(mp))
631ac87a
DW
1219 return 0;
1220
195c248c 1221 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
21cc7c27
CH
1222 xfs_rmap_update_hook(tp, pag_group(pag), XFS_RMAP_MAP, bno, len, false,
1223 oinfo);
631bda23 1224 error = xfs_rmap_map(cur, bno, len, false, oinfo);
631bda23 1225
660265b7 1226 xfs_btree_del_cursor(cur, error);
631ac87a
DW
1227 return error;
1228}
890e1174 1229
7faf209c
DW
1230#define RMAP_LEFT_CONTIG (1 << 0)
1231#define RMAP_RIGHT_CONTIG (1 << 1)
1232#define RMAP_LEFT_FILLING (1 << 2)
1233#define RMAP_RIGHT_FILLING (1 << 3)
1234#define RMAP_LEFT_VALID (1 << 6)
1235#define RMAP_RIGHT_VALID (1 << 7)
1236
1237#define LEFT r[0]
1238#define RIGHT r[1]
1239#define PREV r[2]
1240#define NEW r[3]
1241
1242/*
1243 * Convert an unwritten extent to a real extent or vice versa.
1244 * Does not handle overlapping extents.
1245 */
1246STATIC int
1247xfs_rmap_convert(
5837e73b
DW
1248 struct xfs_btree_cur *cur,
1249 xfs_agblock_t bno,
1250 xfs_extlen_t len,
1251 bool unwritten,
1252 const struct xfs_owner_info *oinfo)
7faf209c 1253{
5837e73b
DW
1254 struct xfs_mount *mp = cur->bc_mp;
1255 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1256 /* left is 0, right is 1, */
1257 /* prev is 2, new is 3 */
7faf209c
DW
1258 uint64_t owner;
1259 uint64_t offset;
1260 uint64_t new_endoff;
1261 unsigned int oldext;
1262 unsigned int newext;
1263 unsigned int flags = 0;
1264 int i;
1265 int state = 0;
1266 int error;
1267
1268 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1269 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1270 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1271 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1272 new_endoff = offset + len;
18c3bc7f 1273 trace_xfs_rmap_convert(cur, bno, len, unwritten, oinfo);
7faf209c
DW
1274
1275 /*
1276 * For the initial lookup, look for an exact match or the left-adjacent
1277 * record for our insertion point. This will also give us the record for
1278 * start block contiguity tests.
1279 */
4a195282 1280 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
7faf209c
DW
1281 if (error)
1282 goto done;
fbb4fa7f 1283 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1284 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1285 error = -EFSCORRUPTED;
1286 goto done;
1287 }
7faf209c 1288
18c3bc7f
DW
1289 trace_xfs_rmap_lookup_le_range_result(cur, PREV.rm_startblock,
1290 PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset,
1291 PREV.rm_flags);
7faf209c
DW
1292
1293 ASSERT(PREV.rm_offset <= offset);
1294 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1295 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1296 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1297
1298 /*
1299 * Set flags determining what part of the previous oldext allocation
1300 * extent is being replaced by a newext allocation.
1301 */
1302 if (PREV.rm_offset == offset)
1303 state |= RMAP_LEFT_FILLING;
1304 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1305 state |= RMAP_RIGHT_FILLING;
1306
1307 /*
1308 * Decrement the cursor to see if we have a left-adjacent record to our
1309 * insertion point. This will give us the record for end block
1310 * contiguity tests.
1311 */
1312 error = xfs_btree_decrement(cur, 0, &i);
1313 if (error)
1314 goto done;
1315 if (i) {
1316 state |= RMAP_LEFT_VALID;
1317 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1318 if (error)
1319 goto done;
fbb4fa7f 1320 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1321 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1322 error = -EFSCORRUPTED;
1323 goto done;
1324 }
1325 if (XFS_IS_CORRUPT(mp,
1326 LEFT.rm_startblock + LEFT.rm_blockcount >
1327 bno)) {
4467a60a 1328 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1329 error = -EFSCORRUPTED;
1330 goto done;
1331 }
18c3bc7f
DW
1332 trace_xfs_rmap_find_left_neighbor_result(cur,
1333 LEFT.rm_startblock, LEFT.rm_blockcount,
1334 LEFT.rm_owner, LEFT.rm_offset, LEFT.rm_flags);
7faf209c
DW
1335 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1336 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1337 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1338 state |= RMAP_LEFT_CONTIG;
1339 }
1340
1341 /*
1342 * Increment the cursor to see if we have a right-adjacent record to our
1343 * insertion point. This will give us the record for end block
1344 * contiguity tests.
1345 */
1346 error = xfs_btree_increment(cur, 0, &i);
1347 if (error)
1348 goto done;
fbb4fa7f 1349 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1350 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1351 error = -EFSCORRUPTED;
1352 goto done;
1353 }
7faf209c
DW
1354 error = xfs_btree_increment(cur, 0, &i);
1355 if (error)
1356 goto done;
1357 if (i) {
1358 state |= RMAP_RIGHT_VALID;
1359 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1360 if (error)
1361 goto done;
fbb4fa7f 1362 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1363 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1364 error = -EFSCORRUPTED;
1365 goto done;
1366 }
1367 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
4467a60a 1368 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1369 error = -EFSCORRUPTED;
1370 goto done;
1371 }
18c3bc7f
DW
1372 trace_xfs_rmap_find_right_neighbor_result(cur,
1373 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1374 RIGHT.rm_owner, RIGHT.rm_offset,
1375 RIGHT.rm_flags);
7faf209c
DW
1376 if (bno + len == RIGHT.rm_startblock &&
1377 offset + len == RIGHT.rm_offset &&
1378 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1379 state |= RMAP_RIGHT_CONTIG;
1380 }
1381
1382 /* check that left + prev + right is not too long */
1383 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1384 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1385 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1386 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1387 (unsigned long)LEFT.rm_blockcount + len +
1388 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1389 state &= ~RMAP_RIGHT_CONTIG;
1390
ff6e47b3 1391 trace_xfs_rmap_convert_state(cur, state, _RET_IP_);
7faf209c
DW
1392
1393 /* reset the cursor back to PREV */
4a195282 1394 error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
7faf209c
DW
1395 if (error)
1396 goto done;
fbb4fa7f 1397 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1398 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1399 error = -EFSCORRUPTED;
1400 goto done;
1401 }
7faf209c
DW
1402
1403 /*
1404 * Switch out based on the FILLING and CONTIG state bits.
1405 */
1406 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1407 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1408 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1409 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1410 /*
1411 * Setting all of a previous oldext extent to newext.
1412 * The left and right neighbors are both contiguous with new.
1413 */
1414 error = xfs_btree_increment(cur, 0, &i);
1415 if (error)
1416 goto done;
fbb4fa7f 1417 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1418 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1419 error = -EFSCORRUPTED;
1420 goto done;
1421 }
18c3bc7f
DW
1422 trace_xfs_rmap_delete(cur, RIGHT.rm_startblock,
1423 RIGHT.rm_blockcount, RIGHT.rm_owner,
1424 RIGHT.rm_offset, RIGHT.rm_flags);
7faf209c
DW
1425 error = xfs_btree_delete(cur, &i);
1426 if (error)
1427 goto done;
fbb4fa7f 1428 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1429 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1430 error = -EFSCORRUPTED;
1431 goto done;
1432 }
7faf209c
DW
1433 error = xfs_btree_decrement(cur, 0, &i);
1434 if (error)
1435 goto done;
fbb4fa7f 1436 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1437 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1438 error = -EFSCORRUPTED;
1439 goto done;
1440 }
18c3bc7f
DW
1441 trace_xfs_rmap_delete(cur, PREV.rm_startblock,
1442 PREV.rm_blockcount, PREV.rm_owner,
1443 PREV.rm_offset, PREV.rm_flags);
7faf209c
DW
1444 error = xfs_btree_delete(cur, &i);
1445 if (error)
1446 goto done;
fbb4fa7f 1447 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1448 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1449 error = -EFSCORRUPTED;
1450 goto done;
1451 }
7faf209c
DW
1452 error = xfs_btree_decrement(cur, 0, &i);
1453 if (error)
1454 goto done;
fbb4fa7f 1455 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1456 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1457 error = -EFSCORRUPTED;
1458 goto done;
1459 }
7faf209c
DW
1460 NEW = LEFT;
1461 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1462 error = xfs_rmap_update(cur, &NEW);
1463 if (error)
1464 goto done;
1465 break;
1466
1467 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1468 /*
1469 * Setting all of a previous oldext extent to newext.
1470 * The left neighbor is contiguous, the right is not.
1471 */
18c3bc7f
DW
1472 trace_xfs_rmap_delete(cur, PREV.rm_startblock,
1473 PREV.rm_blockcount, PREV.rm_owner,
1474 PREV.rm_offset, PREV.rm_flags);
7faf209c
DW
1475 error = xfs_btree_delete(cur, &i);
1476 if (error)
1477 goto done;
fbb4fa7f 1478 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1479 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1480 error = -EFSCORRUPTED;
1481 goto done;
1482 }
7faf209c
DW
1483 error = xfs_btree_decrement(cur, 0, &i);
1484 if (error)
1485 goto done;
fbb4fa7f 1486 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1487 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1488 error = -EFSCORRUPTED;
1489 goto done;
1490 }
7faf209c
DW
1491 NEW = LEFT;
1492 NEW.rm_blockcount += PREV.rm_blockcount;
1493 error = xfs_rmap_update(cur, &NEW);
1494 if (error)
1495 goto done;
1496 break;
1497
1498 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1499 /*
1500 * Setting all of a previous oldext extent to newext.
1501 * The right neighbor is contiguous, the left is not.
1502 */
1503 error = xfs_btree_increment(cur, 0, &i);
1504 if (error)
1505 goto done;
fbb4fa7f 1506 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1507 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1508 error = -EFSCORRUPTED;
1509 goto done;
1510 }
18c3bc7f
DW
1511 trace_xfs_rmap_delete(cur, RIGHT.rm_startblock,
1512 RIGHT.rm_blockcount, RIGHT.rm_owner,
1513 RIGHT.rm_offset, RIGHT.rm_flags);
7faf209c
DW
1514 error = xfs_btree_delete(cur, &i);
1515 if (error)
1516 goto done;
fbb4fa7f 1517 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1518 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1519 error = -EFSCORRUPTED;
1520 goto done;
1521 }
7faf209c
DW
1522 error = xfs_btree_decrement(cur, 0, &i);
1523 if (error)
1524 goto done;
fbb4fa7f 1525 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1526 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1527 error = -EFSCORRUPTED;
1528 goto done;
1529 }
7faf209c
DW
1530 NEW = PREV;
1531 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1532 NEW.rm_flags = newext;
1533 error = xfs_rmap_update(cur, &NEW);
1534 if (error)
1535 goto done;
1536 break;
1537
1538 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1539 /*
1540 * Setting all of a previous oldext extent to newext.
1541 * Neither the left nor right neighbors are contiguous with
1542 * the new one.
1543 */
1544 NEW = PREV;
1545 NEW.rm_flags = newext;
1546 error = xfs_rmap_update(cur, &NEW);
1547 if (error)
1548 goto done;
1549 break;
1550
1551 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1552 /*
1553 * Setting the first part of a previous oldext extent to newext.
1554 * The left neighbor is contiguous.
1555 */
1556 NEW = PREV;
1557 NEW.rm_offset += len;
1558 NEW.rm_startblock += len;
1559 NEW.rm_blockcount -= len;
1560 error = xfs_rmap_update(cur, &NEW);
1561 if (error)
1562 goto done;
1563 error = xfs_btree_decrement(cur, 0, &i);
1564 if (error)
1565 goto done;
1566 NEW = LEFT;
1567 NEW.rm_blockcount += len;
1568 error = xfs_rmap_update(cur, &NEW);
1569 if (error)
1570 goto done;
1571 break;
1572
1573 case RMAP_LEFT_FILLING:
1574 /*
1575 * Setting the first part of a previous oldext extent to newext.
1576 * The left neighbor is not contiguous.
1577 */
1578 NEW = PREV;
1579 NEW.rm_startblock += len;
1580 NEW.rm_offset += len;
1581 NEW.rm_blockcount -= len;
1582 error = xfs_rmap_update(cur, &NEW);
1583 if (error)
1584 goto done;
1585 NEW.rm_startblock = bno;
1586 NEW.rm_owner = owner;
1587 NEW.rm_offset = offset;
1588 NEW.rm_blockcount = len;
1589 NEW.rm_flags = newext;
1590 cur->bc_rec.r = NEW;
18c3bc7f 1591 trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
7faf209c
DW
1592 error = xfs_btree_insert(cur, &i);
1593 if (error)
1594 goto done;
fbb4fa7f 1595 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1596 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1597 error = -EFSCORRUPTED;
1598 goto done;
1599 }
7faf209c
DW
1600 break;
1601
1602 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1603 /*
1604 * Setting the last part of a previous oldext extent to newext.
1605 * The right neighbor is contiguous with the new allocation.
1606 */
1607 NEW = PREV;
1608 NEW.rm_blockcount -= len;
1609 error = xfs_rmap_update(cur, &NEW);
1610 if (error)
1611 goto done;
1612 error = xfs_btree_increment(cur, 0, &i);
1613 if (error)
1614 goto done;
1615 NEW = RIGHT;
1616 NEW.rm_offset = offset;
1617 NEW.rm_startblock = bno;
1618 NEW.rm_blockcount += len;
1619 error = xfs_rmap_update(cur, &NEW);
1620 if (error)
1621 goto done;
1622 break;
1623
1624 case RMAP_RIGHT_FILLING:
1625 /*
1626 * Setting the last part of a previous oldext extent to newext.
1627 * The right neighbor is not contiguous.
1628 */
1629 NEW = PREV;
1630 NEW.rm_blockcount -= len;
1631 error = xfs_rmap_update(cur, &NEW);
1632 if (error)
1633 goto done;
1634 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1635 oldext, &i);
1636 if (error)
1637 goto done;
fbb4fa7f 1638 if (XFS_IS_CORRUPT(mp, i != 0)) {
4467a60a 1639 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1640 error = -EFSCORRUPTED;
1641 goto done;
1642 }
7faf209c
DW
1643 NEW.rm_startblock = bno;
1644 NEW.rm_owner = owner;
1645 NEW.rm_offset = offset;
1646 NEW.rm_blockcount = len;
1647 NEW.rm_flags = newext;
1648 cur->bc_rec.r = NEW;
18c3bc7f 1649 trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
7faf209c
DW
1650 error = xfs_btree_insert(cur, &i);
1651 if (error)
1652 goto done;
fbb4fa7f 1653 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1654 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1655 error = -EFSCORRUPTED;
1656 goto done;
1657 }
7faf209c
DW
1658 break;
1659
1660 case 0:
1661 /*
1662 * Setting the middle part of a previous oldext extent to
1663 * newext. Contiguity is impossible here.
1664 * One extent becomes three extents.
1665 */
1666 /* new right extent - oldext */
1667 NEW.rm_startblock = bno + len;
1668 NEW.rm_owner = owner;
1669 NEW.rm_offset = new_endoff;
1670 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1671 new_endoff;
1672 NEW.rm_flags = PREV.rm_flags;
1673 error = xfs_rmap_update(cur, &NEW);
1674 if (error)
1675 goto done;
1676 /* new left extent - oldext */
1677 NEW = PREV;
1678 NEW.rm_blockcount = offset - PREV.rm_offset;
1679 cur->bc_rec.r = NEW;
18c3bc7f
DW
1680 trace_xfs_rmap_insert(cur, NEW.rm_startblock,
1681 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
7faf209c
DW
1682 NEW.rm_flags);
1683 error = xfs_btree_insert(cur, &i);
1684 if (error)
1685 goto done;
fbb4fa7f 1686 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1687 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1688 error = -EFSCORRUPTED;
1689 goto done;
1690 }
7faf209c
DW
1691 /*
1692 * Reset the cursor to the position of the new extent
1693 * we are about to insert as we can't trust it after
1694 * the previous insert.
1695 */
1696 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1697 oldext, &i);
1698 if (error)
1699 goto done;
fbb4fa7f 1700 if (XFS_IS_CORRUPT(mp, i != 0)) {
4467a60a 1701 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1702 error = -EFSCORRUPTED;
1703 goto done;
1704 }
7faf209c
DW
1705 /* new middle extent - newext */
1706 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1707 cur->bc_rec.r.rm_flags |= newext;
18c3bc7f 1708 trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
7faf209c
DW
1709 error = xfs_btree_insert(cur, &i);
1710 if (error)
1711 goto done;
fbb4fa7f 1712 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1713 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1714 error = -EFSCORRUPTED;
1715 goto done;
1716 }
7faf209c
DW
1717 break;
1718
1719 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1720 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1721 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1722 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1723 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1724 case RMAP_LEFT_CONTIG:
1725 case RMAP_RIGHT_CONTIG:
1726 /*
1727 * These cases are all impossible.
1728 */
1729 ASSERT(0);
1730 }
1731
18c3bc7f 1732 trace_xfs_rmap_convert_done(cur, bno, len, unwritten, oinfo);
7faf209c
DW
1733done:
1734 if (error)
ff6e47b3 1735 trace_xfs_rmap_convert_error(cur, error, _RET_IP_);
7faf209c
DW
1736 return error;
1737}
1738
9c7bc093
DW
1739/*
1740 * Convert an unwritten extent to a real extent or vice versa. If there is no
1741 * possibility of overlapping extents, delegate to the simpler convert
1742 * function.
1743 */
1744STATIC int
1745xfs_rmap_convert_shared(
5837e73b
DW
1746 struct xfs_btree_cur *cur,
1747 xfs_agblock_t bno,
1748 xfs_extlen_t len,
1749 bool unwritten,
1750 const struct xfs_owner_info *oinfo)
9c7bc093 1751{
5837e73b
DW
1752 struct xfs_mount *mp = cur->bc_mp;
1753 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1754 /* left is 0, right is 1, */
1755 /* prev is 2, new is 3 */
9c7bc093
DW
1756 uint64_t owner;
1757 uint64_t offset;
1758 uint64_t new_endoff;
1759 unsigned int oldext;
1760 unsigned int newext;
1761 unsigned int flags = 0;
1762 int i;
1763 int state = 0;
1764 int error;
1765
1766 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1767 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1768 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1769 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1770 new_endoff = offset + len;
18c3bc7f 1771 trace_xfs_rmap_convert(cur, bno, len, unwritten, oinfo);
9c7bc093
DW
1772
1773 /*
1774 * For the initial lookup, look for and exact match or the left-adjacent
1775 * record for our insertion point. This will also give us the record for
1776 * start block contiguity tests.
1777 */
4d1b7499 1778 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
9c7bc093 1779 &PREV, &i);
cfa7d896
DW
1780 if (error)
1781 goto done;
fbb4fa7f 1782 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1783 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1784 error = -EFSCORRUPTED;
1785 goto done;
1786 }
9c7bc093
DW
1787
1788 ASSERT(PREV.rm_offset <= offset);
1789 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1790 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1791 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1792
1793 /*
1794 * Set flags determining what part of the previous oldext allocation
1795 * extent is being replaced by a newext allocation.
1796 */
1797 if (PREV.rm_offset == offset)
1798 state |= RMAP_LEFT_FILLING;
1799 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1800 state |= RMAP_RIGHT_FILLING;
1801
1802 /* Is there a left record that abuts our range? */
1803 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1804 &LEFT, &i);
1805 if (error)
1806 goto done;
1807 if (i) {
1808 state |= RMAP_LEFT_VALID;
fbb4fa7f
DW
1809 if (XFS_IS_CORRUPT(mp,
1810 LEFT.rm_startblock + LEFT.rm_blockcount >
1811 bno)) {
4467a60a 1812 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1813 error = -EFSCORRUPTED;
1814 goto done;
1815 }
9c7bc093
DW
1816 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1817 state |= RMAP_LEFT_CONTIG;
1818 }
1819
1820 /* Is there a right record that abuts our range? */
1821 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1822 newext, &i);
1823 if (error)
1824 goto done;
1825 if (i) {
1826 state |= RMAP_RIGHT_VALID;
1827 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1828 if (error)
1829 goto done;
fbb4fa7f 1830 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1831 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1832 error = -EFSCORRUPTED;
1833 goto done;
1834 }
1835 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
4467a60a 1836 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1837 error = -EFSCORRUPTED;
1838 goto done;
1839 }
18c3bc7f
DW
1840 trace_xfs_rmap_find_right_neighbor_result(cur,
1841 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1842 RIGHT.rm_owner, RIGHT.rm_offset,
1843 RIGHT.rm_flags);
9c7bc093
DW
1844 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1845 state |= RMAP_RIGHT_CONTIG;
1846 }
1847
1848 /* check that left + prev + right is not too long */
1849 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1850 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1851 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1852 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1853 (unsigned long)LEFT.rm_blockcount + len +
1854 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1855 state &= ~RMAP_RIGHT_CONTIG;
1856
ff6e47b3 1857 trace_xfs_rmap_convert_state(cur, state, _RET_IP_);
9c7bc093
DW
1858 /*
1859 * Switch out based on the FILLING and CONTIG state bits.
1860 */
1861 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1862 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1863 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1864 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1865 /*
1866 * Setting all of a previous oldext extent to newext.
1867 * The left and right neighbors are both contiguous with new.
1868 */
1869 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1870 RIGHT.rm_blockcount, RIGHT.rm_owner,
1871 RIGHT.rm_offset, RIGHT.rm_flags);
1872 if (error)
1873 goto done;
1874 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1875 PREV.rm_blockcount, PREV.rm_owner,
1876 PREV.rm_offset, PREV.rm_flags);
1877 if (error)
1878 goto done;
1879 NEW = LEFT;
1880 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1881 NEW.rm_blockcount, NEW.rm_owner,
1882 NEW.rm_offset, NEW.rm_flags, &i);
1883 if (error)
1884 goto done;
fbb4fa7f 1885 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1886 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1887 error = -EFSCORRUPTED;
1888 goto done;
1889 }
9c7bc093
DW
1890 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1891 error = xfs_rmap_update(cur, &NEW);
1892 if (error)
1893 goto done;
1894 break;
1895
1896 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1897 /*
1898 * Setting all of a previous oldext extent to newext.
1899 * The left neighbor is contiguous, the right is not.
1900 */
1901 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1902 PREV.rm_blockcount, PREV.rm_owner,
1903 PREV.rm_offset, PREV.rm_flags);
1904 if (error)
1905 goto done;
1906 NEW = LEFT;
1907 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1908 NEW.rm_blockcount, NEW.rm_owner,
1909 NEW.rm_offset, NEW.rm_flags, &i);
1910 if (error)
1911 goto done;
fbb4fa7f 1912 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1913 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1914 error = -EFSCORRUPTED;
1915 goto done;
1916 }
9c7bc093
DW
1917 NEW.rm_blockcount += PREV.rm_blockcount;
1918 error = xfs_rmap_update(cur, &NEW);
1919 if (error)
1920 goto done;
1921 break;
1922
1923 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1924 /*
1925 * Setting all of a previous oldext extent to newext.
1926 * The right neighbor is contiguous, the left is not.
1927 */
1928 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1929 RIGHT.rm_blockcount, RIGHT.rm_owner,
1930 RIGHT.rm_offset, RIGHT.rm_flags);
1931 if (error)
1932 goto done;
1933 NEW = PREV;
1934 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1935 NEW.rm_blockcount, NEW.rm_owner,
1936 NEW.rm_offset, NEW.rm_flags, &i);
1937 if (error)
1938 goto done;
fbb4fa7f 1939 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1940 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1941 error = -EFSCORRUPTED;
1942 goto done;
1943 }
9c7bc093
DW
1944 NEW.rm_blockcount += RIGHT.rm_blockcount;
1945 NEW.rm_flags = RIGHT.rm_flags;
1946 error = xfs_rmap_update(cur, &NEW);
1947 if (error)
1948 goto done;
1949 break;
1950
1951 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1952 /*
1953 * Setting all of a previous oldext extent to newext.
1954 * Neither the left nor right neighbors are contiguous with
1955 * the new one.
1956 */
1957 NEW = PREV;
1958 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1959 NEW.rm_blockcount, NEW.rm_owner,
1960 NEW.rm_offset, NEW.rm_flags, &i);
1961 if (error)
1962 goto done;
fbb4fa7f 1963 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 1964 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
1965 error = -EFSCORRUPTED;
1966 goto done;
1967 }
9c7bc093
DW
1968 NEW.rm_flags = newext;
1969 error = xfs_rmap_update(cur, &NEW);
1970 if (error)
1971 goto done;
1972 break;
1973
1974 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1975 /*
1976 * Setting the first part of a previous oldext extent to newext.
1977 * The left neighbor is contiguous.
1978 */
1979 NEW = PREV;
1980 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1981 NEW.rm_blockcount, NEW.rm_owner,
1982 NEW.rm_offset, NEW.rm_flags);
1983 if (error)
1984 goto done;
1985 NEW.rm_offset += len;
1986 NEW.rm_startblock += len;
1987 NEW.rm_blockcount -= len;
1988 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1989 NEW.rm_blockcount, NEW.rm_owner,
1990 NEW.rm_offset, NEW.rm_flags);
1991 if (error)
1992 goto done;
1993 NEW = LEFT;
1994 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1995 NEW.rm_blockcount, NEW.rm_owner,
1996 NEW.rm_offset, NEW.rm_flags, &i);
1997 if (error)
1998 goto done;
fbb4fa7f 1999 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2000 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2001 error = -EFSCORRUPTED;
2002 goto done;
2003 }
9c7bc093
DW
2004 NEW.rm_blockcount += len;
2005 error = xfs_rmap_update(cur, &NEW);
2006 if (error)
2007 goto done;
2008 break;
2009
2010 case RMAP_LEFT_FILLING:
2011 /*
2012 * Setting the first part of a previous oldext extent to newext.
2013 * The left neighbor is not contiguous.
2014 */
2015 NEW = PREV;
2016 error = xfs_rmap_delete(cur, NEW.rm_startblock,
2017 NEW.rm_blockcount, NEW.rm_owner,
2018 NEW.rm_offset, NEW.rm_flags);
2019 if (error)
2020 goto done;
2021 NEW.rm_offset += len;
2022 NEW.rm_startblock += len;
2023 NEW.rm_blockcount -= len;
2024 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2025 NEW.rm_blockcount, NEW.rm_owner,
2026 NEW.rm_offset, NEW.rm_flags);
2027 if (error)
2028 goto done;
2029 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
2030 if (error)
2031 goto done;
2032 break;
2033
2034 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
2035 /*
2036 * Setting the last part of a previous oldext extent to newext.
2037 * The right neighbor is contiguous with the new allocation.
2038 */
2039 NEW = PREV;
2040 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2041 NEW.rm_blockcount, NEW.rm_owner,
2042 NEW.rm_offset, NEW.rm_flags, &i);
2043 if (error)
2044 goto done;
fbb4fa7f 2045 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2046 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2047 error = -EFSCORRUPTED;
2048 goto done;
2049 }
9c7bc093
DW
2050 NEW.rm_blockcount = offset - NEW.rm_offset;
2051 error = xfs_rmap_update(cur, &NEW);
2052 if (error)
2053 goto done;
2054 NEW = RIGHT;
2055 error = xfs_rmap_delete(cur, NEW.rm_startblock,
2056 NEW.rm_blockcount, NEW.rm_owner,
2057 NEW.rm_offset, NEW.rm_flags);
2058 if (error)
2059 goto done;
2060 NEW.rm_offset = offset;
2061 NEW.rm_startblock = bno;
2062 NEW.rm_blockcount += len;
2063 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2064 NEW.rm_blockcount, NEW.rm_owner,
2065 NEW.rm_offset, NEW.rm_flags);
2066 if (error)
2067 goto done;
2068 break;
2069
2070 case RMAP_RIGHT_FILLING:
2071 /*
2072 * Setting the last part of a previous oldext extent to newext.
2073 * The right neighbor is not contiguous.
2074 */
2075 NEW = PREV;
2076 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2077 NEW.rm_blockcount, NEW.rm_owner,
2078 NEW.rm_offset, NEW.rm_flags, &i);
2079 if (error)
2080 goto done;
fbb4fa7f 2081 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2082 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2083 error = -EFSCORRUPTED;
2084 goto done;
2085 }
9c7bc093
DW
2086 NEW.rm_blockcount -= len;
2087 error = xfs_rmap_update(cur, &NEW);
2088 if (error)
2089 goto done;
2090 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
2091 if (error)
2092 goto done;
2093 break;
2094
2095 case 0:
2096 /*
2097 * Setting the middle part of a previous oldext extent to
2098 * newext. Contiguity is impossible here.
2099 * One extent becomes three extents.
2100 */
2101 /* new right extent - oldext */
2102 NEW.rm_startblock = bno + len;
2103 NEW.rm_owner = owner;
2104 NEW.rm_offset = new_endoff;
2105 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
2106 new_endoff;
2107 NEW.rm_flags = PREV.rm_flags;
2108 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2109 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
2110 NEW.rm_flags);
2111 if (error)
2112 goto done;
2113 /* new left extent - oldext */
2114 NEW = PREV;
2115 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2116 NEW.rm_blockcount, NEW.rm_owner,
2117 NEW.rm_offset, NEW.rm_flags, &i);
2118 if (error)
2119 goto done;
fbb4fa7f 2120 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2121 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2122 error = -EFSCORRUPTED;
2123 goto done;
2124 }
9c7bc093
DW
2125 NEW.rm_blockcount = offset - NEW.rm_offset;
2126 error = xfs_rmap_update(cur, &NEW);
2127 if (error)
2128 goto done;
2129 /* new middle extent - newext */
2130 NEW.rm_startblock = bno;
2131 NEW.rm_blockcount = len;
2132 NEW.rm_owner = owner;
2133 NEW.rm_offset = offset;
2134 NEW.rm_flags = newext;
2135 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2136 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
2137 NEW.rm_flags);
2138 if (error)
2139 goto done;
2140 break;
2141
2142 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2143 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2144 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
2145 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
2146 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2147 case RMAP_LEFT_CONTIG:
2148 case RMAP_RIGHT_CONTIG:
2149 /*
2150 * These cases are all impossible.
2151 */
2152 ASSERT(0);
2153 }
2154
18c3bc7f 2155 trace_xfs_rmap_convert_done(cur, bno, len, unwritten, oinfo);
9c7bc093
DW
2156done:
2157 if (error)
ff6e47b3 2158 trace_xfs_rmap_convert_error(cur, error, _RET_IP_);
9c7bc093
DW
2159 return error;
2160}
2161
7faf209c
DW
2162#undef NEW
2163#undef LEFT
2164#undef RIGHT
2165#undef PREV
2166
6c6bdf6f
DW
2167/*
2168 * Find an extent in the rmap btree and unmap it. For rmap extent types that
2169 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2170 * that the prev/next records in the btree might belong to another owner.
2171 * Therefore we must use delete+insert to alter any of the key fields.
2172 *
2173 * For every other situation there can only be one owner for a given extent,
2174 * so we can call the regular _free function.
2175 */
2176STATIC int
2177xfs_rmap_unmap_shared(
5837e73b
DW
2178 struct xfs_btree_cur *cur,
2179 xfs_agblock_t bno,
2180 xfs_extlen_t len,
2181 bool unwritten,
2182 const struct xfs_owner_info *oinfo)
6c6bdf6f 2183{
5837e73b
DW
2184 struct xfs_mount *mp = cur->bc_mp;
2185 struct xfs_rmap_irec ltrec;
2186 uint64_t ltoff;
2187 int error = 0;
2188 int i;
2189 uint64_t owner;
2190 uint64_t offset;
2191 unsigned int flags;
6c6bdf6f
DW
2192
2193 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2194 if (unwritten)
2195 flags |= XFS_RMAP_UNWRITTEN;
18c3bc7f 2196 trace_xfs_rmap_unmap(cur, bno, len, unwritten, oinfo);
6c6bdf6f
DW
2197
2198 /*
2199 * We should always have a left record because there's a static record
2200 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2201 * will not ever be removed from the tree.
2202 */
2203 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2204 &ltrec, &i);
2205 if (error)
2206 goto out_error;
fbb4fa7f 2207 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2208 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2209 error = -EFSCORRUPTED;
2210 goto out_error;
2211 }
6c6bdf6f
DW
2212 ltoff = ltrec.rm_offset;
2213
2214 /* Make sure the extent we found covers the entire freeing range. */
fbb4fa7f
DW
2215 if (XFS_IS_CORRUPT(mp,
2216 ltrec.rm_startblock > bno ||
2217 ltrec.rm_startblock + ltrec.rm_blockcount <
2218 bno + len)) {
4467a60a 2219 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2220 error = -EFSCORRUPTED;
2221 goto out_error;
2222 }
6c6bdf6f
DW
2223
2224 /* Make sure the owner matches what we expect to find in the tree. */
fbb4fa7f 2225 if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
4467a60a 2226 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2227 error = -EFSCORRUPTED;
2228 goto out_error;
2229 }
6c6bdf6f
DW
2230
2231 /* Make sure the unwritten flag matches. */
fbb4fa7f
DW
2232 if (XFS_IS_CORRUPT(mp,
2233 (flags & XFS_RMAP_UNWRITTEN) !=
2234 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
4467a60a 2235 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2236 error = -EFSCORRUPTED;
2237 goto out_error;
2238 }
6c6bdf6f
DW
2239
2240 /* Check the offset. */
fbb4fa7f 2241 if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
4467a60a 2242 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2243 error = -EFSCORRUPTED;
2244 goto out_error;
2245 }
2246 if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
4467a60a 2247 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2248 error = -EFSCORRUPTED;
2249 goto out_error;
2250 }
6c6bdf6f
DW
2251
2252 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2253 /* Exact match, simply remove the record from rmap tree. */
2254 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2255 ltrec.rm_blockcount, ltrec.rm_owner,
2256 ltrec.rm_offset, ltrec.rm_flags);
2257 if (error)
2258 goto out_error;
2259 } else if (ltrec.rm_startblock == bno) {
2260 /*
2261 * Overlap left hand side of extent: move the start, trim the
2262 * length and update the current record.
2263 *
2264 * ltbno ltlen
2265 * Orig: |oooooooooooooooooooo|
2266 * Freeing: |fffffffff|
2267 * Result: |rrrrrrrrrr|
2268 * bno len
2269 */
2270
2271 /* Delete prev rmap. */
2272 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2273 ltrec.rm_blockcount, ltrec.rm_owner,
2274 ltrec.rm_offset, ltrec.rm_flags);
2275 if (error)
2276 goto out_error;
2277
2278 /* Add an rmap at the new offset. */
2279 ltrec.rm_startblock += len;
2280 ltrec.rm_blockcount -= len;
2281 ltrec.rm_offset += len;
2282 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2283 ltrec.rm_blockcount, ltrec.rm_owner,
2284 ltrec.rm_offset, ltrec.rm_flags);
2285 if (error)
2286 goto out_error;
2287 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2288 /*
2289 * Overlap right hand side of extent: trim the length and
2290 * update the current record.
2291 *
2292 * ltbno ltlen
2293 * Orig: |oooooooooooooooooooo|
2294 * Freeing: |fffffffff|
2295 * Result: |rrrrrrrrrr|
2296 * bno len
2297 */
2298 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2299 ltrec.rm_blockcount, ltrec.rm_owner,
2300 ltrec.rm_offset, ltrec.rm_flags, &i);
2301 if (error)
2302 goto out_error;
fbb4fa7f 2303 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2304 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2305 error = -EFSCORRUPTED;
2306 goto out_error;
2307 }
6c6bdf6f
DW
2308 ltrec.rm_blockcount -= len;
2309 error = xfs_rmap_update(cur, &ltrec);
2310 if (error)
2311 goto out_error;
2312 } else {
2313 /*
2314 * Overlap middle of extent: trim the length of the existing
2315 * record to the length of the new left-extent size, increment
2316 * the insertion position so we can insert a new record
2317 * containing the remaining right-extent space.
2318 *
2319 * ltbno ltlen
2320 * Orig: |oooooooooooooooooooo|
2321 * Freeing: |fffffffff|
2322 * Result: |rrrrr| |rrrr|
2323 * bno len
2324 */
2325 xfs_extlen_t orig_len = ltrec.rm_blockcount;
2326
2327 /* Shrink the left side of the rmap */
2328 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2329 ltrec.rm_blockcount, ltrec.rm_owner,
2330 ltrec.rm_offset, ltrec.rm_flags, &i);
2331 if (error)
2332 goto out_error;
fbb4fa7f 2333 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2334 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2335 error = -EFSCORRUPTED;
2336 goto out_error;
2337 }
6c6bdf6f
DW
2338 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2339 error = xfs_rmap_update(cur, &ltrec);
2340 if (error)
2341 goto out_error;
2342
2343 /* Add an rmap at the new offset */
2344 error = xfs_rmap_insert(cur, bno + len,
2345 orig_len - len - ltrec.rm_blockcount,
2346 ltrec.rm_owner, offset + len,
2347 ltrec.rm_flags);
2348 if (error)
2349 goto out_error;
2350 }
2351
18c3bc7f 2352 trace_xfs_rmap_unmap_done(cur, bno, len, unwritten, oinfo);
6c6bdf6f
DW
2353out_error:
2354 if (error)
ff6e47b3 2355 trace_xfs_rmap_unmap_error(cur, error, _RET_IP_);
6c6bdf6f
DW
2356 return error;
2357}
2358
2359/*
2360 * Find an extent in the rmap btree and map it. For rmap extent types that
2361 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2362 * that the prev/next records in the btree might belong to another owner.
2363 * Therefore we must use delete+insert to alter any of the key fields.
2364 *
2365 * For every other situation there can only be one owner for a given extent,
2366 * so we can call the regular _alloc function.
2367 */
2368STATIC int
2369xfs_rmap_map_shared(
5837e73b
DW
2370 struct xfs_btree_cur *cur,
2371 xfs_agblock_t bno,
2372 xfs_extlen_t len,
2373 bool unwritten,
2374 const struct xfs_owner_info *oinfo)
6c6bdf6f 2375{
5837e73b
DW
2376 struct xfs_mount *mp = cur->bc_mp;
2377 struct xfs_rmap_irec ltrec;
2378 struct xfs_rmap_irec gtrec;
2379 int have_gt;
2380 int have_lt;
2381 int error = 0;
2382 int i;
2383 uint64_t owner;
2384 uint64_t offset;
2385 unsigned int flags = 0;
6c6bdf6f
DW
2386
2387 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2388 if (unwritten)
2389 flags |= XFS_RMAP_UNWRITTEN;
18c3bc7f 2390 trace_xfs_rmap_map(cur, bno, len, unwritten, oinfo);
6c6bdf6f
DW
2391
2392 /* Is there a left record that abuts our range? */
2393 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2394 &ltrec, &have_lt);
2395 if (error)
2396 goto out_error;
2397 if (have_lt &&
2398 !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2399 have_lt = 0;
2400
2401 /* Is there a right record that abuts our range? */
2402 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2403 flags, &have_gt);
2404 if (error)
2405 goto out_error;
2406 if (have_gt) {
2407 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2408 if (error)
2409 goto out_error;
fbb4fa7f 2410 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
4467a60a 2411 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2412 error = -EFSCORRUPTED;
2413 goto out_error;
2414 }
18c3bc7f
DW
2415 trace_xfs_rmap_find_right_neighbor_result(cur,
2416 gtrec.rm_startblock, gtrec.rm_blockcount,
2417 gtrec.rm_owner, gtrec.rm_offset,
2418 gtrec.rm_flags);
6c6bdf6f
DW
2419
2420 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2421 have_gt = 0;
2422 }
2423
2424 if (have_lt &&
2425 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2426 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2427 /*
2428 * Left edge contiguous, merge into left record.
2429 *
2430 * ltbno ltlen
2431 * orig: |ooooooooo|
2432 * adding: |aaaaaaaaa|
2433 * result: |rrrrrrrrrrrrrrrrrrr|
2434 * bno len
2435 */
2436 ltrec.rm_blockcount += len;
2437 if (have_gt &&
2438 bno + len == gtrec.rm_startblock &&
2439 offset + len == gtrec.rm_offset) {
2440 /*
2441 * Right edge also contiguous, delete right record
2442 * and merge into left record.
2443 *
2444 * ltbno ltlen gtbno gtlen
2445 * orig: |ooooooooo| |ooooooooo|
2446 * adding: |aaaaaaaaa|
2447 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2448 */
2449 ltrec.rm_blockcount += gtrec.rm_blockcount;
2450 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2451 gtrec.rm_blockcount, gtrec.rm_owner,
2452 gtrec.rm_offset, gtrec.rm_flags);
2453 if (error)
2454 goto out_error;
2455 }
2456
2457 /* Point the cursor back to the left record and update. */
2458 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2459 ltrec.rm_blockcount, ltrec.rm_owner,
2460 ltrec.rm_offset, ltrec.rm_flags, &i);
2461 if (error)
2462 goto out_error;
fbb4fa7f 2463 if (XFS_IS_CORRUPT(mp, i != 1)) {
4467a60a 2464 xfs_btree_mark_sick(cur);
fbb4fa7f
DW
2465 error = -EFSCORRUPTED;
2466 goto out_error;
2467 }
6c6bdf6f
DW
2468
2469 error = xfs_rmap_update(cur, &ltrec);
2470 if (error)
2471 goto out_error;
2472 } else if (have_gt &&
2473 bno + len == gtrec.rm_startblock &&
2474 offset + len == gtrec.rm_offset) {
2475 /*
2476 * Right edge contiguous, merge into right record.
2477 *
2478 * gtbno gtlen
2479 * Orig: |ooooooooo|
2480 * adding: |aaaaaaaaa|
2481 * Result: |rrrrrrrrrrrrrrrrrrr|
2482 * bno len
2483 */
2484 /* Delete the old record. */
2485 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2486 gtrec.rm_blockcount, gtrec.rm_owner,
2487 gtrec.rm_offset, gtrec.rm_flags);
2488 if (error)
2489 goto out_error;
2490
2491 /* Move the start and re-add it. */
2492 gtrec.rm_startblock = bno;
2493 gtrec.rm_blockcount += len;
2494 gtrec.rm_offset = offset;
2495 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2496 gtrec.rm_blockcount, gtrec.rm_owner,
2497 gtrec.rm_offset, gtrec.rm_flags);
2498 if (error)
2499 goto out_error;
2500 } else {
2501 /*
2502 * No contiguous edge with identical owner, insert
2503 * new record at current cursor position.
2504 */
2505 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2506 if (error)
2507 goto out_error;
2508 }
2509
18c3bc7f 2510 trace_xfs_rmap_map_done(cur, bno, len, unwritten, oinfo);
6c6bdf6f
DW
2511out_error:
2512 if (error)
ff6e47b3 2513 trace_xfs_rmap_map_error(cur, error, _RET_IP_);
6c6bdf6f
DW
2514 return error;
2515}
2516
d264e392
DW
2517/* Insert a raw rmap into the rmapbt. */
2518int
2519xfs_rmap_map_raw(
2520 struct xfs_btree_cur *cur,
2521 struct xfs_rmap_irec *rmap)
2522{
2523 struct xfs_owner_info oinfo;
2524
9ff7cce7
DW
2525 xfs_owner_info_pack(&oinfo, rmap->rm_owner, rmap->rm_offset,
2526 rmap->rm_flags);
d264e392 2527
9ff7cce7
DW
2528 if ((rmap->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
2529 XFS_RMAP_UNWRITTEN)) ||
2530 XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
d264e392
DW
2531 return xfs_rmap_map(cur, rmap->rm_startblock,
2532 rmap->rm_blockcount,
2533 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2534 &oinfo);
2535
2536 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2537 rmap->rm_blockcount,
2538 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2539 &oinfo);
2540}
2541
890e1174
DW
2542struct xfs_rmap_query_range_info {
2543 xfs_rmap_query_range_fn fn;
2544 void *priv;
2545};
2546
2547/* Format btree record and pass to our callback. */
2548STATIC int
2549xfs_rmap_query_range_helper(
e62318a3
DW
2550 struct xfs_btree_cur *cur,
2551 const union xfs_btree_rec *rec,
2552 void *priv)
890e1174
DW
2553{
2554 struct xfs_rmap_query_range_info *query = priv;
2555 struct xfs_rmap_irec irec;
e70bf9ba 2556 xfs_failaddr_t fa;
890e1174 2557
e70bf9ba
DW
2558 fa = xfs_rmap_btrec_to_irec(rec, &irec);
2559 if (!fa)
9ff7cce7 2560 fa = xfs_rmap_check_btrec(cur, &irec);
e70bf9ba
DW
2561 if (fa)
2562 return xfs_rmap_complain_bad_rec(cur, fa, &irec);
8d444a7a 2563
890e1174
DW
2564 return query->fn(cur, &irec, query->priv);
2565}
2566
2567/* Find all rmaps between two keys. */
2568int
2569xfs_rmap_query_range(
7e05e856 2570 struct xfs_btree_cur *cur,
d34c6373
DW
2571 const struct xfs_rmap_irec *low_rec,
2572 const struct xfs_rmap_irec *high_rec,
7e05e856
DW
2573 xfs_rmap_query_range_fn fn,
2574 void *priv)
890e1174 2575{
05dcea07
DW
2576 union xfs_btree_irec low_brec = { .r = *low_rec };
2577 union xfs_btree_irec high_brec = { .r = *high_rec };
2578 struct xfs_rmap_query_range_info query = { .priv = priv, .fn = fn };
890e1174 2579
890e1174
DW
2580 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2581 xfs_rmap_query_range_helper, &query);
2582}
d7f80320 2583
7e05e856
DW
2584/* Find all rmaps. */
2585int
2586xfs_rmap_query_all(
2587 struct xfs_btree_cur *cur,
2588 xfs_rmap_query_range_fn fn,
2589 void *priv)
2590{
2591 struct xfs_rmap_query_range_info query;
2592
2593 query.priv = priv;
2594 query.fn = fn;
2595 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2596}
2597
a2fd18b4
DW
2598/* Commit an rmap operation into the ondisk tree. */
2599int
2600__xfs_rmap_finish_intent(
2601 struct xfs_btree_cur *rcur,
2602 enum xfs_rmap_intent_type op,
2603 xfs_agblock_t bno,
2604 xfs_extlen_t len,
2605 const struct xfs_owner_info *oinfo,
2606 bool unwritten)
2607{
2608 switch (op) {
2609 case XFS_RMAP_ALLOC:
2610 case XFS_RMAP_MAP:
2611 return xfs_rmap_map(rcur, bno, len, unwritten, oinfo);
2612 case XFS_RMAP_MAP_SHARED:
2613 return xfs_rmap_map_shared(rcur, bno, len, unwritten, oinfo);
2614 case XFS_RMAP_FREE:
2615 case XFS_RMAP_UNMAP:
2616 return xfs_rmap_unmap(rcur, bno, len, unwritten, oinfo);
2617 case XFS_RMAP_UNMAP_SHARED:
2618 return xfs_rmap_unmap_shared(rcur, bno, len, unwritten, oinfo);
2619 case XFS_RMAP_CONVERT:
2620 return xfs_rmap_convert(rcur, bno, len, !unwritten, oinfo);
2621 case XFS_RMAP_CONVERT_SHARED:
2622 return xfs_rmap_convert_shared(rcur, bno, len, !unwritten,
2623 oinfo);
2624 default:
2625 ASSERT(0);
2626 return -EFSCORRUPTED;
2627 }
2628}
2629
5cc11f59
DW
2630static int
2631xfs_rmap_finish_init_cursor(
2632 struct xfs_trans *tp,
2633 struct xfs_rmap_intent *ri,
2634 struct xfs_btree_cur **pcur)
2635{
2636 struct xfs_perag *pag = to_perag(ri->ri_group);
2637 struct xfs_buf *agbp = NULL;
2638 int error;
2639
2640 /*
2641 * Refresh the freelist before we start changing the rmapbt, because a
2642 * shape change could cause us to allocate blocks.
2643 */
2644 error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
2645 if (error) {
2646 xfs_ag_mark_sick(pag, XFS_SICK_AG_AGFL);
2647 return error;
2648 }
2649 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2650 xfs_ag_mark_sick(pag, XFS_SICK_AG_AGFL);
2651 return -EFSCORRUPTED;
2652 }
2653 *pcur = xfs_rmapbt_init_cursor(tp->t_mountp, tp, agbp, pag);
2654 return 0;
2655}
2656
2657static int
2658xfs_rtrmap_finish_init_cursor(
2659 struct xfs_trans *tp,
2660 struct xfs_rmap_intent *ri,
2661 struct xfs_btree_cur **pcur)
2662{
2663 struct xfs_rtgroup *rtg = to_rtg(ri->ri_group);
2664
2665 xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
2666 xfs_rtgroup_trans_join(tp, rtg, XFS_RTGLOCK_RMAP);
2667 *pcur = xfs_rtrmapbt_init_cursor(tp, rtg);
2668 return 0;
2669}
2670
d7f80320
DW
2671/*
2672 * Process one of the deferred rmap operations. We pass back the
2673 * btree cursor to maintain our lock on the rmapbt between calls.
2674 * This saves time and eliminates a buffer deadlock between the
2675 * superblock and the AGF because we'll always grab them in the same
2676 * order.
2677 */
2678int
2679xfs_rmap_finish_one(
2680 struct xfs_trans *tp,
74492d88 2681 struct xfs_rmap_intent *ri,
d7f80320
DW
2682 struct xfs_btree_cur **pcur)
2683{
0e95442e 2684 struct xfs_owner_info oinfo;
d7f80320 2685 struct xfs_mount *mp = tp->t_mountp;
d7f80320
DW
2686 xfs_agblock_t bno;
2687 bool unwritten;
0e95442e 2688 int error = 0;
d7f80320 2689
0e95442e 2690 trace_xfs_rmap_deferred(mp, ri);
d7f80320 2691
818f0c29
DW
2692 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
2693 return -EIO;
d7f80320
DW
2694
2695 /*
2696 * If we haven't gotten a cursor or the cursor AG doesn't match
2697 * the startblock, get one now.
2698 */
5cc11f59
DW
2699 if (*pcur != NULL && (*pcur)->bc_group != ri->ri_group) {
2700 xfs_btree_del_cursor(*pcur, 0);
d7f80320
DW
2701 *pcur = NULL;
2702 }
5cc11f59
DW
2703 if (*pcur == NULL) {
2704 if (ri->ri_group->xg_type == XG_TYPE_RTG)
2705 error = xfs_rtrmap_finish_init_cursor(tp, ri, pcur);
2706 else
2707 error = xfs_rmap_finish_init_cursor(tp, ri, pcur);
2708 if (error)
818f0c29 2709 return error;
d7f80320 2710 }
d7f80320 2711
74492d88
DW
2712 xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
2713 ri->ri_bmap.br_startoff);
2714 unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
d7f80320 2715
5cc11f59
DW
2716 bno = xfs_fsb_to_gbno(mp, ri->ri_bmap.br_startblock,
2717 ri->ri_group->xg_type);
2718 error = __xfs_rmap_finish_intent(*pcur, ri->ri_type, bno,
a2fd18b4
DW
2719 ri->ri_bmap.br_blockcount, &oinfo, unwritten);
2720 if (error)
2721 return error;
818f0c29 2722
0cf510a9
CH
2723 xfs_rmap_update_hook(tp, ri->ri_group, ri->ri_type, bno,
2724 ri->ri_bmap.br_blockcount, unwritten, &oinfo);
a2fd18b4 2725 return 0;
d7f80320
DW
2726}
2727
2728/*
2729 * Don't defer an rmap if we aren't an rmap filesystem.
2730 */
2731static bool
2732xfs_rmap_update_is_needed(
cb8a004a
DW
2733 struct xfs_mount *mp,
2734 int whichfork)
d7f80320 2735{
b16a427a 2736 return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
d7f80320
DW
2737}
2738
2739/*
2740 * Record a rmap intent; the list is kept sorted first by AG and then by
2741 * increasing age.
2742 */
46d29bb9 2743static void
d7f80320 2744__xfs_rmap_add(
21375e5d 2745 struct xfs_trans *tp,
d7f80320 2746 enum xfs_rmap_intent_type type,
4a492e72 2747 uint64_t owner,
bb8f58e8 2748 bool isrt,
d7f80320
DW
2749 int whichfork,
2750 struct xfs_bmbt_irec *bmap)
2751{
21375e5d 2752 struct xfs_rmap_intent *ri;
d7f80320 2753
a6cb3f66 2754 ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);
d7f80320
DW
2755 INIT_LIST_HEAD(&ri->ri_list);
2756 ri->ri_type = type;
2757 ri->ri_owner = owner;
2758 ri->ri_whichfork = whichfork;
2759 ri->ri_bmap = *bmap;
bb8f58e8 2760 ri->ri_realtime = isrt;
d7f80320 2761
f8a9e37d 2762 xfs_rmap_defer_add(tp, ri);
d7f80320
DW
2763}
2764
2765/* Map an extent into a file. */
46d29bb9 2766void
d7f80320 2767xfs_rmap_map_extent(
21375e5d 2768 struct xfs_trans *tp,
d7f80320
DW
2769 struct xfs_inode *ip,
2770 int whichfork,
2771 struct xfs_bmbt_irec *PREV)
2772{
171bead5 2773 enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
bb8f58e8 2774 bool isrt = xfs_ifork_is_realtime(ip, whichfork);
171bead5 2775
21375e5d 2776 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
46d29bb9 2777 return;
d7f80320 2778
171bead5
DW
2779 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2780 type = XFS_RMAP_MAP_SHARED;
2781
bb8f58e8 2782 __xfs_rmap_add(tp, type, ip->i_ino, isrt, whichfork, PREV);
d7f80320
DW
2783}
2784
2785/* Unmap an extent out of a file. */
46d29bb9 2786void
d7f80320 2787xfs_rmap_unmap_extent(
21375e5d 2788 struct xfs_trans *tp,
d7f80320
DW
2789 struct xfs_inode *ip,
2790 int whichfork,
2791 struct xfs_bmbt_irec *PREV)
2792{
171bead5 2793 enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
bb8f58e8 2794 bool isrt = xfs_ifork_is_realtime(ip, whichfork);
171bead5 2795
21375e5d 2796 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
46d29bb9 2797 return;
d7f80320 2798
171bead5
DW
2799 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2800 type = XFS_RMAP_UNMAP_SHARED;
2801
bb8f58e8 2802 __xfs_rmap_add(tp, type, ip->i_ino, isrt, whichfork, PREV);
d7f80320
DW
2803}
2804
21375e5d
BF
2805/*
2806 * Convert a data fork extent from unwritten to real or vice versa.
2807 *
2808 * Note that tp can be NULL here as no transaction is used for COW fork
2809 * unwritten conversion.
2810 */
46d29bb9 2811void
d7f80320
DW
2812xfs_rmap_convert_extent(
2813 struct xfs_mount *mp,
21375e5d 2814 struct xfs_trans *tp,
d7f80320
DW
2815 struct xfs_inode *ip,
2816 int whichfork,
2817 struct xfs_bmbt_irec *PREV)
2818{
171bead5 2819 enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
bb8f58e8 2820 bool isrt = xfs_ifork_is_realtime(ip, whichfork);
171bead5 2821
cb8a004a 2822 if (!xfs_rmap_update_is_needed(mp, whichfork))
46d29bb9 2823 return;
d7f80320 2824
171bead5
DW
2825 if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2826 type = XFS_RMAP_CONVERT_SHARED;
2827
bb8f58e8 2828 __xfs_rmap_add(tp, type, ip->i_ino, isrt, whichfork, PREV);
d7f80320
DW
2829}
2830
2831/* Schedule the creation of an rmap for non-file data. */
46d29bb9 2832void
d7f80320 2833xfs_rmap_alloc_extent(
21375e5d 2834 struct xfs_trans *tp,
bb8f58e8 2835 bool isrt,
cf20a9c6 2836 xfs_fsblock_t fsbno,
d7f80320 2837 xfs_extlen_t len,
4a492e72 2838 uint64_t owner)
d7f80320
DW
2839{
2840 struct xfs_bmbt_irec bmap;
2841
21375e5d 2842 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
46d29bb9 2843 return;
d7f80320 2844
cf20a9c6 2845 bmap.br_startblock = fsbno;
d7f80320
DW
2846 bmap.br_blockcount = len;
2847 bmap.br_startoff = 0;
2848 bmap.br_state = XFS_EXT_NORM;
2849
bb8f58e8 2850 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, isrt, XFS_DATA_FORK, &bmap);
d7f80320
DW
2851}
2852
2853/* Schedule the deletion of an rmap for non-file data. */
46d29bb9 2854void
d7f80320 2855xfs_rmap_free_extent(
21375e5d 2856 struct xfs_trans *tp,
bb8f58e8 2857 bool isrt,
cf20a9c6 2858 xfs_fsblock_t fsbno,
d7f80320 2859 xfs_extlen_t len,
4a492e72 2860 uint64_t owner)
d7f80320
DW
2861{
2862 struct xfs_bmbt_irec bmap;
2863
21375e5d 2864 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
46d29bb9 2865 return;
d7f80320 2866
cf20a9c6 2867 bmap.br_startblock = fsbno;
d7f80320
DW
2868 bmap.br_blockcount = len;
2869 bmap.br_startoff = 0;
2870 bmap.br_state = XFS_EXT_NORM;
2871
bb8f58e8 2872 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, isrt, XFS_DATA_FORK, &bmap);
d7f80320 2873}
9282c506
DW
2874
2875/* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2876int
2877xfs_rmap_compare(
2878 const struct xfs_rmap_irec *a,
2879 const struct xfs_rmap_irec *b)
2880{
2881 __u64 oa;
2882 __u64 ob;
2883
2884 oa = xfs_rmap_irec_offset_pack(a);
2885 ob = xfs_rmap_irec_offset_pack(b);
2886
2887 if (a->rm_startblock < b->rm_startblock)
2888 return -1;
2889 else if (a->rm_startblock > b->rm_startblock)
2890 return 1;
2891 else if (a->rm_owner < b->rm_owner)
2892 return -1;
2893 else if (a->rm_owner > b->rm_owner)
2894 return 1;
2895 else if (oa < ob)
2896 return -1;
2897 else if (oa > ob)
2898 return 1;
2899 else
2900 return 0;
2901}
556c739d 2902
9ba4dc82
DW
2903/*
2904 * Scan the physical storage part of the keyspace of the reverse mapping index
2905 * and tell us if the area has no records, is fully mapped by records, or is
2906 * partially filled.
2907 */
556c739d 2908int
9ba4dc82 2909xfs_rmap_has_records(
556c739d
DW
2910 struct xfs_btree_cur *cur,
2911 xfs_agblock_t bno,
2912 xfs_extlen_t len,
9ba4dc82 2913 enum xbtree_recpacking *outcome)
556c739d 2914{
d99b8900
DW
2915 union xfs_btree_key mask = {
2916 .rmap.rm_startblock = cpu_to_be32(-1U),
2917 };
556c739d
DW
2918 union xfs_btree_irec low;
2919 union xfs_btree_irec high;
2920
2921 memset(&low, 0, sizeof(low));
2922 low.r.rm_startblock = bno;
2923 memset(&high, 0xFF, sizeof(high));
2924 high.r.rm_startblock = bno + len - 1;
2925
d99b8900 2926 return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
556c739d
DW
2927}
2928
54644f25
DW
2929struct xfs_rmap_ownercount {
2930 /* Owner that we're looking for. */
2931 struct xfs_rmap_irec good;
2932
2933 /* rmap search keys */
2934 struct xfs_rmap_irec low;
2935 struct xfs_rmap_irec high;
2936
2937 struct xfs_rmap_matches *results;
2938
2939 /* Stop early if we find a nonmatch? */
2940 bool stop_on_nonmatch;
2941};
2942
2943/* Does this rmap represent space that can have multiple owners? */
2944static inline bool
2945xfs_rmap_shareable(
2946 struct xfs_mount *mp,
2947 const struct xfs_rmap_irec *rmap)
2948{
2949 if (!xfs_has_reflink(mp))
2950 return false;
2951 if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2952 return false;
2953 if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
2954 XFS_RMAP_BMBT_BLOCK))
2955 return false;
2956 return true;
2957}
2958
2959static inline void
2960xfs_rmap_ownercount_init(
2961 struct xfs_rmap_ownercount *roc,
5837e73b
DW
2962 xfs_agblock_t bno,
2963 xfs_extlen_t len,
2964 const struct xfs_owner_info *oinfo,
54644f25 2965 struct xfs_rmap_matches *results)
556c739d 2966{
54644f25
DW
2967 memset(roc, 0, sizeof(*roc));
2968 roc->results = results;
2969
2970 roc->low.rm_startblock = bno;
2971 memset(&roc->high, 0xFF, sizeof(roc->high));
2972 roc->high.rm_startblock = bno + len - 1;
2973
2974 memset(results, 0, sizeof(*results));
2975 roc->good.rm_startblock = bno;
2976 roc->good.rm_blockcount = len;
2977 roc->good.rm_owner = oinfo->oi_owner;
2978 roc->good.rm_offset = oinfo->oi_offset;
2979 if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
2980 roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
2981 if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
2982 roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2983}
556c739d 2984
54644f25
DW
2985/* Figure out if this is a match for the owner. */
2986STATIC int
2987xfs_rmap_count_owners_helper(
2988 struct xfs_btree_cur *cur,
2989 const struct xfs_rmap_irec *rec,
2990 void *priv)
2991{
2992 struct xfs_rmap_ownercount *roc = priv;
2993 struct xfs_rmap_irec check = *rec;
2994 unsigned int keyflags;
2995 bool filedata;
2996 int64_t delta;
2997
2998 filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
2999 !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
3000
3001 /* Trim the part of check that comes before the comparison range. */
3002 delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
3003 if (delta > 0) {
3004 check.rm_startblock += delta;
3005 check.rm_blockcount -= delta;
3006 if (filedata)
3007 check.rm_offset += delta;
3008 }
556c739d 3009
54644f25
DW
3010 /* Trim the part of check that comes after the comparison range. */
3011 delta = (check.rm_startblock + check.rm_blockcount) -
3012 (roc->good.rm_startblock + roc->good.rm_blockcount);
3013 if (delta > 0)
3014 check.rm_blockcount -= delta;
3015
3016 /* Don't care about unwritten status for establishing ownership. */
3017 keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
3018
3019 if (check.rm_startblock == roc->good.rm_startblock &&
3020 check.rm_blockcount == roc->good.rm_blockcount &&
3021 check.rm_owner == roc->good.rm_owner &&
3022 check.rm_offset == roc->good.rm_offset &&
3023 keyflags == roc->good.rm_flags) {
3024 roc->results->matches++;
3025 } else {
3026 roc->results->non_owner_matches++;
3027 if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
3028 xfs_rmap_shareable(cur->bc_mp, &check))
3029 roc->results->bad_non_owner_matches++;
556c739d
DW
3030 }
3031
54644f25
DW
3032 if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
3033 return -ECANCELED;
3034
556c739d
DW
3035 return 0;
3036}
d264e392 3037
54644f25
DW
3038/* Count the number of owners and non-owners of this range of blocks. */
3039int
3040xfs_rmap_count_owners(
d264e392 3041 struct xfs_btree_cur *cur,
54644f25
DW
3042 xfs_agblock_t bno,
3043 xfs_extlen_t len,
3044 const struct xfs_owner_info *oinfo,
3045 struct xfs_rmap_matches *results)
d264e392 3046{
54644f25
DW
3047 struct xfs_rmap_ownercount roc;
3048 int error;
d264e392 3049
54644f25
DW
3050 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
3051 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
3052 xfs_rmap_count_owners_helper, &roc);
3053 if (error)
3054 return error;
3055
3056 /*
3057 * There can't be any non-owner rmaps that conflict with the given
3058 * owner if we didn't find any rmaps matching the owner.
3059 */
3060 if (!results->matches)
3061 results->bad_non_owner_matches = 0;
3062
3063 return 0;
d264e392
DW
3064}
3065
3066/*
3067 * Given an extent and some owner info, can we find records overlapping
3068 * the extent whose owner info does not match the given owner?
3069 */
3070int
3071xfs_rmap_has_other_keys(
3072 struct xfs_btree_cur *cur,
3073 xfs_agblock_t bno,
3074 xfs_extlen_t len,
5837e73b 3075 const struct xfs_owner_info *oinfo,
54644f25 3076 bool *has_other)
d264e392 3077{
54644f25
DW
3078 struct xfs_rmap_matches res;
3079 struct xfs_rmap_ownercount roc;
d264e392
DW
3080 int error;
3081
54644f25
DW
3082 xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
3083 roc.stop_on_nonmatch = true;
d264e392 3084
54644f25
DW
3085 error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
3086 xfs_rmap_count_owners_helper, &roc);
443d6241 3087 if (error == -ECANCELED) {
54644f25 3088 *has_other = true;
443d6241
DW
3089 return 0;
3090 }
54644f25
DW
3091 if (error)
3092 return error;
6c3013ad 3093
54644f25
DW
3094 *has_other = false;
3095 return 0;
d264e392 3096}
007347e3
DW
3097
3098const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
3099 .oi_owner = XFS_RMAP_OWN_NULL,
3100};
3101const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
3102 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
3103};
3104const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
3105 .oi_owner = XFS_RMAP_OWN_FS,
3106};
3107const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
3108 .oi_owner = XFS_RMAP_OWN_LOG,
3109};
3110const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
3111 .oi_owner = XFS_RMAP_OWN_AG,
3112};
3113const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
3114 .oi_owner = XFS_RMAP_OWN_INOBT,
3115};
3116const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
3117 .oi_owner = XFS_RMAP_OWN_INODES,
3118};
3119const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
3120 .oi_owner = XFS_RMAP_OWN_REFC,
3121};
3122const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
3123 .oi_owner = XFS_RMAP_OWN_COW,
3124};
1577541c
DW
3125
3126int __init
3127xfs_rmap_intent_init_cache(void)
3128{
3129 xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
3130 sizeof(struct xfs_rmap_intent),
3131 0, 0, NULL);
3132
3133 return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
3134}
3135
3136void
3137xfs_rmap_intent_destroy_cache(void)
3138{
3139 kmem_cache_destroy(xfs_rmap_intent_cache);
3140 xfs_rmap_intent_cache = NULL;
3141}