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