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