]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_rmap.c
xfs: remove all *_ITER_ABORT values
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_rmap.c
CommitLineData
37b3b4d6 1// SPDX-License-Identifier: GPL-2.0
631ac87a
DW
2/*
3 * Copyright (c) 2014 Red Hat, Inc.
4 * All Rights Reserved.
631ac87a
DW
5 */
6#include "libxfs_priv.h"
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
12#include "xfs_bit.h"
631ac87a
DW
13#include "xfs_mount.h"
14#include "xfs_defer.h"
631ac87a
DW
15#include "xfs_btree.h"
16#include "xfs_trans.h"
17#include "xfs_alloc.h"
18#include "xfs_rmap.h"
631bda23 19#include "xfs_rmap_btree.h"
631ac87a 20#include "xfs_trace.h"
d7f80320 21#include "xfs_inode.h"
631ac87a 22
936ca687
DW
23/*
24 * Lookup the first record less than or equal to [bno, len, owner, offset]
25 * in the btree given by cur.
26 */
27int
28xfs_rmap_lookup_le(
29 struct xfs_btree_cur *cur,
30 xfs_agblock_t bno,
31 xfs_extlen_t len,
32 uint64_t owner,
33 uint64_t offset,
34 unsigned int flags,
35 int *stat)
36{
37 cur->bc_rec.r.rm_startblock = bno;
38 cur->bc_rec.r.rm_blockcount = len;
39 cur->bc_rec.r.rm_owner = owner;
40 cur->bc_rec.r.rm_offset = offset;
41 cur->bc_rec.r.rm_flags = flags;
42 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
43}
44
45/*
46 * Lookup the record exactly matching [bno, len, owner, offset]
47 * in the btree given by cur.
48 */
49int
50xfs_rmap_lookup_eq(
51 struct xfs_btree_cur *cur,
52 xfs_agblock_t bno,
53 xfs_extlen_t len,
54 uint64_t owner,
55 uint64_t offset,
56 unsigned int flags,
57 int *stat)
58{
59 cur->bc_rec.r.rm_startblock = bno;
60 cur->bc_rec.r.rm_blockcount = len;
61 cur->bc_rec.r.rm_owner = owner;
62 cur->bc_rec.r.rm_offset = offset;
63 cur->bc_rec.r.rm_flags = flags;
64 return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
65}
66
67/*
68 * Update the record referred to by cur to the value given
69 * by [bno, len, owner, offset].
70 * This either works (return 0) or gets an EFSCORRUPTED error.
71 */
72STATIC int
73xfs_rmap_update(
74 struct xfs_btree_cur *cur,
75 struct xfs_rmap_irec *irec)
76{
77 union xfs_btree_rec rec;
b26675c4
DW
78 int error;
79
80 trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
81 irec->rm_startblock, irec->rm_blockcount,
82 irec->rm_owner, irec->rm_offset, irec->rm_flags);
936ca687
DW
83
84 rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
85 rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
86 rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
87 rec.rmap.rm_offset = cpu_to_be64(
88 xfs_rmap_irec_offset_pack(irec));
b26675c4
DW
89 error = xfs_btree_update(cur, &rec);
90 if (error)
91 trace_xfs_rmap_update_error(cur->bc_mp,
92 cur->bc_private.a.agno, error, _RET_IP_);
93 return error;
94}
95
96int
97xfs_rmap_insert(
98 struct xfs_btree_cur *rcur,
99 xfs_agblock_t agbno,
100 xfs_extlen_t len,
101 uint64_t owner,
102 uint64_t offset,
103 unsigned int flags)
104{
105 int i;
106 int error;
107
108 trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
109 len, owner, offset, flags);
110
111 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
112 if (error)
113 goto done;
114 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
115
116 rcur->bc_rec.r.rm_startblock = agbno;
117 rcur->bc_rec.r.rm_blockcount = len;
118 rcur->bc_rec.r.rm_owner = owner;
119 rcur->bc_rec.r.rm_offset = offset;
120 rcur->bc_rec.r.rm_flags = flags;
121 error = xfs_btree_insert(rcur, &i);
122 if (error)
123 goto done;
124 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
125done:
126 if (error)
127 trace_xfs_rmap_insert_error(rcur->bc_mp,
128 rcur->bc_private.a.agno, error, _RET_IP_);
129 return error;
936ca687
DW
130}
131
6c6bdf6f
DW
132STATIC int
133xfs_rmap_delete(
134 struct xfs_btree_cur *rcur,
135 xfs_agblock_t agbno,
136 xfs_extlen_t len,
137 uint64_t owner,
138 uint64_t offset,
139 unsigned int flags)
140{
141 int i;
142 int error;
143
144 trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
145 len, owner, offset, flags);
146
147 error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
148 if (error)
149 goto done;
150 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
151
152 error = xfs_btree_delete(rcur, &i);
153 if (error)
154 goto done;
155 XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
156done:
157 if (error)
158 trace_xfs_rmap_delete_error(rcur->bc_mp,
159 rcur->bc_private.a.agno, error, _RET_IP_);
160 return error;
161}
162
50bb67d6
DW
163/* Convert an internal btree record to an rmap record. */
164int
936ca687
DW
165xfs_rmap_btrec_to_irec(
166 union xfs_btree_rec *rec,
167 struct xfs_rmap_irec *irec)
168{
936ca687
DW
169 irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
170 irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
171 irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
172 return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
173 irec);
174}
175
176/*
177 * Get the data from the pointed-to record.
178 */
179int
180xfs_rmap_get_rec(
181 struct xfs_btree_cur *cur,
182 struct xfs_rmap_irec *irec,
183 int *stat)
184{
ec291989
DC
185 struct xfs_mount *mp = cur->bc_mp;
186 xfs_agnumber_t agno = cur->bc_private.a.agno;
936ca687
DW
187 union xfs_btree_rec *rec;
188 int error;
189
190 error = xfs_btree_get_rec(cur, &rec, stat);
191 if (error || !*stat)
192 return error;
193
ec291989
DC
194 if (xfs_rmap_btrec_to_irec(rec, irec))
195 goto out_bad_rec;
196
197 if (irec->rm_blockcount == 0)
198 goto out_bad_rec;
199 if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
200 if (irec->rm_owner != XFS_RMAP_OWN_FS)
201 goto out_bad_rec;
202 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
203 goto out_bad_rec;
204 } else {
205 /* check for valid extent range, including overflow */
206 if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
207 goto out_bad_rec;
208 if (irec->rm_startblock >
209 irec->rm_startblock + irec->rm_blockcount)
210 goto out_bad_rec;
211 if (!xfs_verify_agbno(mp, agno,
212 irec->rm_startblock + irec->rm_blockcount - 1))
213 goto out_bad_rec;
214 }
215
216 if (!(xfs_verify_ino(mp, irec->rm_owner) ||
217 (irec->rm_owner <= XFS_RMAP_OWN_FS &&
218 irec->rm_owner >= XFS_RMAP_OWN_MIN)))
219 goto out_bad_rec;
220
221 return 0;
222out_bad_rec:
223 xfs_warn(mp,
224 "Reverse Mapping BTree record corruption in AG %d detected!",
225 agno);
226 xfs_warn(mp,
227 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
228 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
229 irec->rm_blockcount);
230 return -EFSCORRUPTED;
936ca687
DW
231}
232
6c6bdf6f
DW
233struct xfs_find_left_neighbor_info {
234 struct xfs_rmap_irec high;
235 struct xfs_rmap_irec *irec;
236 int *stat;
237};
238
239/* For each rmap given, figure out if it matches the key we want. */
240STATIC int
241xfs_rmap_find_left_neighbor_helper(
242 struct xfs_btree_cur *cur,
243 struct xfs_rmap_irec *rec,
244 void *priv)
245{
246 struct xfs_find_left_neighbor_info *info = priv;
247
248 trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
249 cur->bc_private.a.agno, rec->rm_startblock,
250 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
251 rec->rm_flags);
252
253 if (rec->rm_owner != info->high.rm_owner)
254 return XFS_BTREE_QUERY_RANGE_CONTINUE;
255 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
256 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
257 rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
258 return XFS_BTREE_QUERY_RANGE_CONTINUE;
259
260 *info->irec = *rec;
261 *info->stat = 1;
a0f17dde 262 return -ECANCELED;
6c6bdf6f
DW
263}
264
265/*
266 * Find the record to the left of the given extent, being careful only to
267 * return a match with the same owner and adjacent physical and logical
268 * block ranges.
269 */
270int
271xfs_rmap_find_left_neighbor(
272 struct xfs_btree_cur *cur,
273 xfs_agblock_t bno,
274 uint64_t owner,
275 uint64_t offset,
276 unsigned int flags,
277 struct xfs_rmap_irec *irec,
278 int *stat)
279{
280 struct xfs_find_left_neighbor_info info;
281 int error;
282
283 *stat = 0;
284 if (bno == 0)
285 return 0;
286 info.high.rm_startblock = bno - 1;
287 info.high.rm_owner = owner;
288 if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
289 !(flags & XFS_RMAP_BMBT_BLOCK)) {
290 if (offset == 0)
291 return 0;
292 info.high.rm_offset = offset - 1;
293 } else
294 info.high.rm_offset = 0;
295 info.high.rm_flags = flags;
296 info.high.rm_blockcount = 0;
297 info.irec = irec;
298 info.stat = stat;
299
300 trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
301 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
302
303 error = xfs_rmap_query_range(cur, &info.high, &info.high,
304 xfs_rmap_find_left_neighbor_helper, &info);
a0f17dde 305 if (error == -ECANCELED)
6c6bdf6f
DW
306 error = 0;
307 if (*stat)
308 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
309 cur->bc_private.a.agno, irec->rm_startblock,
310 irec->rm_blockcount, irec->rm_owner,
311 irec->rm_offset, irec->rm_flags);
312 return error;
313}
314
315/* For each rmap given, figure out if it matches the key we want. */
316STATIC int
317xfs_rmap_lookup_le_range_helper(
318 struct xfs_btree_cur *cur,
319 struct xfs_rmap_irec *rec,
320 void *priv)
321{
322 struct xfs_find_left_neighbor_info *info = priv;
323
324 trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
325 cur->bc_private.a.agno, rec->rm_startblock,
326 rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
327 rec->rm_flags);
328
329 if (rec->rm_owner != info->high.rm_owner)
330 return XFS_BTREE_QUERY_RANGE_CONTINUE;
331 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
332 !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
333 (rec->rm_offset > info->high.rm_offset ||
334 rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
335 return XFS_BTREE_QUERY_RANGE_CONTINUE;
336
337 *info->irec = *rec;
338 *info->stat = 1;
a0f17dde 339 return -ECANCELED;
6c6bdf6f
DW
340}
341
342/*
343 * Find the record to the left of the given extent, being careful only to
344 * return a match with the same owner and overlapping physical and logical
345 * block ranges. This is the overlapping-interval version of
346 * xfs_rmap_lookup_le.
347 */
348int
349xfs_rmap_lookup_le_range(
350 struct xfs_btree_cur *cur,
351 xfs_agblock_t bno,
352 uint64_t owner,
353 uint64_t offset,
354 unsigned int flags,
355 struct xfs_rmap_irec *irec,
356 int *stat)
357{
358 struct xfs_find_left_neighbor_info info;
359 int error;
360
361 info.high.rm_startblock = bno;
362 info.high.rm_owner = owner;
363 if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
364 info.high.rm_offset = offset;
365 else
366 info.high.rm_offset = 0;
367 info.high.rm_flags = flags;
368 info.high.rm_blockcount = 0;
369 *stat = 0;
370 info.irec = irec;
371 info.stat = stat;
372
373 trace_xfs_rmap_lookup_le_range(cur->bc_mp,
374 cur->bc_private.a.agno, bno, 0, owner, offset, flags);
375 error = xfs_rmap_query_range(cur, &info.high, &info.high,
376 xfs_rmap_lookup_le_range_helper, &info);
a0f17dde 377 if (error == -ECANCELED)
6c6bdf6f
DW
378 error = 0;
379 if (*stat)
380 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
381 cur->bc_private.a.agno, irec->rm_startblock,
382 irec->rm_blockcount, irec->rm_owner,
383 irec->rm_offset, irec->rm_flags);
384 return error;
385}
386
19f9a63a
DW
387/*
388 * Perform all the relevant owner checks for a removal op. If we're doing an
389 * unknown-owner removal then we have no owner information to check.
390 */
391static int
392xfs_rmap_free_check_owner(
393 struct xfs_mount *mp,
394 uint64_t ltoff,
395 struct xfs_rmap_irec *rec,
19f9a63a
DW
396 xfs_filblks_t len,
397 uint64_t owner,
398 uint64_t offset,
399 unsigned int flags)
400{
401 int error = 0;
402
403 if (owner == XFS_RMAP_OWN_UNKNOWN)
404 return 0;
405
406 /* Make sure the unwritten flag matches. */
407 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
408 (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
409
410 /* Make sure the owner matches what we expect to find in the tree. */
411 XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
412
413 /* Check the offset, if necessary. */
414 if (XFS_RMAP_NON_INODE_OWNER(owner))
415 goto out;
416
417 if (flags & XFS_RMAP_BMBT_BLOCK) {
418 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
419 out);
420 } else {
421 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
422 XFS_WANT_CORRUPTED_GOTO(mp,
423 ltoff + rec->rm_blockcount >= offset + len,
424 out);
425 }
426
427out:
428 return error;
429}
430
ae81ebf2
DW
431/*
432 * Find the extent in the rmap btree and remove it.
433 *
434 * The record we find should always be an exact match for the extent that we're
435 * looking for, since we insert them into the btree without modification.
436 *
437 * Special Case #1: when growing the filesystem, we "free" an extent when
438 * growing the last AG. This extent is new space and so it is not tracked as
439 * used space in the btree. The growfs code will pass in an owner of
440 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
441 * extent. We verify that - the extent lookup result in a record that does not
442 * overlap.
443 *
444 * Special Case #2: EFIs do not record the owner of the extent, so when
445 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
446 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
447 * corruption checks during log recovery.
448 */
449STATIC int
450xfs_rmap_unmap(
5837e73b
DW
451 struct xfs_btree_cur *cur,
452 xfs_agblock_t bno,
453 xfs_extlen_t len,
454 bool unwritten,
455 const struct xfs_owner_info *oinfo)
ae81ebf2 456{
5837e73b
DW
457 struct xfs_mount *mp = cur->bc_mp;
458 struct xfs_rmap_irec ltrec;
459 uint64_t ltoff;
460 int error = 0;
461 int i;
462 uint64_t owner;
463 uint64_t offset;
464 unsigned int flags;
465 bool ignore_off;
ae81ebf2
DW
466
467 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
468 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
469 (flags & XFS_RMAP_BMBT_BLOCK);
470 if (unwritten)
471 flags |= XFS_RMAP_UNWRITTEN;
472 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
473 unwritten, oinfo);
474
475 /*
476 * We should always have a left record because there's a static record
477 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
478 * will not ever be removed from the tree.
479 */
480 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
481 if (error)
482 goto out_error;
483 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
484
485 error = xfs_rmap_get_rec(cur, &ltrec, &i);
486 if (error)
487 goto out_error;
488 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
489 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
490 cur->bc_private.a.agno, ltrec.rm_startblock,
491 ltrec.rm_blockcount, ltrec.rm_owner,
492 ltrec.rm_offset, ltrec.rm_flags);
493 ltoff = ltrec.rm_offset;
494
495 /*
496 * For growfs, the incoming extent must be beyond the left record we
497 * just found as it is new space and won't be used by anyone. This is
498 * just a corruption check as we don't actually do anything with this
499 * extent. Note that we need to use >= instead of > because it might
500 * be the case that the "left" extent goes all the way to EOFS.
501 */
502 if (owner == XFS_RMAP_OWN_NULL) {
503 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
504 ltrec.rm_blockcount, out_error);
505 goto out_done;
506 }
507
3ee858aa
DW
508 /*
509 * If we're doing an unknown-owner removal for EFI recovery, we expect
510 * to find the full range in the rmapbt or nothing at all. If we
511 * don't find any rmaps overlapping either end of the range, we're
512 * done. Hopefully this means that the EFI creator already queued
513 * (and finished) a RUI to remove the rmap.
514 */
515 if (owner == XFS_RMAP_OWN_UNKNOWN &&
516 ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
517 struct xfs_rmap_irec rtrec;
518
519 error = xfs_btree_increment(cur, 0, &i);
520 if (error)
521 goto out_error;
522 if (i == 0)
523 goto out_done;
524 error = xfs_rmap_get_rec(cur, &rtrec, &i);
525 if (error)
526 goto out_error;
527 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
528 if (rtrec.rm_startblock >= bno + len)
529 goto out_done;
530 }
531
ae81ebf2
DW
532 /* Make sure the extent we found covers the entire freeing range. */
533 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
19f9a63a
DW
534 ltrec.rm_startblock + ltrec.rm_blockcount >=
535 bno + len, out_error);
ae81ebf2 536
19f9a63a 537 /* Check owner information. */
1421de38 538 error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, len, owner,
19f9a63a
DW
539 offset, flags);
540 if (error)
541 goto out_error;
ae81ebf2
DW
542
543 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
544 /* exact match, simply remove the record from rmap tree */
545 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
546 ltrec.rm_startblock, ltrec.rm_blockcount,
547 ltrec.rm_owner, ltrec.rm_offset,
548 ltrec.rm_flags);
549 error = xfs_btree_delete(cur, &i);
550 if (error)
551 goto out_error;
552 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
553 } else if (ltrec.rm_startblock == bno) {
554 /*
555 * overlap left hand side of extent: move the start, trim the
556 * length and update the current record.
557 *
558 * ltbno ltlen
559 * Orig: |oooooooooooooooooooo|
560 * Freeing: |fffffffff|
561 * Result: |rrrrrrrrrr|
562 * bno len
563 */
564 ltrec.rm_startblock += len;
565 ltrec.rm_blockcount -= len;
566 if (!ignore_off)
567 ltrec.rm_offset += len;
568 error = xfs_rmap_update(cur, &ltrec);
569 if (error)
570 goto out_error;
571 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
572 /*
573 * overlap right hand side of extent: trim the length and update
574 * the current record.
575 *
576 * ltbno ltlen
577 * Orig: |oooooooooooooooooooo|
578 * Freeing: |fffffffff|
579 * Result: |rrrrrrrrrr|
580 * bno len
581 */
582 ltrec.rm_blockcount -= len;
583 error = xfs_rmap_update(cur, &ltrec);
584 if (error)
585 goto out_error;
586 } else {
587
588 /*
589 * overlap middle of extent: trim the length of the existing
590 * record to the length of the new left-extent size, increment
591 * the insertion position so we can insert a new record
592 * containing the remaining right-extent space.
593 *
594 * ltbno ltlen
595 * Orig: |oooooooooooooooooooo|
596 * Freeing: |fffffffff|
597 * Result: |rrrrr| |rrrr|
598 * bno len
599 */
600 xfs_extlen_t orig_len = ltrec.rm_blockcount;
601
602 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
603 error = xfs_rmap_update(cur, &ltrec);
604 if (error)
605 goto out_error;
606
607 error = xfs_btree_increment(cur, 0, &i);
608 if (error)
609 goto out_error;
610
611 cur->bc_rec.r.rm_startblock = bno + len;
612 cur->bc_rec.r.rm_blockcount = orig_len - len -
613 ltrec.rm_blockcount;
614 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
615 if (ignore_off)
616 cur->bc_rec.r.rm_offset = 0;
617 else
618 cur->bc_rec.r.rm_offset = offset + len;
619 cur->bc_rec.r.rm_flags = flags;
620 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
621 cur->bc_rec.r.rm_startblock,
622 cur->bc_rec.r.rm_blockcount,
623 cur->bc_rec.r.rm_owner,
624 cur->bc_rec.r.rm_offset,
625 cur->bc_rec.r.rm_flags);
626 error = xfs_btree_insert(cur, &i);
627 if (error)
628 goto out_error;
629 }
630
631out_done:
632 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
633 unwritten, oinfo);
634out_error:
635 if (error)
636 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
637 error, _RET_IP_);
638 return error;
639}
640
641/*
642 * Remove a reference to an extent in the rmap btree.
643 */
631ac87a
DW
644int
645xfs_rmap_free(
5837e73b
DW
646 struct xfs_trans *tp,
647 struct xfs_buf *agbp,
648 xfs_agnumber_t agno,
649 xfs_agblock_t bno,
650 xfs_extlen_t len,
651 const struct xfs_owner_info *oinfo)
631ac87a 652{
5837e73b
DW
653 struct xfs_mount *mp = tp->t_mountp;
654 struct xfs_btree_cur *cur;
655 int error;
631ac87a
DW
656
657 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
658 return 0;
659
ae81ebf2
DW
660 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
661
662 error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
ae81ebf2 663
660265b7 664 xfs_btree_del_cursor(cur, error);
631ac87a
DW
665 return error;
666}
667
631bda23
DW
668/*
669 * A mergeable rmap must have the same owner and the same values for
670 * the unwritten, attr_fork, and bmbt flags. The startblock and
671 * offset are checked separately.
672 */
673static bool
674xfs_rmap_is_mergeable(
675 struct xfs_rmap_irec *irec,
676 uint64_t owner,
677 unsigned int flags)
678{
679 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
680 return false;
681 if (irec->rm_owner != owner)
682 return false;
683 if ((flags & XFS_RMAP_UNWRITTEN) ^
684 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
685 return false;
686 if ((flags & XFS_RMAP_ATTR_FORK) ^
687 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
688 return false;
689 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
690 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
691 return false;
692 return true;
693}
694
695/*
696 * When we allocate a new block, the first thing we do is add a reference to
697 * the extent in the rmap btree. This takes the form of a [agbno, length,
698 * owner, offset] record. Flags are encoded in the high bits of the offset
699 * field.
700 */
701STATIC int
702xfs_rmap_map(
5837e73b
DW
703 struct xfs_btree_cur *cur,
704 xfs_agblock_t bno,
705 xfs_extlen_t len,
706 bool unwritten,
707 const struct xfs_owner_info *oinfo)
631bda23 708{
5837e73b
DW
709 struct xfs_mount *mp = cur->bc_mp;
710 struct xfs_rmap_irec ltrec;
711 struct xfs_rmap_irec gtrec;
712 int have_gt;
713 int have_lt;
714 int error = 0;
715 int i;
716 uint64_t owner;
717 uint64_t offset;
718 unsigned int flags = 0;
719 bool ignore_off;
631bda23
DW
720
721 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
722 ASSERT(owner != 0);
723 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
724 (flags & XFS_RMAP_BMBT_BLOCK);
725 if (unwritten)
726 flags |= XFS_RMAP_UNWRITTEN;
727 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
728 unwritten, oinfo);
3ee858aa 729 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
631bda23
DW
730
731 /*
732 * For the initial lookup, look for an exact match or the left-adjacent
733 * record for our insertion point. This will also give us the record for
734 * start block contiguity tests.
735 */
736 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
737 &have_lt);
738 if (error)
739 goto out_error;
a6ad7ea8
DW
740 if (have_lt) {
741 error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
742 if (error)
743 goto out_error;
744 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
745 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
746 cur->bc_private.a.agno, ltrec.rm_startblock,
747 ltrec.rm_blockcount, ltrec.rm_owner,
748 ltrec.rm_offset, ltrec.rm_flags);
631bda23 749
a6ad7ea8
DW
750 if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
751 have_lt = 0;
752 }
631bda23
DW
753
754 XFS_WANT_CORRUPTED_GOTO(mp,
755 have_lt == 0 ||
756 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
757
758 /*
759 * Increment the cursor to see if we have a right-adjacent record to our
760 * insertion point. This will give us the record for end block
761 * contiguity tests.
762 */
763 error = xfs_btree_increment(cur, 0, &have_gt);
764 if (error)
765 goto out_error;
766 if (have_gt) {
767 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
768 if (error)
769 goto out_error;
770 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
771 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
772 out_error);
773 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
774 cur->bc_private.a.agno, gtrec.rm_startblock,
775 gtrec.rm_blockcount, gtrec.rm_owner,
776 gtrec.rm_offset, gtrec.rm_flags);
777 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
778 have_gt = 0;
779 }
780
781 /*
782 * Note: cursor currently points one record to the right of ltrec, even
783 * if there is no record in the tree to the right.
784 */
785 if (have_lt &&
786 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
787 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
788 /*
789 * left edge contiguous, merge into left record.
790 *
791 * ltbno ltlen
792 * orig: |ooooooooo|
793 * adding: |aaaaaaaaa|
794 * result: |rrrrrrrrrrrrrrrrrrr|
795 * bno len
796 */
797 ltrec.rm_blockcount += len;
798 if (have_gt &&
799 bno + len == gtrec.rm_startblock &&
800 (ignore_off || offset + len == gtrec.rm_offset) &&
801 (unsigned long)ltrec.rm_blockcount + len +
802 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
803 /*
804 * right edge also contiguous, delete right record
805 * and merge into left record.
806 *
807 * ltbno ltlen gtbno gtlen
808 * orig: |ooooooooo| |ooooooooo|
809 * adding: |aaaaaaaaa|
810 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
811 */
812 ltrec.rm_blockcount += gtrec.rm_blockcount;
813 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
814 gtrec.rm_startblock,
815 gtrec.rm_blockcount,
816 gtrec.rm_owner,
817 gtrec.rm_offset,
818 gtrec.rm_flags);
819 error = xfs_btree_delete(cur, &i);
820 if (error)
821 goto out_error;
822 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
823 }
824
825 /* point the cursor back to the left record and update */
826 error = xfs_btree_decrement(cur, 0, &have_gt);
827 if (error)
828 goto out_error;
829 error = xfs_rmap_update(cur, &ltrec);
830 if (error)
831 goto out_error;
832 } else if (have_gt &&
833 bno + len == gtrec.rm_startblock &&
834 (ignore_off || offset + len == gtrec.rm_offset)) {
835 /*
836 * right edge contiguous, merge into right record.
837 *
838 * gtbno gtlen
839 * Orig: |ooooooooo|
840 * adding: |aaaaaaaaa|
841 * Result: |rrrrrrrrrrrrrrrrrrr|
842 * bno len
843 */
844 gtrec.rm_startblock = bno;
845 gtrec.rm_blockcount += len;
846 if (!ignore_off)
847 gtrec.rm_offset = offset;
848 error = xfs_rmap_update(cur, &gtrec);
849 if (error)
850 goto out_error;
851 } else {
852 /*
853 * no contiguous edge with identical owner, insert
854 * new record at current cursor position.
855 */
856 cur->bc_rec.r.rm_startblock = bno;
857 cur->bc_rec.r.rm_blockcount = len;
858 cur->bc_rec.r.rm_owner = owner;
859 cur->bc_rec.r.rm_offset = offset;
860 cur->bc_rec.r.rm_flags = flags;
861 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
862 owner, offset, flags);
863 error = xfs_btree_insert(cur, &i);
864 if (error)
865 goto out_error;
866 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
867 }
868
869 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
870 unwritten, oinfo);
871out_error:
872 if (error)
873 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
874 error, _RET_IP_);
875 return error;
876}
877
878/*
879 * Add a reference to an extent in the rmap btree.
880 */
631ac87a
DW
881int
882xfs_rmap_alloc(
5837e73b
DW
883 struct xfs_trans *tp,
884 struct xfs_buf *agbp,
885 xfs_agnumber_t agno,
886 xfs_agblock_t bno,
887 xfs_extlen_t len,
888 const struct xfs_owner_info *oinfo)
631ac87a 889{
5837e73b
DW
890 struct xfs_mount *mp = tp->t_mountp;
891 struct xfs_btree_cur *cur;
892 int error;
631ac87a
DW
893
894 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
895 return 0;
896
631bda23
DW
897 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
898 error = xfs_rmap_map(cur, bno, len, false, oinfo);
631bda23 899
660265b7 900 xfs_btree_del_cursor(cur, error);
631ac87a
DW
901 return error;
902}
890e1174 903
7faf209c
DW
904#define RMAP_LEFT_CONTIG (1 << 0)
905#define RMAP_RIGHT_CONTIG (1 << 1)
906#define RMAP_LEFT_FILLING (1 << 2)
907#define RMAP_RIGHT_FILLING (1 << 3)
908#define RMAP_LEFT_VALID (1 << 6)
909#define RMAP_RIGHT_VALID (1 << 7)
910
911#define LEFT r[0]
912#define RIGHT r[1]
913#define PREV r[2]
914#define NEW r[3]
915
916/*
917 * Convert an unwritten extent to a real extent or vice versa.
918 * Does not handle overlapping extents.
919 */
920STATIC int
921xfs_rmap_convert(
5837e73b
DW
922 struct xfs_btree_cur *cur,
923 xfs_agblock_t bno,
924 xfs_extlen_t len,
925 bool unwritten,
926 const struct xfs_owner_info *oinfo)
7faf209c 927{
5837e73b
DW
928 struct xfs_mount *mp = cur->bc_mp;
929 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
930 /* left is 0, right is 1, */
931 /* prev is 2, new is 3 */
7faf209c
DW
932 uint64_t owner;
933 uint64_t offset;
934 uint64_t new_endoff;
935 unsigned int oldext;
936 unsigned int newext;
937 unsigned int flags = 0;
938 int i;
939 int state = 0;
940 int error;
941
942 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
943 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
944 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
945 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
946 new_endoff = offset + len;
947 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
948 unwritten, oinfo);
949
950 /*
951 * For the initial lookup, look for an exact match or the left-adjacent
952 * record for our insertion point. This will also give us the record for
953 * start block contiguity tests.
954 */
955 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
956 if (error)
957 goto done;
958 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
959
960 error = xfs_rmap_get_rec(cur, &PREV, &i);
961 if (error)
962 goto done;
963 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
964 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
965 cur->bc_private.a.agno, PREV.rm_startblock,
966 PREV.rm_blockcount, PREV.rm_owner,
967 PREV.rm_offset, PREV.rm_flags);
968
969 ASSERT(PREV.rm_offset <= offset);
970 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
971 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
972 newext = ~oldext & XFS_RMAP_UNWRITTEN;
973
974 /*
975 * Set flags determining what part of the previous oldext allocation
976 * extent is being replaced by a newext allocation.
977 */
978 if (PREV.rm_offset == offset)
979 state |= RMAP_LEFT_FILLING;
980 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
981 state |= RMAP_RIGHT_FILLING;
982
983 /*
984 * Decrement the cursor to see if we have a left-adjacent record to our
985 * insertion point. This will give us the record for end block
986 * contiguity tests.
987 */
988 error = xfs_btree_decrement(cur, 0, &i);
989 if (error)
990 goto done;
991 if (i) {
992 state |= RMAP_LEFT_VALID;
993 error = xfs_rmap_get_rec(cur, &LEFT, &i);
994 if (error)
995 goto done;
996 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
997 XFS_WANT_CORRUPTED_GOTO(mp,
998 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
999 done);
1000 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1001 cur->bc_private.a.agno, LEFT.rm_startblock,
1002 LEFT.rm_blockcount, LEFT.rm_owner,
1003 LEFT.rm_offset, LEFT.rm_flags);
1004 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1005 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1006 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1007 state |= RMAP_LEFT_CONTIG;
1008 }
1009
1010 /*
1011 * Increment the cursor to see if we have a right-adjacent record to our
1012 * insertion point. This will give us the record for end block
1013 * contiguity tests.
1014 */
1015 error = xfs_btree_increment(cur, 0, &i);
1016 if (error)
1017 goto done;
1018 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1019 error = xfs_btree_increment(cur, 0, &i);
1020 if (error)
1021 goto done;
1022 if (i) {
1023 state |= RMAP_RIGHT_VALID;
1024 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1025 if (error)
1026 goto done;
1027 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1028 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1029 done);
1030 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1031 cur->bc_private.a.agno, RIGHT.rm_startblock,
1032 RIGHT.rm_blockcount, RIGHT.rm_owner,
1033 RIGHT.rm_offset, RIGHT.rm_flags);
1034 if (bno + len == RIGHT.rm_startblock &&
1035 offset + len == RIGHT.rm_offset &&
1036 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1037 state |= RMAP_RIGHT_CONTIG;
1038 }
1039
1040 /* check that left + prev + right is not too long */
1041 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1042 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1043 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1044 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1045 (unsigned long)LEFT.rm_blockcount + len +
1046 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1047 state &= ~RMAP_RIGHT_CONTIG;
1048
1049 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1050 _RET_IP_);
1051
1052 /* reset the cursor back to PREV */
1053 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1054 if (error)
1055 goto done;
1056 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1057
1058 /*
1059 * Switch out based on the FILLING and CONTIG state bits.
1060 */
1061 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1062 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1063 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1064 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1065 /*
1066 * Setting all of a previous oldext extent to newext.
1067 * The left and right neighbors are both contiguous with new.
1068 */
1069 error = xfs_btree_increment(cur, 0, &i);
1070 if (error)
1071 goto done;
1072 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1073 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1074 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1075 RIGHT.rm_owner, RIGHT.rm_offset,
1076 RIGHT.rm_flags);
1077 error = xfs_btree_delete(cur, &i);
1078 if (error)
1079 goto done;
1080 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1081 error = xfs_btree_decrement(cur, 0, &i);
1082 if (error)
1083 goto done;
1084 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1085 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1086 PREV.rm_startblock, PREV.rm_blockcount,
1087 PREV.rm_owner, PREV.rm_offset,
1088 PREV.rm_flags);
1089 error = xfs_btree_delete(cur, &i);
1090 if (error)
1091 goto done;
1092 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1093 error = xfs_btree_decrement(cur, 0, &i);
1094 if (error)
1095 goto done;
1096 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1097 NEW = LEFT;
1098 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1099 error = xfs_rmap_update(cur, &NEW);
1100 if (error)
1101 goto done;
1102 break;
1103
1104 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1105 /*
1106 * Setting all of a previous oldext extent to newext.
1107 * The left neighbor is contiguous, the right is not.
1108 */
1109 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1110 PREV.rm_startblock, PREV.rm_blockcount,
1111 PREV.rm_owner, PREV.rm_offset,
1112 PREV.rm_flags);
1113 error = xfs_btree_delete(cur, &i);
1114 if (error)
1115 goto done;
1116 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1117 error = xfs_btree_decrement(cur, 0, &i);
1118 if (error)
1119 goto done;
1120 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1121 NEW = LEFT;
1122 NEW.rm_blockcount += PREV.rm_blockcount;
1123 error = xfs_rmap_update(cur, &NEW);
1124 if (error)
1125 goto done;
1126 break;
1127
1128 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1129 /*
1130 * Setting all of a previous oldext extent to newext.
1131 * The right neighbor is contiguous, the left is not.
1132 */
1133 error = xfs_btree_increment(cur, 0, &i);
1134 if (error)
1135 goto done;
1136 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1137 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1138 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1139 RIGHT.rm_owner, RIGHT.rm_offset,
1140 RIGHT.rm_flags);
1141 error = xfs_btree_delete(cur, &i);
1142 if (error)
1143 goto done;
1144 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1145 error = xfs_btree_decrement(cur, 0, &i);
1146 if (error)
1147 goto done;
1148 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1149 NEW = PREV;
1150 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1151 NEW.rm_flags = newext;
1152 error = xfs_rmap_update(cur, &NEW);
1153 if (error)
1154 goto done;
1155 break;
1156
1157 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1158 /*
1159 * Setting all of a previous oldext extent to newext.
1160 * Neither the left nor right neighbors are contiguous with
1161 * the new one.
1162 */
1163 NEW = PREV;
1164 NEW.rm_flags = newext;
1165 error = xfs_rmap_update(cur, &NEW);
1166 if (error)
1167 goto done;
1168 break;
1169
1170 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1171 /*
1172 * Setting the first part of a previous oldext extent to newext.
1173 * The left neighbor is contiguous.
1174 */
1175 NEW = PREV;
1176 NEW.rm_offset += len;
1177 NEW.rm_startblock += len;
1178 NEW.rm_blockcount -= len;
1179 error = xfs_rmap_update(cur, &NEW);
1180 if (error)
1181 goto done;
1182 error = xfs_btree_decrement(cur, 0, &i);
1183 if (error)
1184 goto done;
1185 NEW = LEFT;
1186 NEW.rm_blockcount += len;
1187 error = xfs_rmap_update(cur, &NEW);
1188 if (error)
1189 goto done;
1190 break;
1191
1192 case RMAP_LEFT_FILLING:
1193 /*
1194 * Setting the first part of a previous oldext extent to newext.
1195 * The left neighbor is not contiguous.
1196 */
1197 NEW = PREV;
1198 NEW.rm_startblock += len;
1199 NEW.rm_offset += len;
1200 NEW.rm_blockcount -= len;
1201 error = xfs_rmap_update(cur, &NEW);
1202 if (error)
1203 goto done;
1204 NEW.rm_startblock = bno;
1205 NEW.rm_owner = owner;
1206 NEW.rm_offset = offset;
1207 NEW.rm_blockcount = len;
1208 NEW.rm_flags = newext;
1209 cur->bc_rec.r = NEW;
1210 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1211 len, owner, offset, newext);
1212 error = xfs_btree_insert(cur, &i);
1213 if (error)
1214 goto done;
1215 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1216 break;
1217
1218 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1219 /*
1220 * Setting the last part of a previous oldext extent to newext.
1221 * The right neighbor is contiguous with the new allocation.
1222 */
1223 NEW = PREV;
1224 NEW.rm_blockcount -= len;
1225 error = xfs_rmap_update(cur, &NEW);
1226 if (error)
1227 goto done;
1228 error = xfs_btree_increment(cur, 0, &i);
1229 if (error)
1230 goto done;
1231 NEW = RIGHT;
1232 NEW.rm_offset = offset;
1233 NEW.rm_startblock = bno;
1234 NEW.rm_blockcount += len;
1235 error = xfs_rmap_update(cur, &NEW);
1236 if (error)
1237 goto done;
1238 break;
1239
1240 case RMAP_RIGHT_FILLING:
1241 /*
1242 * Setting the last part of a previous oldext extent to newext.
1243 * The right neighbor is not contiguous.
1244 */
1245 NEW = PREV;
1246 NEW.rm_blockcount -= len;
1247 error = xfs_rmap_update(cur, &NEW);
1248 if (error)
1249 goto done;
1250 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1251 oldext, &i);
1252 if (error)
1253 goto done;
1254 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1255 NEW.rm_startblock = bno;
1256 NEW.rm_owner = owner;
1257 NEW.rm_offset = offset;
1258 NEW.rm_blockcount = len;
1259 NEW.rm_flags = newext;
1260 cur->bc_rec.r = NEW;
1261 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1262 len, owner, offset, newext);
1263 error = xfs_btree_insert(cur, &i);
1264 if (error)
1265 goto done;
1266 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1267 break;
1268
1269 case 0:
1270 /*
1271 * Setting the middle part of a previous oldext extent to
1272 * newext. Contiguity is impossible here.
1273 * One extent becomes three extents.
1274 */
1275 /* new right extent - oldext */
1276 NEW.rm_startblock = bno + len;
1277 NEW.rm_owner = owner;
1278 NEW.rm_offset = new_endoff;
1279 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1280 new_endoff;
1281 NEW.rm_flags = PREV.rm_flags;
1282 error = xfs_rmap_update(cur, &NEW);
1283 if (error)
1284 goto done;
1285 /* new left extent - oldext */
1286 NEW = PREV;
1287 NEW.rm_blockcount = offset - PREV.rm_offset;
1288 cur->bc_rec.r = NEW;
1289 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1290 NEW.rm_startblock, NEW.rm_blockcount,
1291 NEW.rm_owner, NEW.rm_offset,
1292 NEW.rm_flags);
1293 error = xfs_btree_insert(cur, &i);
1294 if (error)
1295 goto done;
1296 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1297 /*
1298 * Reset the cursor to the position of the new extent
1299 * we are about to insert as we can't trust it after
1300 * the previous insert.
1301 */
1302 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1303 oldext, &i);
1304 if (error)
1305 goto done;
1306 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1307 /* new middle extent - newext */
1308 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1309 cur->bc_rec.r.rm_flags |= newext;
1310 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1311 owner, offset, newext);
1312 error = xfs_btree_insert(cur, &i);
1313 if (error)
1314 goto done;
1315 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1316 break;
1317
1318 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1319 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1320 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1321 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1322 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1323 case RMAP_LEFT_CONTIG:
1324 case RMAP_RIGHT_CONTIG:
1325 /*
1326 * These cases are all impossible.
1327 */
1328 ASSERT(0);
1329 }
1330
1331 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1332 unwritten, oinfo);
1333done:
1334 if (error)
1335 trace_xfs_rmap_convert_error(cur->bc_mp,
1336 cur->bc_private.a.agno, error, _RET_IP_);
1337 return error;
1338}
1339
9c7bc093
DW
1340/*
1341 * Convert an unwritten extent to a real extent or vice versa. If there is no
1342 * possibility of overlapping extents, delegate to the simpler convert
1343 * function.
1344 */
1345STATIC int
1346xfs_rmap_convert_shared(
5837e73b
DW
1347 struct xfs_btree_cur *cur,
1348 xfs_agblock_t bno,
1349 xfs_extlen_t len,
1350 bool unwritten,
1351 const struct xfs_owner_info *oinfo)
9c7bc093 1352{
5837e73b
DW
1353 struct xfs_mount *mp = cur->bc_mp;
1354 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1355 /* left is 0, right is 1, */
1356 /* prev is 2, new is 3 */
9c7bc093
DW
1357 uint64_t owner;
1358 uint64_t offset;
1359 uint64_t new_endoff;
1360 unsigned int oldext;
1361 unsigned int newext;
1362 unsigned int flags = 0;
1363 int i;
1364 int state = 0;
1365 int error;
1366
1367 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1368 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1369 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1370 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1371 new_endoff = offset + len;
1372 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1373 unwritten, oinfo);
1374
1375 /*
1376 * For the initial lookup, look for and exact match or the left-adjacent
1377 * record for our insertion point. This will also give us the record for
1378 * start block contiguity tests.
1379 */
1380 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1381 &PREV, &i);
cfa7d896
DW
1382 if (error)
1383 goto done;
9c7bc093
DW
1384 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1385
1386 ASSERT(PREV.rm_offset <= offset);
1387 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1388 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1389 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1390
1391 /*
1392 * Set flags determining what part of the previous oldext allocation
1393 * extent is being replaced by a newext allocation.
1394 */
1395 if (PREV.rm_offset == offset)
1396 state |= RMAP_LEFT_FILLING;
1397 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1398 state |= RMAP_RIGHT_FILLING;
1399
1400 /* Is there a left record that abuts our range? */
1401 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1402 &LEFT, &i);
1403 if (error)
1404 goto done;
1405 if (i) {
1406 state |= RMAP_LEFT_VALID;
1407 XFS_WANT_CORRUPTED_GOTO(mp,
1408 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1409 done);
1410 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1411 state |= RMAP_LEFT_CONTIG;
1412 }
1413
1414 /* Is there a right record that abuts our range? */
1415 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1416 newext, &i);
1417 if (error)
1418 goto done;
1419 if (i) {
1420 state |= RMAP_RIGHT_VALID;
1421 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1422 if (error)
1423 goto done;
1424 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1425 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1426 done);
1427 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1428 cur->bc_private.a.agno, RIGHT.rm_startblock,
1429 RIGHT.rm_blockcount, RIGHT.rm_owner,
1430 RIGHT.rm_offset, RIGHT.rm_flags);
1431 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1432 state |= RMAP_RIGHT_CONTIG;
1433 }
1434
1435 /* check that left + prev + right is not too long */
1436 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1437 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1438 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1439 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1440 (unsigned long)LEFT.rm_blockcount + len +
1441 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1442 state &= ~RMAP_RIGHT_CONTIG;
1443
1444 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1445 _RET_IP_);
1446 /*
1447 * Switch out based on the FILLING and CONTIG state bits.
1448 */
1449 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1450 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1451 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1452 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1453 /*
1454 * Setting all of a previous oldext extent to newext.
1455 * The left and right neighbors are both contiguous with new.
1456 */
1457 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1458 RIGHT.rm_blockcount, RIGHT.rm_owner,
1459 RIGHT.rm_offset, RIGHT.rm_flags);
1460 if (error)
1461 goto done;
1462 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1463 PREV.rm_blockcount, PREV.rm_owner,
1464 PREV.rm_offset, PREV.rm_flags);
1465 if (error)
1466 goto done;
1467 NEW = LEFT;
1468 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1469 NEW.rm_blockcount, NEW.rm_owner,
1470 NEW.rm_offset, NEW.rm_flags, &i);
1471 if (error)
1472 goto done;
1473 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1474 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1475 error = xfs_rmap_update(cur, &NEW);
1476 if (error)
1477 goto done;
1478 break;
1479
1480 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1481 /*
1482 * Setting all of a previous oldext extent to newext.
1483 * The left neighbor is contiguous, the right is not.
1484 */
1485 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1486 PREV.rm_blockcount, PREV.rm_owner,
1487 PREV.rm_offset, PREV.rm_flags);
1488 if (error)
1489 goto done;
1490 NEW = LEFT;
1491 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1492 NEW.rm_blockcount, NEW.rm_owner,
1493 NEW.rm_offset, NEW.rm_flags, &i);
1494 if (error)
1495 goto done;
1496 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1497 NEW.rm_blockcount += PREV.rm_blockcount;
1498 error = xfs_rmap_update(cur, &NEW);
1499 if (error)
1500 goto done;
1501 break;
1502
1503 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1504 /*
1505 * Setting all of a previous oldext extent to newext.
1506 * The right neighbor is contiguous, the left is not.
1507 */
1508 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1509 RIGHT.rm_blockcount, RIGHT.rm_owner,
1510 RIGHT.rm_offset, RIGHT.rm_flags);
1511 if (error)
1512 goto done;
1513 NEW = PREV;
1514 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1515 NEW.rm_blockcount, NEW.rm_owner,
1516 NEW.rm_offset, NEW.rm_flags, &i);
1517 if (error)
1518 goto done;
1519 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1520 NEW.rm_blockcount += RIGHT.rm_blockcount;
1521 NEW.rm_flags = RIGHT.rm_flags;
1522 error = xfs_rmap_update(cur, &NEW);
1523 if (error)
1524 goto done;
1525 break;
1526
1527 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1528 /*
1529 * Setting all of a previous oldext extent to newext.
1530 * Neither the left nor right neighbors are contiguous with
1531 * the new one.
1532 */
1533 NEW = PREV;
1534 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1535 NEW.rm_blockcount, NEW.rm_owner,
1536 NEW.rm_offset, NEW.rm_flags, &i);
1537 if (error)
1538 goto done;
1539 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1540 NEW.rm_flags = newext;
1541 error = xfs_rmap_update(cur, &NEW);
1542 if (error)
1543 goto done;
1544 break;
1545
1546 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1547 /*
1548 * Setting the first part of a previous oldext extent to newext.
1549 * The left neighbor is contiguous.
1550 */
1551 NEW = PREV;
1552 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1553 NEW.rm_blockcount, NEW.rm_owner,
1554 NEW.rm_offset, NEW.rm_flags);
1555 if (error)
1556 goto done;
1557 NEW.rm_offset += len;
1558 NEW.rm_startblock += len;
1559 NEW.rm_blockcount -= len;
1560 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1561 NEW.rm_blockcount, NEW.rm_owner,
1562 NEW.rm_offset, NEW.rm_flags);
1563 if (error)
1564 goto done;
1565 NEW = LEFT;
1566 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1567 NEW.rm_blockcount, NEW.rm_owner,
1568 NEW.rm_offset, NEW.rm_flags, &i);
1569 if (error)
1570 goto done;
1571 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1572 NEW.rm_blockcount += len;
1573 error = xfs_rmap_update(cur, &NEW);
1574 if (error)
1575 goto done;
1576 break;
1577
1578 case RMAP_LEFT_FILLING:
1579 /*
1580 * Setting the first part of a previous oldext extent to newext.
1581 * The left neighbor is not contiguous.
1582 */
1583 NEW = PREV;
1584 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1585 NEW.rm_blockcount, NEW.rm_owner,
1586 NEW.rm_offset, NEW.rm_flags);
1587 if (error)
1588 goto done;
1589 NEW.rm_offset += len;
1590 NEW.rm_startblock += len;
1591 NEW.rm_blockcount -= len;
1592 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1593 NEW.rm_blockcount, NEW.rm_owner,
1594 NEW.rm_offset, NEW.rm_flags);
1595 if (error)
1596 goto done;
1597 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1598 if (error)
1599 goto done;
1600 break;
1601
1602 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1603 /*
1604 * Setting the last part of a previous oldext extent to newext.
1605 * The right neighbor is contiguous with the new allocation.
1606 */
1607 NEW = PREV;
1608 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1609 NEW.rm_blockcount, NEW.rm_owner,
1610 NEW.rm_offset, NEW.rm_flags, &i);
1611 if (error)
1612 goto done;
1613 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1614 NEW.rm_blockcount = offset - NEW.rm_offset;
1615 error = xfs_rmap_update(cur, &NEW);
1616 if (error)
1617 goto done;
1618 NEW = RIGHT;
1619 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1620 NEW.rm_blockcount, NEW.rm_owner,
1621 NEW.rm_offset, NEW.rm_flags);
1622 if (error)
1623 goto done;
1624 NEW.rm_offset = offset;
1625 NEW.rm_startblock = bno;
1626 NEW.rm_blockcount += len;
1627 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1628 NEW.rm_blockcount, NEW.rm_owner,
1629 NEW.rm_offset, NEW.rm_flags);
1630 if (error)
1631 goto done;
1632 break;
1633
1634 case RMAP_RIGHT_FILLING:
1635 /*
1636 * Setting the last part of a previous oldext extent to newext.
1637 * The right neighbor is not contiguous.
1638 */
1639 NEW = PREV;
1640 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1641 NEW.rm_blockcount, NEW.rm_owner,
1642 NEW.rm_offset, NEW.rm_flags, &i);
1643 if (error)
1644 goto done;
1645 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1646 NEW.rm_blockcount -= len;
1647 error = xfs_rmap_update(cur, &NEW);
1648 if (error)
1649 goto done;
1650 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1651 if (error)
1652 goto done;
1653 break;
1654
1655 case 0:
1656 /*
1657 * Setting the middle part of a previous oldext extent to
1658 * newext. Contiguity is impossible here.
1659 * One extent becomes three extents.
1660 */
1661 /* new right extent - oldext */
1662 NEW.rm_startblock = bno + len;
1663 NEW.rm_owner = owner;
1664 NEW.rm_offset = new_endoff;
1665 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1666 new_endoff;
1667 NEW.rm_flags = PREV.rm_flags;
1668 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1669 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1670 NEW.rm_flags);
1671 if (error)
1672 goto done;
1673 /* new left extent - oldext */
1674 NEW = PREV;
1675 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1676 NEW.rm_blockcount, NEW.rm_owner,
1677 NEW.rm_offset, NEW.rm_flags, &i);
1678 if (error)
1679 goto done;
1680 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1681 NEW.rm_blockcount = offset - NEW.rm_offset;
1682 error = xfs_rmap_update(cur, &NEW);
1683 if (error)
1684 goto done;
1685 /* new middle extent - newext */
1686 NEW.rm_startblock = bno;
1687 NEW.rm_blockcount = len;
1688 NEW.rm_owner = owner;
1689 NEW.rm_offset = offset;
1690 NEW.rm_flags = newext;
1691 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1692 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1693 NEW.rm_flags);
1694 if (error)
1695 goto done;
1696 break;
1697
1698 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1699 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1700 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1701 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1702 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1703 case RMAP_LEFT_CONTIG:
1704 case RMAP_RIGHT_CONTIG:
1705 /*
1706 * These cases are all impossible.
1707 */
1708 ASSERT(0);
1709 }
1710
1711 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1712 unwritten, oinfo);
1713done:
1714 if (error)
1715 trace_xfs_rmap_convert_error(cur->bc_mp,
1716 cur->bc_private.a.agno, error, _RET_IP_);
1717 return error;
1718}
1719
7faf209c
DW
1720#undef NEW
1721#undef LEFT
1722#undef RIGHT
1723#undef PREV
1724
6c6bdf6f
DW
1725/*
1726 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1727 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1728 * that the prev/next records in the btree might belong to another owner.
1729 * Therefore we must use delete+insert to alter any of the key fields.
1730 *
1731 * For every other situation there can only be one owner for a given extent,
1732 * so we can call the regular _free function.
1733 */
1734STATIC int
1735xfs_rmap_unmap_shared(
5837e73b
DW
1736 struct xfs_btree_cur *cur,
1737 xfs_agblock_t bno,
1738 xfs_extlen_t len,
1739 bool unwritten,
1740 const struct xfs_owner_info *oinfo)
6c6bdf6f 1741{
5837e73b
DW
1742 struct xfs_mount *mp = cur->bc_mp;
1743 struct xfs_rmap_irec ltrec;
1744 uint64_t ltoff;
1745 int error = 0;
1746 int i;
1747 uint64_t owner;
1748 uint64_t offset;
1749 unsigned int flags;
6c6bdf6f
DW
1750
1751 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1752 if (unwritten)
1753 flags |= XFS_RMAP_UNWRITTEN;
1754 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1755 unwritten, oinfo);
1756
1757 /*
1758 * We should always have a left record because there's a static record
1759 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1760 * will not ever be removed from the tree.
1761 */
1762 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1763 &ltrec, &i);
1764 if (error)
1765 goto out_error;
1766 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1767 ltoff = ltrec.rm_offset;
1768
1769 /* Make sure the extent we found covers the entire freeing range. */
1770 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1771 ltrec.rm_startblock + ltrec.rm_blockcount >=
1772 bno + len, out_error);
1773
1774 /* Make sure the owner matches what we expect to find in the tree. */
1775 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1776
1777 /* Make sure the unwritten flag matches. */
1778 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1779 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1780
1781 /* Check the offset. */
1782 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1783 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1784 out_error);
1785
1786 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1787 /* Exact match, simply remove the record from rmap tree. */
1788 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1789 ltrec.rm_blockcount, ltrec.rm_owner,
1790 ltrec.rm_offset, ltrec.rm_flags);
1791 if (error)
1792 goto out_error;
1793 } else if (ltrec.rm_startblock == bno) {
1794 /*
1795 * Overlap left hand side of extent: move the start, trim the
1796 * length and update the current record.
1797 *
1798 * ltbno ltlen
1799 * Orig: |oooooooooooooooooooo|
1800 * Freeing: |fffffffff|
1801 * Result: |rrrrrrrrrr|
1802 * bno len
1803 */
1804
1805 /* Delete prev rmap. */
1806 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1807 ltrec.rm_blockcount, ltrec.rm_owner,
1808 ltrec.rm_offset, ltrec.rm_flags);
1809 if (error)
1810 goto out_error;
1811
1812 /* Add an rmap at the new offset. */
1813 ltrec.rm_startblock += len;
1814 ltrec.rm_blockcount -= len;
1815 ltrec.rm_offset += len;
1816 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1817 ltrec.rm_blockcount, ltrec.rm_owner,
1818 ltrec.rm_offset, ltrec.rm_flags);
1819 if (error)
1820 goto out_error;
1821 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1822 /*
1823 * Overlap right hand side of extent: trim the length and
1824 * update the current record.
1825 *
1826 * ltbno ltlen
1827 * Orig: |oooooooooooooooooooo|
1828 * Freeing: |fffffffff|
1829 * Result: |rrrrrrrrrr|
1830 * bno len
1831 */
1832 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1833 ltrec.rm_blockcount, ltrec.rm_owner,
1834 ltrec.rm_offset, ltrec.rm_flags, &i);
1835 if (error)
1836 goto out_error;
1837 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1838 ltrec.rm_blockcount -= len;
1839 error = xfs_rmap_update(cur, &ltrec);
1840 if (error)
1841 goto out_error;
1842 } else {
1843 /*
1844 * Overlap middle of extent: trim the length of the existing
1845 * record to the length of the new left-extent size, increment
1846 * the insertion position so we can insert a new record
1847 * containing the remaining right-extent space.
1848 *
1849 * ltbno ltlen
1850 * Orig: |oooooooooooooooooooo|
1851 * Freeing: |fffffffff|
1852 * Result: |rrrrr| |rrrr|
1853 * bno len
1854 */
1855 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1856
1857 /* Shrink the left side of the rmap */
1858 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1859 ltrec.rm_blockcount, ltrec.rm_owner,
1860 ltrec.rm_offset, ltrec.rm_flags, &i);
1861 if (error)
1862 goto out_error;
1863 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1864 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1865 error = xfs_rmap_update(cur, &ltrec);
1866 if (error)
1867 goto out_error;
1868
1869 /* Add an rmap at the new offset */
1870 error = xfs_rmap_insert(cur, bno + len,
1871 orig_len - len - ltrec.rm_blockcount,
1872 ltrec.rm_owner, offset + len,
1873 ltrec.rm_flags);
1874 if (error)
1875 goto out_error;
1876 }
1877
1878 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1879 unwritten, oinfo);
1880out_error:
1881 if (error)
1882 trace_xfs_rmap_unmap_error(cur->bc_mp,
1883 cur->bc_private.a.agno, error, _RET_IP_);
1884 return error;
1885}
1886
1887/*
1888 * Find an extent in the rmap btree and map it. For rmap extent types that
1889 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1890 * that the prev/next records in the btree might belong to another owner.
1891 * Therefore we must use delete+insert to alter any of the key fields.
1892 *
1893 * For every other situation there can only be one owner for a given extent,
1894 * so we can call the regular _alloc function.
1895 */
1896STATIC int
1897xfs_rmap_map_shared(
5837e73b
DW
1898 struct xfs_btree_cur *cur,
1899 xfs_agblock_t bno,
1900 xfs_extlen_t len,
1901 bool unwritten,
1902 const struct xfs_owner_info *oinfo)
6c6bdf6f 1903{
5837e73b
DW
1904 struct xfs_mount *mp = cur->bc_mp;
1905 struct xfs_rmap_irec ltrec;
1906 struct xfs_rmap_irec gtrec;
1907 int have_gt;
1908 int have_lt;
1909 int error = 0;
1910 int i;
1911 uint64_t owner;
1912 uint64_t offset;
1913 unsigned int flags = 0;
6c6bdf6f
DW
1914
1915 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1916 if (unwritten)
1917 flags |= XFS_RMAP_UNWRITTEN;
1918 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1919 unwritten, oinfo);
1920
1921 /* Is there a left record that abuts our range? */
1922 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1923 &ltrec, &have_lt);
1924 if (error)
1925 goto out_error;
1926 if (have_lt &&
1927 !xfs_rmap_is_mergeable(&ltrec, owner, flags))
1928 have_lt = 0;
1929
1930 /* Is there a right record that abuts our range? */
1931 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1932 flags, &have_gt);
1933 if (error)
1934 goto out_error;
1935 if (have_gt) {
1936 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
1937 if (error)
1938 goto out_error;
1939 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1940 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1941 cur->bc_private.a.agno, gtrec.rm_startblock,
1942 gtrec.rm_blockcount, gtrec.rm_owner,
1943 gtrec.rm_offset, gtrec.rm_flags);
1944
1945 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
1946 have_gt = 0;
1947 }
1948
1949 if (have_lt &&
1950 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1951 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1952 /*
1953 * Left edge contiguous, merge into left record.
1954 *
1955 * ltbno ltlen
1956 * orig: |ooooooooo|
1957 * adding: |aaaaaaaaa|
1958 * result: |rrrrrrrrrrrrrrrrrrr|
1959 * bno len
1960 */
1961 ltrec.rm_blockcount += len;
1962 if (have_gt &&
1963 bno + len == gtrec.rm_startblock &&
1964 offset + len == gtrec.rm_offset) {
1965 /*
1966 * Right edge also contiguous, delete right record
1967 * and merge into left record.
1968 *
1969 * ltbno ltlen gtbno gtlen
1970 * orig: |ooooooooo| |ooooooooo|
1971 * adding: |aaaaaaaaa|
1972 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1973 */
1974 ltrec.rm_blockcount += gtrec.rm_blockcount;
1975 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1976 gtrec.rm_blockcount, gtrec.rm_owner,
1977 gtrec.rm_offset, gtrec.rm_flags);
1978 if (error)
1979 goto out_error;
1980 }
1981
1982 /* Point the cursor back to the left record and update. */
1983 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1984 ltrec.rm_blockcount, ltrec.rm_owner,
1985 ltrec.rm_offset, ltrec.rm_flags, &i);
1986 if (error)
1987 goto out_error;
1988 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1989
1990 error = xfs_rmap_update(cur, &ltrec);
1991 if (error)
1992 goto out_error;
1993 } else if (have_gt &&
1994 bno + len == gtrec.rm_startblock &&
1995 offset + len == gtrec.rm_offset) {
1996 /*
1997 * Right edge contiguous, merge into right record.
1998 *
1999 * gtbno gtlen
2000 * Orig: |ooooooooo|
2001 * adding: |aaaaaaaaa|
2002 * Result: |rrrrrrrrrrrrrrrrrrr|
2003 * bno len
2004 */
2005 /* Delete the old record. */
2006 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2007 gtrec.rm_blockcount, gtrec.rm_owner,
2008 gtrec.rm_offset, gtrec.rm_flags);
2009 if (error)
2010 goto out_error;
2011
2012 /* Move the start and re-add it. */
2013 gtrec.rm_startblock = bno;
2014 gtrec.rm_blockcount += len;
2015 gtrec.rm_offset = offset;
2016 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2017 gtrec.rm_blockcount, gtrec.rm_owner,
2018 gtrec.rm_offset, gtrec.rm_flags);
2019 if (error)
2020 goto out_error;
2021 } else {
2022 /*
2023 * No contiguous edge with identical owner, insert
2024 * new record at current cursor position.
2025 */
2026 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2027 if (error)
2028 goto out_error;
2029 }
2030
2031 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2032 unwritten, oinfo);
2033out_error:
2034 if (error)
2035 trace_xfs_rmap_map_error(cur->bc_mp,
2036 cur->bc_private.a.agno, error, _RET_IP_);
2037 return error;
2038}
2039
d264e392
DW
2040/* Insert a raw rmap into the rmapbt. */
2041int
2042xfs_rmap_map_raw(
2043 struct xfs_btree_cur *cur,
2044 struct xfs_rmap_irec *rmap)
2045{
2046 struct xfs_owner_info oinfo;
2047
2048 oinfo.oi_owner = rmap->rm_owner;
2049 oinfo.oi_offset = rmap->rm_offset;
2050 oinfo.oi_flags = 0;
2051 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2052 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2053 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2054 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2055
2056 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2057 return xfs_rmap_map(cur, rmap->rm_startblock,
2058 rmap->rm_blockcount,
2059 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2060 &oinfo);
2061
2062 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2063 rmap->rm_blockcount,
2064 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2065 &oinfo);
2066}
2067
890e1174
DW
2068struct xfs_rmap_query_range_info {
2069 xfs_rmap_query_range_fn fn;
2070 void *priv;
2071};
2072
2073/* Format btree record and pass to our callback. */
2074STATIC int
2075xfs_rmap_query_range_helper(
2076 struct xfs_btree_cur *cur,
2077 union xfs_btree_rec *rec,
2078 void *priv)
2079{
2080 struct xfs_rmap_query_range_info *query = priv;
2081 struct xfs_rmap_irec irec;
2082 int error;
2083
2084 error = xfs_rmap_btrec_to_irec(rec, &irec);
2085 if (error)
2086 return error;
2087 return query->fn(cur, &irec, query->priv);
2088}
2089
2090/* Find all rmaps between two keys. */
2091int
2092xfs_rmap_query_range(
7e05e856
DW
2093 struct xfs_btree_cur *cur,
2094 struct xfs_rmap_irec *low_rec,
2095 struct xfs_rmap_irec *high_rec,
2096 xfs_rmap_query_range_fn fn,
2097 void *priv)
890e1174 2098{
7e05e856
DW
2099 union xfs_btree_irec low_brec;
2100 union xfs_btree_irec high_brec;
890e1174
DW
2101 struct xfs_rmap_query_range_info query;
2102
2103 low_brec.r = *low_rec;
2104 high_brec.r = *high_rec;
2105 query.priv = priv;
2106 query.fn = fn;
2107 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2108 xfs_rmap_query_range_helper, &query);
2109}
d7f80320 2110
7e05e856
DW
2111/* Find all rmaps. */
2112int
2113xfs_rmap_query_all(
2114 struct xfs_btree_cur *cur,
2115 xfs_rmap_query_range_fn fn,
2116 void *priv)
2117{
2118 struct xfs_rmap_query_range_info query;
2119
2120 query.priv = priv;
2121 query.fn = fn;
2122 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2123}
2124
d7f80320
DW
2125/* Clean up after calling xfs_rmap_finish_one. */
2126void
2127xfs_rmap_finish_one_cleanup(
2128 struct xfs_trans *tp,
2129 struct xfs_btree_cur *rcur,
2130 int error)
2131{
2132 struct xfs_buf *agbp;
2133
2134 if (rcur == NULL)
2135 return;
2136 agbp = rcur->bc_private.a.agbp;
660265b7 2137 xfs_btree_del_cursor(rcur, error);
d7f80320
DW
2138 if (error)
2139 xfs_trans_brelse(tp, agbp);
2140}
2141
2142/*
2143 * Process one of the deferred rmap operations. We pass back the
2144 * btree cursor to maintain our lock on the rmapbt between calls.
2145 * This saves time and eliminates a buffer deadlock between the
2146 * superblock and the AGF because we'll always grab them in the same
2147 * order.
2148 */
2149int
2150xfs_rmap_finish_one(
2151 struct xfs_trans *tp,
2152 enum xfs_rmap_intent_type type,
4a492e72 2153 uint64_t owner,
d7f80320
DW
2154 int whichfork,
2155 xfs_fileoff_t startoff,
2156 xfs_fsblock_t startblock,
2157 xfs_filblks_t blockcount,
2158 xfs_exntst_t state,
2159 struct xfs_btree_cur **pcur)
2160{
2161 struct xfs_mount *mp = tp->t_mountp;
2162 struct xfs_btree_cur *rcur;
2163 struct xfs_buf *agbp = NULL;
2164 int error = 0;
2165 xfs_agnumber_t agno;
2166 struct xfs_owner_info oinfo;
2167 xfs_agblock_t bno;
2168 bool unwritten;
2169
2170 agno = XFS_FSB_TO_AGNO(mp, startblock);
2171 ASSERT(agno != NULLAGNUMBER);
2172 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2173
2174 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2175 startoff, blockcount, state);
2176
2177 if (XFS_TEST_ERROR(false, mp,
e2a190dd 2178 XFS_ERRTAG_RMAP_FINISH_ONE))
d7f80320
DW
2179 return -EIO;
2180
2181 /*
2182 * If we haven't gotten a cursor or the cursor AG doesn't match
2183 * the startblock, get one now.
2184 */
2185 rcur = *pcur;
2186 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2187 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2188 rcur = NULL;
2189 *pcur = NULL;
2190 }
2191 if (rcur == NULL) {
2192 /*
2193 * Refresh the freelist before we start changing the
2194 * rmapbt, because a shape change could cause us to
2195 * allocate blocks.
2196 */
2197 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2198 if (error)
2199 return error;
2200 if (!agbp)
2201 return -EFSCORRUPTED;
2202
2203 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2204 if (!rcur) {
2205 error = -ENOMEM;
2206 goto out_cur;
2207 }
2208 }
2209 *pcur = rcur;
2210
2211 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2212 unwritten = state == XFS_EXT_UNWRITTEN;
2213 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2214
2215 switch (type) {
2216 case XFS_RMAP_ALLOC:
2217 case XFS_RMAP_MAP:
2218 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2219 break;
6c6bdf6f
DW
2220 case XFS_RMAP_MAP_SHARED:
2221 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2222 &oinfo);
2223 break;
d7f80320
DW
2224 case XFS_RMAP_FREE:
2225 case XFS_RMAP_UNMAP:
2226 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2227 &oinfo);
2228 break;
6c6bdf6f
DW
2229 case XFS_RMAP_UNMAP_SHARED:
2230 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2231 &oinfo);
2232 break;
d7f80320
DW
2233 case XFS_RMAP_CONVERT:
2234 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2235 &oinfo);
2236 break;
9c7bc093
DW
2237 case XFS_RMAP_CONVERT_SHARED:
2238 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2239 !unwritten, &oinfo);
2240 break;
d7f80320
DW
2241 default:
2242 ASSERT(0);
2243 error = -EFSCORRUPTED;
2244 }
2245 return error;
2246
2247out_cur:
2248 xfs_trans_brelse(tp, agbp);
2249
2250 return error;
2251}
2252
2253/*
2254 * Don't defer an rmap if we aren't an rmap filesystem.
2255 */
2256static bool
2257xfs_rmap_update_is_needed(
cb8a004a
DW
2258 struct xfs_mount *mp,
2259 int whichfork)
d7f80320 2260{
cb8a004a 2261 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
d7f80320
DW
2262}
2263
2264/*
2265 * Record a rmap intent; the list is kept sorted first by AG and then by
2266 * increasing age.
2267 */
46d29bb9 2268static void
d7f80320 2269__xfs_rmap_add(
21375e5d 2270 struct xfs_trans *tp,
d7f80320 2271 enum xfs_rmap_intent_type type,
4a492e72 2272 uint64_t owner,
d7f80320
DW
2273 int whichfork,
2274 struct xfs_bmbt_irec *bmap)
2275{
21375e5d 2276 struct xfs_rmap_intent *ri;
d7f80320 2277
21375e5d
BF
2278 trace_xfs_rmap_defer(tp->t_mountp,
2279 XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
d7f80320 2280 type,
21375e5d 2281 XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
d7f80320
DW
2282 owner, whichfork,
2283 bmap->br_startoff,
2284 bmap->br_blockcount,
2285 bmap->br_state);
2286
6cd1e6db 2287 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_NOFS);
d7f80320
DW
2288 INIT_LIST_HEAD(&ri->ri_list);
2289 ri->ri_type = type;
2290 ri->ri_owner = owner;
2291 ri->ri_whichfork = whichfork;
2292 ri->ri_bmap = *bmap;
2293
21375e5d 2294 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
d7f80320
DW
2295}
2296
2297/* Map an extent into a file. */
46d29bb9 2298void
d7f80320 2299xfs_rmap_map_extent(
21375e5d 2300 struct xfs_trans *tp,
d7f80320
DW
2301 struct xfs_inode *ip,
2302 int whichfork,
2303 struct xfs_bmbt_irec *PREV)
2304{
21375e5d 2305 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
46d29bb9 2306 return;
d7f80320 2307
46d29bb9 2308 __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
6c6bdf6f 2309 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
d7f80320
DW
2310 whichfork, PREV);
2311}
2312
2313/* Unmap an extent out of a file. */
46d29bb9 2314void
d7f80320 2315xfs_rmap_unmap_extent(
21375e5d 2316 struct xfs_trans *tp,
d7f80320
DW
2317 struct xfs_inode *ip,
2318 int whichfork,
2319 struct xfs_bmbt_irec *PREV)
2320{
21375e5d 2321 if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
46d29bb9 2322 return;
d7f80320 2323
46d29bb9 2324 __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
6c6bdf6f 2325 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
d7f80320
DW
2326 whichfork, PREV);
2327}
2328
21375e5d
BF
2329/*
2330 * Convert a data fork extent from unwritten to real or vice versa.
2331 *
2332 * Note that tp can be NULL here as no transaction is used for COW fork
2333 * unwritten conversion.
2334 */
46d29bb9 2335void
d7f80320
DW
2336xfs_rmap_convert_extent(
2337 struct xfs_mount *mp,
21375e5d 2338 struct xfs_trans *tp,
d7f80320
DW
2339 struct xfs_inode *ip,
2340 int whichfork,
2341 struct xfs_bmbt_irec *PREV)
2342{
cb8a004a 2343 if (!xfs_rmap_update_is_needed(mp, whichfork))
46d29bb9 2344 return;
d7f80320 2345
46d29bb9 2346 __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
9c7bc093 2347 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
d7f80320
DW
2348 whichfork, PREV);
2349}
2350
2351/* Schedule the creation of an rmap for non-file data. */
46d29bb9 2352void
d7f80320 2353xfs_rmap_alloc_extent(
21375e5d 2354 struct xfs_trans *tp,
d7f80320
DW
2355 xfs_agnumber_t agno,
2356 xfs_agblock_t bno,
2357 xfs_extlen_t len,
4a492e72 2358 uint64_t owner)
d7f80320
DW
2359{
2360 struct xfs_bmbt_irec bmap;
2361
21375e5d 2362 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
46d29bb9 2363 return;
d7f80320 2364
21375e5d 2365 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
d7f80320
DW
2366 bmap.br_blockcount = len;
2367 bmap.br_startoff = 0;
2368 bmap.br_state = XFS_EXT_NORM;
2369
46d29bb9 2370 __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
d7f80320
DW
2371}
2372
2373/* Schedule the deletion of an rmap for non-file data. */
46d29bb9 2374void
d7f80320 2375xfs_rmap_free_extent(
21375e5d 2376 struct xfs_trans *tp,
d7f80320
DW
2377 xfs_agnumber_t agno,
2378 xfs_agblock_t bno,
2379 xfs_extlen_t len,
4a492e72 2380 uint64_t owner)
d7f80320
DW
2381{
2382 struct xfs_bmbt_irec bmap;
2383
21375e5d 2384 if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
46d29bb9 2385 return;
d7f80320 2386
21375e5d 2387 bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
d7f80320
DW
2388 bmap.br_blockcount = len;
2389 bmap.br_startoff = 0;
2390 bmap.br_state = XFS_EXT_NORM;
2391
46d29bb9 2392 __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
d7f80320 2393}
9282c506
DW
2394
2395/* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2396int
2397xfs_rmap_compare(
2398 const struct xfs_rmap_irec *a,
2399 const struct xfs_rmap_irec *b)
2400{
2401 __u64 oa;
2402 __u64 ob;
2403
2404 oa = xfs_rmap_irec_offset_pack(a);
2405 ob = xfs_rmap_irec_offset_pack(b);
2406
2407 if (a->rm_startblock < b->rm_startblock)
2408 return -1;
2409 else if (a->rm_startblock > b->rm_startblock)
2410 return 1;
2411 else if (a->rm_owner < b->rm_owner)
2412 return -1;
2413 else if (a->rm_owner > b->rm_owner)
2414 return 1;
2415 else if (oa < ob)
2416 return -1;
2417 else if (oa > ob)
2418 return 1;
2419 else
2420 return 0;
2421}
556c739d
DW
2422
2423/* Is there a record covering a given extent? */
2424int
2425xfs_rmap_has_record(
2426 struct xfs_btree_cur *cur,
2427 xfs_agblock_t bno,
2428 xfs_extlen_t len,
2429 bool *exists)
2430{
2431 union xfs_btree_irec low;
2432 union xfs_btree_irec high;
2433
2434 memset(&low, 0, sizeof(low));
2435 low.r.rm_startblock = bno;
2436 memset(&high, 0xFF, sizeof(high));
2437 high.r.rm_startblock = bno + len - 1;
2438
2439 return xfs_btree_has_record(cur, &low, &high, exists);
2440}
2441
2442/*
2443 * Is there a record for this owner completely covering a given physical
2444 * extent? If so, *has_rmap will be set to true. If there is no record
2445 * or the record only covers part of the range, we set *has_rmap to false.
2446 * This function doesn't perform range lookups or offset checks, so it is
2447 * not suitable for checking data fork blocks.
2448 */
2449int
2450xfs_rmap_record_exists(
5837e73b
DW
2451 struct xfs_btree_cur *cur,
2452 xfs_agblock_t bno,
2453 xfs_extlen_t len,
2454 const struct xfs_owner_info *oinfo,
2455 bool *has_rmap)
556c739d 2456{
5837e73b
DW
2457 uint64_t owner;
2458 uint64_t offset;
2459 unsigned int flags;
2460 int has_record;
2461 struct xfs_rmap_irec irec;
2462 int error;
556c739d
DW
2463
2464 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2465 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2466 (flags & XFS_RMAP_BMBT_BLOCK));
2467
2468 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2469 &has_record);
2470 if (error)
2471 return error;
2472 if (!has_record) {
2473 *has_rmap = false;
2474 return 0;
2475 }
2476
2477 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2478 if (error)
2479 return error;
2480 if (!has_record) {
2481 *has_rmap = false;
2482 return 0;
2483 }
2484
2485 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2486 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2487 return 0;
2488}
d264e392
DW
2489
2490struct xfs_rmap_key_state {
2491 uint64_t owner;
2492 uint64_t offset;
2493 unsigned int flags;
2494 bool has_rmap;
2495};
2496
2497/* For each rmap given, figure out if it doesn't match the key we want. */
2498STATIC int
2499xfs_rmap_has_other_keys_helper(
2500 struct xfs_btree_cur *cur,
2501 struct xfs_rmap_irec *rec,
2502 void *priv)
2503{
2504 struct xfs_rmap_key_state *rks = priv;
2505
2506 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2507 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2508 return 0;
2509 rks->has_rmap = true;
a0f17dde 2510 return -ECANCELED;
d264e392
DW
2511}
2512
2513/*
2514 * Given an extent and some owner info, can we find records overlapping
2515 * the extent whose owner info does not match the given owner?
2516 */
2517int
2518xfs_rmap_has_other_keys(
2519 struct xfs_btree_cur *cur,
2520 xfs_agblock_t bno,
2521 xfs_extlen_t len,
5837e73b 2522 const struct xfs_owner_info *oinfo,
d264e392
DW
2523 bool *has_rmap)
2524{
2525 struct xfs_rmap_irec low = {0};
2526 struct xfs_rmap_irec high;
2527 struct xfs_rmap_key_state rks;
2528 int error;
2529
2530 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2531 rks.has_rmap = false;
2532
2533 low.rm_startblock = bno;
2534 memset(&high, 0xFF, sizeof(high));
2535 high.rm_startblock = bno + len - 1;
2536
2537 error = xfs_rmap_query_range(cur, &low, &high,
2538 xfs_rmap_has_other_keys_helper, &rks);
6c3013ad
DW
2539 if (error < 0)
2540 return error;
2541
d264e392 2542 *has_rmap = rks.has_rmap;
6c3013ad 2543 return 0;
d264e392 2544}
007347e3
DW
2545
2546const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2547 .oi_owner = XFS_RMAP_OWN_NULL,
2548};
2549const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2550 .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2551};
2552const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2553 .oi_owner = XFS_RMAP_OWN_FS,
2554};
2555const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2556 .oi_owner = XFS_RMAP_OWN_LOG,
2557};
2558const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2559 .oi_owner = XFS_RMAP_OWN_AG,
2560};
2561const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2562 .oi_owner = XFS_RMAP_OWN_INOBT,
2563};
2564const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2565 .oi_owner = XFS_RMAP_OWN_INODES,
2566};
2567const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2568 .oi_owner = XFS_RMAP_OWN_REFC,
2569};
2570const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2571 .oi_owner = XFS_RMAP_OWN_COW,
2572};