]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/xfs_rmap.c
xfs: fix transaction leak on remote attr set/remove failure
[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
672 xfs_btree_del_cursor(cur, error);
673 return error;
674 }
675
676 /*
677 * A mergeable rmap must have the same owner and the same values for
678 * the unwritten, attr_fork, and bmbt flags. The startblock and
679 * offset are checked separately.
680 */
681 static bool
682 xfs_rmap_is_mergeable(
683 struct xfs_rmap_irec *irec,
684 uint64_t owner,
685 unsigned int flags)
686 {
687 if (irec->rm_owner == XFS_RMAP_OWN_NULL)
688 return false;
689 if (irec->rm_owner != owner)
690 return false;
691 if ((flags & XFS_RMAP_UNWRITTEN) ^
692 (irec->rm_flags & XFS_RMAP_UNWRITTEN))
693 return false;
694 if ((flags & XFS_RMAP_ATTR_FORK) ^
695 (irec->rm_flags & XFS_RMAP_ATTR_FORK))
696 return false;
697 if ((flags & XFS_RMAP_BMBT_BLOCK) ^
698 (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
699 return false;
700 return true;
701 }
702
703 /*
704 * When we allocate a new block, the first thing we do is add a reference to
705 * the extent in the rmap btree. This takes the form of a [agbno, length,
706 * owner, offset] record. Flags are encoded in the high bits of the offset
707 * field.
708 */
709 STATIC int
710 xfs_rmap_map(
711 struct xfs_btree_cur *cur,
712 xfs_agblock_t bno,
713 xfs_extlen_t len,
714 bool unwritten,
715 struct xfs_owner_info *oinfo)
716 {
717 struct xfs_mount *mp = cur->bc_mp;
718 struct xfs_rmap_irec ltrec;
719 struct xfs_rmap_irec gtrec;
720 int have_gt;
721 int have_lt;
722 int error = 0;
723 int i;
724 uint64_t owner;
725 uint64_t offset;
726 unsigned int flags = 0;
727 bool ignore_off;
728
729 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
730 ASSERT(owner != 0);
731 ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
732 (flags & XFS_RMAP_BMBT_BLOCK);
733 if (unwritten)
734 flags |= XFS_RMAP_UNWRITTEN;
735 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
736 unwritten, oinfo);
737 ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
738
739 /*
740 * For the initial lookup, look for an exact match or the left-adjacent
741 * record for our insertion point. This will also give us the record for
742 * start block contiguity tests.
743 */
744 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
745 &have_lt);
746 if (error)
747 goto out_error;
748 if (have_lt) {
749 error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
750 if (error)
751 goto out_error;
752 XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
753 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
754 cur->bc_private.a.agno, ltrec.rm_startblock,
755 ltrec.rm_blockcount, ltrec.rm_owner,
756 ltrec.rm_offset, ltrec.rm_flags);
757
758 if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
759 have_lt = 0;
760 }
761
762 XFS_WANT_CORRUPTED_GOTO(mp,
763 have_lt == 0 ||
764 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
765
766 /*
767 * Increment the cursor to see if we have a right-adjacent record to our
768 * insertion point. This will give us the record for end block
769 * contiguity tests.
770 */
771 error = xfs_btree_increment(cur, 0, &have_gt);
772 if (error)
773 goto out_error;
774 if (have_gt) {
775 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
776 if (error)
777 goto out_error;
778 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
779 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
780 out_error);
781 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
782 cur->bc_private.a.agno, gtrec.rm_startblock,
783 gtrec.rm_blockcount, gtrec.rm_owner,
784 gtrec.rm_offset, gtrec.rm_flags);
785 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
786 have_gt = 0;
787 }
788
789 /*
790 * Note: cursor currently points one record to the right of ltrec, even
791 * if there is no record in the tree to the right.
792 */
793 if (have_lt &&
794 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
795 (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
796 /*
797 * left edge contiguous, merge into left record.
798 *
799 * ltbno ltlen
800 * orig: |ooooooooo|
801 * adding: |aaaaaaaaa|
802 * result: |rrrrrrrrrrrrrrrrrrr|
803 * bno len
804 */
805 ltrec.rm_blockcount += len;
806 if (have_gt &&
807 bno + len == gtrec.rm_startblock &&
808 (ignore_off || offset + len == gtrec.rm_offset) &&
809 (unsigned long)ltrec.rm_blockcount + len +
810 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
811 /*
812 * right edge also contiguous, delete right record
813 * and merge into left record.
814 *
815 * ltbno ltlen gtbno gtlen
816 * orig: |ooooooooo| |ooooooooo|
817 * adding: |aaaaaaaaa|
818 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
819 */
820 ltrec.rm_blockcount += gtrec.rm_blockcount;
821 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
822 gtrec.rm_startblock,
823 gtrec.rm_blockcount,
824 gtrec.rm_owner,
825 gtrec.rm_offset,
826 gtrec.rm_flags);
827 error = xfs_btree_delete(cur, &i);
828 if (error)
829 goto out_error;
830 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
831 }
832
833 /* point the cursor back to the left record and update */
834 error = xfs_btree_decrement(cur, 0, &have_gt);
835 if (error)
836 goto out_error;
837 error = xfs_rmap_update(cur, &ltrec);
838 if (error)
839 goto out_error;
840 } else if (have_gt &&
841 bno + len == gtrec.rm_startblock &&
842 (ignore_off || offset + len == gtrec.rm_offset)) {
843 /*
844 * right edge contiguous, merge into right record.
845 *
846 * gtbno gtlen
847 * Orig: |ooooooooo|
848 * adding: |aaaaaaaaa|
849 * Result: |rrrrrrrrrrrrrrrrrrr|
850 * bno len
851 */
852 gtrec.rm_startblock = bno;
853 gtrec.rm_blockcount += len;
854 if (!ignore_off)
855 gtrec.rm_offset = offset;
856 error = xfs_rmap_update(cur, &gtrec);
857 if (error)
858 goto out_error;
859 } else {
860 /*
861 * no contiguous edge with identical owner, insert
862 * new record at current cursor position.
863 */
864 cur->bc_rec.r.rm_startblock = bno;
865 cur->bc_rec.r.rm_blockcount = len;
866 cur->bc_rec.r.rm_owner = owner;
867 cur->bc_rec.r.rm_offset = offset;
868 cur->bc_rec.r.rm_flags = flags;
869 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
870 owner, offset, flags);
871 error = xfs_btree_insert(cur, &i);
872 if (error)
873 goto out_error;
874 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
875 }
876
877 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
878 unwritten, oinfo);
879 out_error:
880 if (error)
881 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
882 error, _RET_IP_);
883 return error;
884 }
885
886 /*
887 * Add a reference to an extent in the rmap btree.
888 */
889 int
890 xfs_rmap_alloc(
891 struct xfs_trans *tp,
892 struct xfs_buf *agbp,
893 xfs_agnumber_t agno,
894 xfs_agblock_t bno,
895 xfs_extlen_t len,
896 struct xfs_owner_info *oinfo)
897 {
898 struct xfs_mount *mp = tp->t_mountp;
899 struct xfs_btree_cur *cur;
900 int error;
901
902 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
903 return 0;
904
905 cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
906 error = xfs_rmap_map(cur, bno, len, false, oinfo);
907
908 xfs_btree_del_cursor(cur, error);
909 return error;
910 }
911
912 #define RMAP_LEFT_CONTIG (1 << 0)
913 #define RMAP_RIGHT_CONTIG (1 << 1)
914 #define RMAP_LEFT_FILLING (1 << 2)
915 #define RMAP_RIGHT_FILLING (1 << 3)
916 #define RMAP_LEFT_VALID (1 << 6)
917 #define RMAP_RIGHT_VALID (1 << 7)
918
919 #define LEFT r[0]
920 #define RIGHT r[1]
921 #define PREV r[2]
922 #define NEW r[3]
923
924 /*
925 * Convert an unwritten extent to a real extent or vice versa.
926 * Does not handle overlapping extents.
927 */
928 STATIC int
929 xfs_rmap_convert(
930 struct xfs_btree_cur *cur,
931 xfs_agblock_t bno,
932 xfs_extlen_t len,
933 bool unwritten,
934 struct xfs_owner_info *oinfo)
935 {
936 struct xfs_mount *mp = cur->bc_mp;
937 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
938 /* left is 0, right is 1, prev is 2 */
939 /* new is 3 */
940 uint64_t owner;
941 uint64_t offset;
942 uint64_t new_endoff;
943 unsigned int oldext;
944 unsigned int newext;
945 unsigned int flags = 0;
946 int i;
947 int state = 0;
948 int error;
949
950 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
951 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
952 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
953 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
954 new_endoff = offset + len;
955 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
956 unwritten, oinfo);
957
958 /*
959 * For the initial lookup, look for an exact match or the left-adjacent
960 * record for our insertion point. This will also give us the record for
961 * start block contiguity tests.
962 */
963 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
964 if (error)
965 goto done;
966 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
967
968 error = xfs_rmap_get_rec(cur, &PREV, &i);
969 if (error)
970 goto done;
971 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
972 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
973 cur->bc_private.a.agno, PREV.rm_startblock,
974 PREV.rm_blockcount, PREV.rm_owner,
975 PREV.rm_offset, PREV.rm_flags);
976
977 ASSERT(PREV.rm_offset <= offset);
978 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
979 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
980 newext = ~oldext & XFS_RMAP_UNWRITTEN;
981
982 /*
983 * Set flags determining what part of the previous oldext allocation
984 * extent is being replaced by a newext allocation.
985 */
986 if (PREV.rm_offset == offset)
987 state |= RMAP_LEFT_FILLING;
988 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
989 state |= RMAP_RIGHT_FILLING;
990
991 /*
992 * Decrement the cursor to see if we have a left-adjacent record to our
993 * insertion point. This will give us the record for end block
994 * contiguity tests.
995 */
996 error = xfs_btree_decrement(cur, 0, &i);
997 if (error)
998 goto done;
999 if (i) {
1000 state |= RMAP_LEFT_VALID;
1001 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1002 if (error)
1003 goto done;
1004 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1005 XFS_WANT_CORRUPTED_GOTO(mp,
1006 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1007 done);
1008 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1009 cur->bc_private.a.agno, LEFT.rm_startblock,
1010 LEFT.rm_blockcount, LEFT.rm_owner,
1011 LEFT.rm_offset, LEFT.rm_flags);
1012 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1013 LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1014 xfs_rmap_is_mergeable(&LEFT, owner, newext))
1015 state |= RMAP_LEFT_CONTIG;
1016 }
1017
1018 /*
1019 * Increment the cursor to see if we have a right-adjacent record to our
1020 * insertion point. This will give us the record for end block
1021 * contiguity tests.
1022 */
1023 error = xfs_btree_increment(cur, 0, &i);
1024 if (error)
1025 goto done;
1026 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1027 error = xfs_btree_increment(cur, 0, &i);
1028 if (error)
1029 goto done;
1030 if (i) {
1031 state |= RMAP_RIGHT_VALID;
1032 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1033 if (error)
1034 goto done;
1035 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1036 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1037 done);
1038 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1039 cur->bc_private.a.agno, RIGHT.rm_startblock,
1040 RIGHT.rm_blockcount, RIGHT.rm_owner,
1041 RIGHT.rm_offset, RIGHT.rm_flags);
1042 if (bno + len == RIGHT.rm_startblock &&
1043 offset + len == RIGHT.rm_offset &&
1044 xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1045 state |= RMAP_RIGHT_CONTIG;
1046 }
1047
1048 /* check that left + prev + right is not too long */
1049 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1050 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1051 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1052 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1053 (unsigned long)LEFT.rm_blockcount + len +
1054 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1055 state &= ~RMAP_RIGHT_CONTIG;
1056
1057 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1058 _RET_IP_);
1059
1060 /* reset the cursor back to PREV */
1061 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1062 if (error)
1063 goto done;
1064 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1065
1066 /*
1067 * Switch out based on the FILLING and CONTIG state bits.
1068 */
1069 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1070 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1071 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1072 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1073 /*
1074 * Setting all of a previous oldext extent to newext.
1075 * The left and right neighbors are both contiguous with new.
1076 */
1077 error = xfs_btree_increment(cur, 0, &i);
1078 if (error)
1079 goto done;
1080 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1081 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1082 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1083 RIGHT.rm_owner, RIGHT.rm_offset,
1084 RIGHT.rm_flags);
1085 error = xfs_btree_delete(cur, &i);
1086 if (error)
1087 goto done;
1088 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1089 error = xfs_btree_decrement(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 PREV.rm_startblock, PREV.rm_blockcount,
1095 PREV.rm_owner, PREV.rm_offset,
1096 PREV.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 NEW = LEFT;
1106 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1107 error = xfs_rmap_update(cur, &NEW);
1108 if (error)
1109 goto done;
1110 break;
1111
1112 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1113 /*
1114 * Setting all of a previous oldext extent to newext.
1115 * The left neighbor is contiguous, the right is not.
1116 */
1117 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1118 PREV.rm_startblock, PREV.rm_blockcount,
1119 PREV.rm_owner, PREV.rm_offset,
1120 PREV.rm_flags);
1121 error = xfs_btree_delete(cur, &i);
1122 if (error)
1123 goto done;
1124 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1125 error = xfs_btree_decrement(cur, 0, &i);
1126 if (error)
1127 goto done;
1128 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1129 NEW = LEFT;
1130 NEW.rm_blockcount += PREV.rm_blockcount;
1131 error = xfs_rmap_update(cur, &NEW);
1132 if (error)
1133 goto done;
1134 break;
1135
1136 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1137 /*
1138 * Setting all of a previous oldext extent to newext.
1139 * The right neighbor is contiguous, the left is not.
1140 */
1141 error = xfs_btree_increment(cur, 0, &i);
1142 if (error)
1143 goto done;
1144 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1145 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1146 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1147 RIGHT.rm_owner, RIGHT.rm_offset,
1148 RIGHT.rm_flags);
1149 error = xfs_btree_delete(cur, &i);
1150 if (error)
1151 goto done;
1152 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1153 error = xfs_btree_decrement(cur, 0, &i);
1154 if (error)
1155 goto done;
1156 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1157 NEW = PREV;
1158 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1159 NEW.rm_flags = newext;
1160 error = xfs_rmap_update(cur, &NEW);
1161 if (error)
1162 goto done;
1163 break;
1164
1165 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1166 /*
1167 * Setting all of a previous oldext extent to newext.
1168 * Neither the left nor right neighbors are contiguous with
1169 * the new one.
1170 */
1171 NEW = PREV;
1172 NEW.rm_flags = newext;
1173 error = xfs_rmap_update(cur, &NEW);
1174 if (error)
1175 goto done;
1176 break;
1177
1178 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1179 /*
1180 * Setting the first part of a previous oldext extent to newext.
1181 * The left neighbor is contiguous.
1182 */
1183 NEW = PREV;
1184 NEW.rm_offset += len;
1185 NEW.rm_startblock += len;
1186 NEW.rm_blockcount -= len;
1187 error = xfs_rmap_update(cur, &NEW);
1188 if (error)
1189 goto done;
1190 error = xfs_btree_decrement(cur, 0, &i);
1191 if (error)
1192 goto done;
1193 NEW = LEFT;
1194 NEW.rm_blockcount += len;
1195 error = xfs_rmap_update(cur, &NEW);
1196 if (error)
1197 goto done;
1198 break;
1199
1200 case RMAP_LEFT_FILLING:
1201 /*
1202 * Setting the first part of a previous oldext extent to newext.
1203 * The left neighbor is not contiguous.
1204 */
1205 NEW = PREV;
1206 NEW.rm_startblock += len;
1207 NEW.rm_offset += len;
1208 NEW.rm_blockcount -= len;
1209 error = xfs_rmap_update(cur, &NEW);
1210 if (error)
1211 goto done;
1212 NEW.rm_startblock = bno;
1213 NEW.rm_owner = owner;
1214 NEW.rm_offset = offset;
1215 NEW.rm_blockcount = len;
1216 NEW.rm_flags = newext;
1217 cur->bc_rec.r = NEW;
1218 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1219 len, owner, offset, newext);
1220 error = xfs_btree_insert(cur, &i);
1221 if (error)
1222 goto done;
1223 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1224 break;
1225
1226 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1227 /*
1228 * Setting the last part of a previous oldext extent to newext.
1229 * The right neighbor is contiguous with the new allocation.
1230 */
1231 NEW = PREV;
1232 NEW.rm_blockcount -= len;
1233 error = xfs_rmap_update(cur, &NEW);
1234 if (error)
1235 goto done;
1236 error = xfs_btree_increment(cur, 0, &i);
1237 if (error)
1238 goto done;
1239 NEW = RIGHT;
1240 NEW.rm_offset = offset;
1241 NEW.rm_startblock = bno;
1242 NEW.rm_blockcount += len;
1243 error = xfs_rmap_update(cur, &NEW);
1244 if (error)
1245 goto done;
1246 break;
1247
1248 case RMAP_RIGHT_FILLING:
1249 /*
1250 * Setting the last part of a previous oldext extent to newext.
1251 * The right neighbor is not contiguous.
1252 */
1253 NEW = PREV;
1254 NEW.rm_blockcount -= len;
1255 error = xfs_rmap_update(cur, &NEW);
1256 if (error)
1257 goto done;
1258 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1259 oldext, &i);
1260 if (error)
1261 goto done;
1262 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1263 NEW.rm_startblock = bno;
1264 NEW.rm_owner = owner;
1265 NEW.rm_offset = offset;
1266 NEW.rm_blockcount = len;
1267 NEW.rm_flags = newext;
1268 cur->bc_rec.r = NEW;
1269 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1270 len, owner, offset, newext);
1271 error = xfs_btree_insert(cur, &i);
1272 if (error)
1273 goto done;
1274 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1275 break;
1276
1277 case 0:
1278 /*
1279 * Setting the middle part of a previous oldext extent to
1280 * newext. Contiguity is impossible here.
1281 * One extent becomes three extents.
1282 */
1283 /* new right extent - oldext */
1284 NEW.rm_startblock = bno + len;
1285 NEW.rm_owner = owner;
1286 NEW.rm_offset = new_endoff;
1287 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1288 new_endoff;
1289 NEW.rm_flags = PREV.rm_flags;
1290 error = xfs_rmap_update(cur, &NEW);
1291 if (error)
1292 goto done;
1293 /* new left extent - oldext */
1294 NEW = PREV;
1295 NEW.rm_blockcount = offset - PREV.rm_offset;
1296 cur->bc_rec.r = NEW;
1297 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1298 NEW.rm_startblock, NEW.rm_blockcount,
1299 NEW.rm_owner, NEW.rm_offset,
1300 NEW.rm_flags);
1301 error = xfs_btree_insert(cur, &i);
1302 if (error)
1303 goto done;
1304 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1305 /*
1306 * Reset the cursor to the position of the new extent
1307 * we are about to insert as we can't trust it after
1308 * the previous insert.
1309 */
1310 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1311 oldext, &i);
1312 if (error)
1313 goto done;
1314 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1315 /* new middle extent - newext */
1316 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1317 cur->bc_rec.r.rm_flags |= newext;
1318 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1319 owner, offset, newext);
1320 error = xfs_btree_insert(cur, &i);
1321 if (error)
1322 goto done;
1323 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1324 break;
1325
1326 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1327 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1328 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1329 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1330 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1331 case RMAP_LEFT_CONTIG:
1332 case RMAP_RIGHT_CONTIG:
1333 /*
1334 * These cases are all impossible.
1335 */
1336 ASSERT(0);
1337 }
1338
1339 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1340 unwritten, oinfo);
1341 done:
1342 if (error)
1343 trace_xfs_rmap_convert_error(cur->bc_mp,
1344 cur->bc_private.a.agno, error, _RET_IP_);
1345 return error;
1346 }
1347
1348 /*
1349 * Convert an unwritten extent to a real extent or vice versa. If there is no
1350 * possibility of overlapping extents, delegate to the simpler convert
1351 * function.
1352 */
1353 STATIC int
1354 xfs_rmap_convert_shared(
1355 struct xfs_btree_cur *cur,
1356 xfs_agblock_t bno,
1357 xfs_extlen_t len,
1358 bool unwritten,
1359 struct xfs_owner_info *oinfo)
1360 {
1361 struct xfs_mount *mp = cur->bc_mp;
1362 struct xfs_rmap_irec r[4]; /* neighbor extent entries */
1363 /* left is 0, right is 1, prev is 2 */
1364 /* new is 3 */
1365 uint64_t owner;
1366 uint64_t offset;
1367 uint64_t new_endoff;
1368 unsigned int oldext;
1369 unsigned int newext;
1370 unsigned int flags = 0;
1371 int i;
1372 int state = 0;
1373 int error;
1374
1375 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1376 ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1377 (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1378 oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1379 new_endoff = offset + len;
1380 trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1381 unwritten, oinfo);
1382
1383 /*
1384 * For the initial lookup, look for and exact match or the left-adjacent
1385 * record for our insertion point. This will also give us the record for
1386 * start block contiguity tests.
1387 */
1388 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1389 &PREV, &i);
1390 if (error)
1391 goto done;
1392 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1393
1394 ASSERT(PREV.rm_offset <= offset);
1395 ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1396 ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1397 newext = ~oldext & XFS_RMAP_UNWRITTEN;
1398
1399 /*
1400 * Set flags determining what part of the previous oldext allocation
1401 * extent is being replaced by a newext allocation.
1402 */
1403 if (PREV.rm_offset == offset)
1404 state |= RMAP_LEFT_FILLING;
1405 if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1406 state |= RMAP_RIGHT_FILLING;
1407
1408 /* Is there a left record that abuts our range? */
1409 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1410 &LEFT, &i);
1411 if (error)
1412 goto done;
1413 if (i) {
1414 state |= RMAP_LEFT_VALID;
1415 XFS_WANT_CORRUPTED_GOTO(mp,
1416 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1417 done);
1418 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1419 state |= RMAP_LEFT_CONTIG;
1420 }
1421
1422 /* Is there a right record that abuts our range? */
1423 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1424 newext, &i);
1425 if (error)
1426 goto done;
1427 if (i) {
1428 state |= RMAP_RIGHT_VALID;
1429 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1430 if (error)
1431 goto done;
1432 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1433 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1434 done);
1435 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1436 cur->bc_private.a.agno, RIGHT.rm_startblock,
1437 RIGHT.rm_blockcount, RIGHT.rm_owner,
1438 RIGHT.rm_offset, RIGHT.rm_flags);
1439 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1440 state |= RMAP_RIGHT_CONTIG;
1441 }
1442
1443 /* check that left + prev + right is not too long */
1444 if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1445 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1446 (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1447 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1448 (unsigned long)LEFT.rm_blockcount + len +
1449 RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1450 state &= ~RMAP_RIGHT_CONTIG;
1451
1452 trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1453 _RET_IP_);
1454 /*
1455 * Switch out based on the FILLING and CONTIG state bits.
1456 */
1457 switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1458 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1459 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1460 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1461 /*
1462 * Setting all of a previous oldext extent to newext.
1463 * The left and right neighbors are both contiguous with new.
1464 */
1465 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1466 RIGHT.rm_blockcount, RIGHT.rm_owner,
1467 RIGHT.rm_offset, RIGHT.rm_flags);
1468 if (error)
1469 goto done;
1470 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1471 PREV.rm_blockcount, PREV.rm_owner,
1472 PREV.rm_offset, PREV.rm_flags);
1473 if (error)
1474 goto done;
1475 NEW = LEFT;
1476 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1477 NEW.rm_blockcount, NEW.rm_owner,
1478 NEW.rm_offset, NEW.rm_flags, &i);
1479 if (error)
1480 goto done;
1481 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1482 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1483 error = xfs_rmap_update(cur, &NEW);
1484 if (error)
1485 goto done;
1486 break;
1487
1488 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1489 /*
1490 * Setting all of a previous oldext extent to newext.
1491 * The left neighbor is contiguous, the right is not.
1492 */
1493 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1494 PREV.rm_blockcount, PREV.rm_owner,
1495 PREV.rm_offset, PREV.rm_flags);
1496 if (error)
1497 goto done;
1498 NEW = LEFT;
1499 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1500 NEW.rm_blockcount, NEW.rm_owner,
1501 NEW.rm_offset, NEW.rm_flags, &i);
1502 if (error)
1503 goto done;
1504 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1505 NEW.rm_blockcount += PREV.rm_blockcount;
1506 error = xfs_rmap_update(cur, &NEW);
1507 if (error)
1508 goto done;
1509 break;
1510
1511 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1512 /*
1513 * Setting all of a previous oldext extent to newext.
1514 * The right neighbor is contiguous, the left is not.
1515 */
1516 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1517 RIGHT.rm_blockcount, RIGHT.rm_owner,
1518 RIGHT.rm_offset, RIGHT.rm_flags);
1519 if (error)
1520 goto done;
1521 NEW = PREV;
1522 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1523 NEW.rm_blockcount, NEW.rm_owner,
1524 NEW.rm_offset, NEW.rm_flags, &i);
1525 if (error)
1526 goto done;
1527 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1528 NEW.rm_blockcount += RIGHT.rm_blockcount;
1529 NEW.rm_flags = RIGHT.rm_flags;
1530 error = xfs_rmap_update(cur, &NEW);
1531 if (error)
1532 goto done;
1533 break;
1534
1535 case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1536 /*
1537 * Setting all of a previous oldext extent to newext.
1538 * Neither the left nor right neighbors are contiguous with
1539 * the new one.
1540 */
1541 NEW = PREV;
1542 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1543 NEW.rm_blockcount, NEW.rm_owner,
1544 NEW.rm_offset, NEW.rm_flags, &i);
1545 if (error)
1546 goto done;
1547 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1548 NEW.rm_flags = newext;
1549 error = xfs_rmap_update(cur, &NEW);
1550 if (error)
1551 goto done;
1552 break;
1553
1554 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1555 /*
1556 * Setting the first part of a previous oldext extent to newext.
1557 * The left neighbor is contiguous.
1558 */
1559 NEW = PREV;
1560 error = xfs_rmap_delete(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.rm_offset += len;
1566 NEW.rm_startblock += len;
1567 NEW.rm_blockcount -= len;
1568 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1569 NEW.rm_blockcount, NEW.rm_owner,
1570 NEW.rm_offset, NEW.rm_flags);
1571 if (error)
1572 goto done;
1573 NEW = LEFT;
1574 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1575 NEW.rm_blockcount, NEW.rm_owner,
1576 NEW.rm_offset, NEW.rm_flags, &i);
1577 if (error)
1578 goto done;
1579 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1580 NEW.rm_blockcount += len;
1581 error = xfs_rmap_update(cur, &NEW);
1582 if (error)
1583 goto done;
1584 break;
1585
1586 case RMAP_LEFT_FILLING:
1587 /*
1588 * Setting the first part of a previous oldext extent to newext.
1589 * The left neighbor is not contiguous.
1590 */
1591 NEW = PREV;
1592 error = xfs_rmap_delete(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 NEW.rm_offset += len;
1598 NEW.rm_startblock += len;
1599 NEW.rm_blockcount -= len;
1600 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1601 NEW.rm_blockcount, NEW.rm_owner,
1602 NEW.rm_offset, NEW.rm_flags);
1603 if (error)
1604 goto done;
1605 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1606 if (error)
1607 goto done;
1608 break;
1609
1610 case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1611 /*
1612 * Setting the last part of a previous oldext extent to newext.
1613 * The right neighbor is contiguous with the new allocation.
1614 */
1615 NEW = PREV;
1616 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1617 NEW.rm_blockcount, NEW.rm_owner,
1618 NEW.rm_offset, NEW.rm_flags, &i);
1619 if (error)
1620 goto done;
1621 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1622 NEW.rm_blockcount = offset - NEW.rm_offset;
1623 error = xfs_rmap_update(cur, &NEW);
1624 if (error)
1625 goto done;
1626 NEW = RIGHT;
1627 error = xfs_rmap_delete(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 NEW.rm_offset = offset;
1633 NEW.rm_startblock = bno;
1634 NEW.rm_blockcount += len;
1635 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1636 NEW.rm_blockcount, NEW.rm_owner,
1637 NEW.rm_offset, NEW.rm_flags);
1638 if (error)
1639 goto done;
1640 break;
1641
1642 case RMAP_RIGHT_FILLING:
1643 /*
1644 * Setting the last part of a previous oldext extent to newext.
1645 * The right neighbor is not contiguous.
1646 */
1647 NEW = PREV;
1648 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1649 NEW.rm_blockcount, NEW.rm_owner,
1650 NEW.rm_offset, NEW.rm_flags, &i);
1651 if (error)
1652 goto done;
1653 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1654 NEW.rm_blockcount -= len;
1655 error = xfs_rmap_update(cur, &NEW);
1656 if (error)
1657 goto done;
1658 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1659 if (error)
1660 goto done;
1661 break;
1662
1663 case 0:
1664 /*
1665 * Setting the middle part of a previous oldext extent to
1666 * newext. Contiguity is impossible here.
1667 * One extent becomes three extents.
1668 */
1669 /* new right extent - oldext */
1670 NEW.rm_startblock = bno + len;
1671 NEW.rm_owner = owner;
1672 NEW.rm_offset = new_endoff;
1673 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1674 new_endoff;
1675 NEW.rm_flags = PREV.rm_flags;
1676 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1677 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1678 NEW.rm_flags);
1679 if (error)
1680 goto done;
1681 /* new left extent - oldext */
1682 NEW = PREV;
1683 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1684 NEW.rm_blockcount, NEW.rm_owner,
1685 NEW.rm_offset, NEW.rm_flags, &i);
1686 if (error)
1687 goto done;
1688 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1689 NEW.rm_blockcount = offset - NEW.rm_offset;
1690 error = xfs_rmap_update(cur, &NEW);
1691 if (error)
1692 goto done;
1693 /* new middle extent - newext */
1694 NEW.rm_startblock = bno;
1695 NEW.rm_blockcount = len;
1696 NEW.rm_owner = owner;
1697 NEW.rm_offset = offset;
1698 NEW.rm_flags = newext;
1699 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1700 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1701 NEW.rm_flags);
1702 if (error)
1703 goto done;
1704 break;
1705
1706 case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1707 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1708 case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1709 case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1710 case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1711 case RMAP_LEFT_CONTIG:
1712 case RMAP_RIGHT_CONTIG:
1713 /*
1714 * These cases are all impossible.
1715 */
1716 ASSERT(0);
1717 }
1718
1719 trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1720 unwritten, oinfo);
1721 done:
1722 if (error)
1723 trace_xfs_rmap_convert_error(cur->bc_mp,
1724 cur->bc_private.a.agno, error, _RET_IP_);
1725 return error;
1726 }
1727
1728 #undef NEW
1729 #undef LEFT
1730 #undef RIGHT
1731 #undef PREV
1732
1733 /*
1734 * Find an extent in the rmap btree and unmap it. For rmap extent types that
1735 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1736 * that the prev/next records in the btree might belong to another owner.
1737 * Therefore we must use delete+insert to alter any of the key fields.
1738 *
1739 * For every other situation there can only be one owner for a given extent,
1740 * so we can call the regular _free function.
1741 */
1742 STATIC int
1743 xfs_rmap_unmap_shared(
1744 struct xfs_btree_cur *cur,
1745 xfs_agblock_t bno,
1746 xfs_extlen_t len,
1747 bool unwritten,
1748 struct xfs_owner_info *oinfo)
1749 {
1750 struct xfs_mount *mp = cur->bc_mp;
1751 struct xfs_rmap_irec ltrec;
1752 uint64_t ltoff;
1753 int error = 0;
1754 int i;
1755 uint64_t owner;
1756 uint64_t offset;
1757 unsigned int flags;
1758
1759 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1760 if (unwritten)
1761 flags |= XFS_RMAP_UNWRITTEN;
1762 trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1763 unwritten, oinfo);
1764
1765 /*
1766 * We should always have a left record because there's a static record
1767 * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1768 * will not ever be removed from the tree.
1769 */
1770 error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1771 &ltrec, &i);
1772 if (error)
1773 goto out_error;
1774 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1775 ltoff = ltrec.rm_offset;
1776
1777 /* Make sure the extent we found covers the entire freeing range. */
1778 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1779 ltrec.rm_startblock + ltrec.rm_blockcount >=
1780 bno + len, out_error);
1781
1782 /* Make sure the owner matches what we expect to find in the tree. */
1783 XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1784
1785 /* Make sure the unwritten flag matches. */
1786 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1787 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1788
1789 /* Check the offset. */
1790 XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1791 XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1792 out_error);
1793
1794 if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1795 /* Exact match, simply remove the record from rmap tree. */
1796 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1797 ltrec.rm_blockcount, ltrec.rm_owner,
1798 ltrec.rm_offset, ltrec.rm_flags);
1799 if (error)
1800 goto out_error;
1801 } else if (ltrec.rm_startblock == bno) {
1802 /*
1803 * Overlap left hand side of extent: move the start, trim the
1804 * length and update the current record.
1805 *
1806 * ltbno ltlen
1807 * Orig: |oooooooooooooooooooo|
1808 * Freeing: |fffffffff|
1809 * Result: |rrrrrrrrrr|
1810 * bno len
1811 */
1812
1813 /* Delete prev rmap. */
1814 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1815 ltrec.rm_blockcount, ltrec.rm_owner,
1816 ltrec.rm_offset, ltrec.rm_flags);
1817 if (error)
1818 goto out_error;
1819
1820 /* Add an rmap at the new offset. */
1821 ltrec.rm_startblock += len;
1822 ltrec.rm_blockcount -= len;
1823 ltrec.rm_offset += len;
1824 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1825 ltrec.rm_blockcount, ltrec.rm_owner,
1826 ltrec.rm_offset, ltrec.rm_flags);
1827 if (error)
1828 goto out_error;
1829 } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1830 /*
1831 * Overlap right hand side of extent: trim the length and
1832 * update the current record.
1833 *
1834 * ltbno ltlen
1835 * Orig: |oooooooooooooooooooo|
1836 * Freeing: |fffffffff|
1837 * Result: |rrrrrrrrrr|
1838 * bno len
1839 */
1840 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1841 ltrec.rm_blockcount, ltrec.rm_owner,
1842 ltrec.rm_offset, ltrec.rm_flags, &i);
1843 if (error)
1844 goto out_error;
1845 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1846 ltrec.rm_blockcount -= len;
1847 error = xfs_rmap_update(cur, &ltrec);
1848 if (error)
1849 goto out_error;
1850 } else {
1851 /*
1852 * Overlap middle of extent: trim the length of the existing
1853 * record to the length of the new left-extent size, increment
1854 * the insertion position so we can insert a new record
1855 * containing the remaining right-extent space.
1856 *
1857 * ltbno ltlen
1858 * Orig: |oooooooooooooooooooo|
1859 * Freeing: |fffffffff|
1860 * Result: |rrrrr| |rrrr|
1861 * bno len
1862 */
1863 xfs_extlen_t orig_len = ltrec.rm_blockcount;
1864
1865 /* Shrink the left side of the rmap */
1866 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1867 ltrec.rm_blockcount, ltrec.rm_owner,
1868 ltrec.rm_offset, ltrec.rm_flags, &i);
1869 if (error)
1870 goto out_error;
1871 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1872 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1873 error = xfs_rmap_update(cur, &ltrec);
1874 if (error)
1875 goto out_error;
1876
1877 /* Add an rmap at the new offset */
1878 error = xfs_rmap_insert(cur, bno + len,
1879 orig_len - len - ltrec.rm_blockcount,
1880 ltrec.rm_owner, offset + len,
1881 ltrec.rm_flags);
1882 if (error)
1883 goto out_error;
1884 }
1885
1886 trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1887 unwritten, oinfo);
1888 out_error:
1889 if (error)
1890 trace_xfs_rmap_unmap_error(cur->bc_mp,
1891 cur->bc_private.a.agno, error, _RET_IP_);
1892 return error;
1893 }
1894
1895 /*
1896 * Find an extent in the rmap btree and map it. For rmap extent types that
1897 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1898 * that the prev/next records in the btree might belong to another owner.
1899 * Therefore we must use delete+insert to alter any of the key fields.
1900 *
1901 * For every other situation there can only be one owner for a given extent,
1902 * so we can call the regular _alloc function.
1903 */
1904 STATIC int
1905 xfs_rmap_map_shared(
1906 struct xfs_btree_cur *cur,
1907 xfs_agblock_t bno,
1908 xfs_extlen_t len,
1909 bool unwritten,
1910 struct xfs_owner_info *oinfo)
1911 {
1912 struct xfs_mount *mp = cur->bc_mp;
1913 struct xfs_rmap_irec ltrec;
1914 struct xfs_rmap_irec gtrec;
1915 int have_gt;
1916 int have_lt;
1917 int error = 0;
1918 int i;
1919 uint64_t owner;
1920 uint64_t offset;
1921 unsigned int flags = 0;
1922
1923 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1924 if (unwritten)
1925 flags |= XFS_RMAP_UNWRITTEN;
1926 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1927 unwritten, oinfo);
1928
1929 /* Is there a left record that abuts our range? */
1930 error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1931 &ltrec, &have_lt);
1932 if (error)
1933 goto out_error;
1934 if (have_lt &&
1935 !xfs_rmap_is_mergeable(&ltrec, owner, flags))
1936 have_lt = 0;
1937
1938 /* Is there a right record that abuts our range? */
1939 error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1940 flags, &have_gt);
1941 if (error)
1942 goto out_error;
1943 if (have_gt) {
1944 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
1945 if (error)
1946 goto out_error;
1947 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1948 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1949 cur->bc_private.a.agno, gtrec.rm_startblock,
1950 gtrec.rm_blockcount, gtrec.rm_owner,
1951 gtrec.rm_offset, gtrec.rm_flags);
1952
1953 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
1954 have_gt = 0;
1955 }
1956
1957 if (have_lt &&
1958 ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1959 ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1960 /*
1961 * Left edge contiguous, merge into left record.
1962 *
1963 * ltbno ltlen
1964 * orig: |ooooooooo|
1965 * adding: |aaaaaaaaa|
1966 * result: |rrrrrrrrrrrrrrrrrrr|
1967 * bno len
1968 */
1969 ltrec.rm_blockcount += len;
1970 if (have_gt &&
1971 bno + len == gtrec.rm_startblock &&
1972 offset + len == gtrec.rm_offset) {
1973 /*
1974 * Right edge also contiguous, delete right record
1975 * and merge into left record.
1976 *
1977 * ltbno ltlen gtbno gtlen
1978 * orig: |ooooooooo| |ooooooooo|
1979 * adding: |aaaaaaaaa|
1980 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1981 */
1982 ltrec.rm_blockcount += gtrec.rm_blockcount;
1983 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1984 gtrec.rm_blockcount, gtrec.rm_owner,
1985 gtrec.rm_offset, gtrec.rm_flags);
1986 if (error)
1987 goto out_error;
1988 }
1989
1990 /* Point the cursor back to the left record and update. */
1991 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1992 ltrec.rm_blockcount, ltrec.rm_owner,
1993 ltrec.rm_offset, ltrec.rm_flags, &i);
1994 if (error)
1995 goto out_error;
1996 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1997
1998 error = xfs_rmap_update(cur, &ltrec);
1999 if (error)
2000 goto out_error;
2001 } else if (have_gt &&
2002 bno + len == gtrec.rm_startblock &&
2003 offset + len == gtrec.rm_offset) {
2004 /*
2005 * Right edge contiguous, merge into right record.
2006 *
2007 * gtbno gtlen
2008 * Orig: |ooooooooo|
2009 * adding: |aaaaaaaaa|
2010 * Result: |rrrrrrrrrrrrrrrrrrr|
2011 * bno len
2012 */
2013 /* Delete the old record. */
2014 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2015 gtrec.rm_blockcount, gtrec.rm_owner,
2016 gtrec.rm_offset, gtrec.rm_flags);
2017 if (error)
2018 goto out_error;
2019
2020 /* Move the start and re-add it. */
2021 gtrec.rm_startblock = bno;
2022 gtrec.rm_blockcount += len;
2023 gtrec.rm_offset = offset;
2024 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2025 gtrec.rm_blockcount, gtrec.rm_owner,
2026 gtrec.rm_offset, gtrec.rm_flags);
2027 if (error)
2028 goto out_error;
2029 } else {
2030 /*
2031 * No contiguous edge with identical owner, insert
2032 * new record at current cursor position.
2033 */
2034 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2035 if (error)
2036 goto out_error;
2037 }
2038
2039 trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2040 unwritten, oinfo);
2041 out_error:
2042 if (error)
2043 trace_xfs_rmap_map_error(cur->bc_mp,
2044 cur->bc_private.a.agno, error, _RET_IP_);
2045 return error;
2046 }
2047
2048 /* Insert a raw rmap into the rmapbt. */
2049 int
2050 xfs_rmap_map_raw(
2051 struct xfs_btree_cur *cur,
2052 struct xfs_rmap_irec *rmap)
2053 {
2054 struct xfs_owner_info oinfo;
2055
2056 oinfo.oi_owner = rmap->rm_owner;
2057 oinfo.oi_offset = rmap->rm_offset;
2058 oinfo.oi_flags = 0;
2059 if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2060 oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2061 if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2062 oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2063
2064 if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2065 return xfs_rmap_map(cur, rmap->rm_startblock,
2066 rmap->rm_blockcount,
2067 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2068 &oinfo);
2069
2070 return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2071 rmap->rm_blockcount,
2072 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2073 &oinfo);
2074 }
2075
2076 struct xfs_rmap_query_range_info {
2077 xfs_rmap_query_range_fn fn;
2078 void *priv;
2079 };
2080
2081 /* Format btree record and pass to our callback. */
2082 STATIC int
2083 xfs_rmap_query_range_helper(
2084 struct xfs_btree_cur *cur,
2085 union xfs_btree_rec *rec,
2086 void *priv)
2087 {
2088 struct xfs_rmap_query_range_info *query = priv;
2089 struct xfs_rmap_irec irec;
2090 int error;
2091
2092 error = xfs_rmap_btrec_to_irec(rec, &irec);
2093 if (error)
2094 return error;
2095 return query->fn(cur, &irec, query->priv);
2096 }
2097
2098 /* Find all rmaps between two keys. */
2099 int
2100 xfs_rmap_query_range(
2101 struct xfs_btree_cur *cur,
2102 struct xfs_rmap_irec *low_rec,
2103 struct xfs_rmap_irec *high_rec,
2104 xfs_rmap_query_range_fn fn,
2105 void *priv)
2106 {
2107 union xfs_btree_irec low_brec;
2108 union xfs_btree_irec high_brec;
2109 struct xfs_rmap_query_range_info query;
2110
2111 low_brec.r = *low_rec;
2112 high_brec.r = *high_rec;
2113 query.priv = priv;
2114 query.fn = fn;
2115 return xfs_btree_query_range(cur, &low_brec, &high_brec,
2116 xfs_rmap_query_range_helper, &query);
2117 }
2118
2119 /* Find all rmaps. */
2120 int
2121 xfs_rmap_query_all(
2122 struct xfs_btree_cur *cur,
2123 xfs_rmap_query_range_fn fn,
2124 void *priv)
2125 {
2126 struct xfs_rmap_query_range_info query;
2127
2128 query.priv = priv;
2129 query.fn = fn;
2130 return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2131 }
2132
2133 /* Clean up after calling xfs_rmap_finish_one. */
2134 void
2135 xfs_rmap_finish_one_cleanup(
2136 struct xfs_trans *tp,
2137 struct xfs_btree_cur *rcur,
2138 int error)
2139 {
2140 struct xfs_buf *agbp;
2141
2142 if (rcur == NULL)
2143 return;
2144 agbp = rcur->bc_private.a.agbp;
2145 xfs_btree_del_cursor(rcur, error);
2146 if (error)
2147 xfs_trans_brelse(tp, agbp);
2148 }
2149
2150 /*
2151 * Process one of the deferred rmap operations. We pass back the
2152 * btree cursor to maintain our lock on the rmapbt between calls.
2153 * This saves time and eliminates a buffer deadlock between the
2154 * superblock and the AGF because we'll always grab them in the same
2155 * order.
2156 */
2157 int
2158 xfs_rmap_finish_one(
2159 struct xfs_trans *tp,
2160 enum xfs_rmap_intent_type type,
2161 uint64_t owner,
2162 int whichfork,
2163 xfs_fileoff_t startoff,
2164 xfs_fsblock_t startblock,
2165 xfs_filblks_t blockcount,
2166 xfs_exntst_t state,
2167 struct xfs_btree_cur **pcur)
2168 {
2169 struct xfs_mount *mp = tp->t_mountp;
2170 struct xfs_btree_cur *rcur;
2171 struct xfs_buf *agbp = NULL;
2172 int error = 0;
2173 xfs_agnumber_t agno;
2174 struct xfs_owner_info oinfo;
2175 xfs_agblock_t bno;
2176 bool unwritten;
2177
2178 agno = XFS_FSB_TO_AGNO(mp, startblock);
2179 ASSERT(agno != NULLAGNUMBER);
2180 bno = XFS_FSB_TO_AGBNO(mp, startblock);
2181
2182 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2183 startoff, blockcount, state);
2184
2185 if (XFS_TEST_ERROR(false, mp,
2186 XFS_ERRTAG_RMAP_FINISH_ONE))
2187 return -EIO;
2188
2189 /*
2190 * If we haven't gotten a cursor or the cursor AG doesn't match
2191 * the startblock, get one now.
2192 */
2193 rcur = *pcur;
2194 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2195 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2196 rcur = NULL;
2197 *pcur = NULL;
2198 }
2199 if (rcur == NULL) {
2200 /*
2201 * Refresh the freelist before we start changing the
2202 * rmapbt, because a shape change could cause us to
2203 * allocate blocks.
2204 */
2205 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2206 if (error)
2207 return error;
2208 if (!agbp)
2209 return -EFSCORRUPTED;
2210
2211 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2212 if (!rcur) {
2213 error = -ENOMEM;
2214 goto out_cur;
2215 }
2216 }
2217 *pcur = rcur;
2218
2219 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2220 unwritten = state == XFS_EXT_UNWRITTEN;
2221 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2222
2223 switch (type) {
2224 case XFS_RMAP_ALLOC:
2225 case XFS_RMAP_MAP:
2226 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2227 break;
2228 case XFS_RMAP_MAP_SHARED:
2229 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2230 &oinfo);
2231 break;
2232 case XFS_RMAP_FREE:
2233 case XFS_RMAP_UNMAP:
2234 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2235 &oinfo);
2236 break;
2237 case XFS_RMAP_UNMAP_SHARED:
2238 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2239 &oinfo);
2240 break;
2241 case XFS_RMAP_CONVERT:
2242 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2243 &oinfo);
2244 break;
2245 case XFS_RMAP_CONVERT_SHARED:
2246 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2247 !unwritten, &oinfo);
2248 break;
2249 default:
2250 ASSERT(0);
2251 error = -EFSCORRUPTED;
2252 }
2253 return error;
2254
2255 out_cur:
2256 xfs_trans_brelse(tp, agbp);
2257
2258 return error;
2259 }
2260
2261 /*
2262 * Don't defer an rmap if we aren't an rmap filesystem.
2263 */
2264 static bool
2265 xfs_rmap_update_is_needed(
2266 struct xfs_mount *mp,
2267 int whichfork)
2268 {
2269 return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2270 }
2271
2272 /*
2273 * Record a rmap intent; the list is kept sorted first by AG and then by
2274 * increasing age.
2275 */
2276 static int
2277 __xfs_rmap_add(
2278 struct xfs_mount *mp,
2279 struct xfs_defer_ops *dfops,
2280 enum xfs_rmap_intent_type type,
2281 uint64_t owner,
2282 int whichfork,
2283 struct xfs_bmbt_irec *bmap)
2284 {
2285 struct xfs_rmap_intent *ri;
2286
2287 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2288 type,
2289 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2290 owner, whichfork,
2291 bmap->br_startoff,
2292 bmap->br_blockcount,
2293 bmap->br_state);
2294
2295 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2296 INIT_LIST_HEAD(&ri->ri_list);
2297 ri->ri_type = type;
2298 ri->ri_owner = owner;
2299 ri->ri_whichfork = whichfork;
2300 ri->ri_bmap = *bmap;
2301
2302 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2303 return 0;
2304 }
2305
2306 /* Map an extent into a file. */
2307 int
2308 xfs_rmap_map_extent(
2309 struct xfs_mount *mp,
2310 struct xfs_defer_ops *dfops,
2311 struct xfs_inode *ip,
2312 int whichfork,
2313 struct xfs_bmbt_irec *PREV)
2314 {
2315 if (!xfs_rmap_update_is_needed(mp, whichfork))
2316 return 0;
2317
2318 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2319 XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2320 whichfork, PREV);
2321 }
2322
2323 /* Unmap an extent out of a file. */
2324 int
2325 xfs_rmap_unmap_extent(
2326 struct xfs_mount *mp,
2327 struct xfs_defer_ops *dfops,
2328 struct xfs_inode *ip,
2329 int whichfork,
2330 struct xfs_bmbt_irec *PREV)
2331 {
2332 if (!xfs_rmap_update_is_needed(mp, whichfork))
2333 return 0;
2334
2335 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2336 XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2337 whichfork, PREV);
2338 }
2339
2340 /* Convert a data fork extent from unwritten to real or vice versa. */
2341 int
2342 xfs_rmap_convert_extent(
2343 struct xfs_mount *mp,
2344 struct xfs_defer_ops *dfops,
2345 struct xfs_inode *ip,
2346 int whichfork,
2347 struct xfs_bmbt_irec *PREV)
2348 {
2349 if (!xfs_rmap_update_is_needed(mp, whichfork))
2350 return 0;
2351
2352 return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2353 XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2354 whichfork, PREV);
2355 }
2356
2357 /* Schedule the creation of an rmap for non-file data. */
2358 int
2359 xfs_rmap_alloc_extent(
2360 struct xfs_mount *mp,
2361 struct xfs_defer_ops *dfops,
2362 xfs_agnumber_t agno,
2363 xfs_agblock_t bno,
2364 xfs_extlen_t len,
2365 uint64_t owner)
2366 {
2367 struct xfs_bmbt_irec bmap;
2368
2369 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2370 return 0;
2371
2372 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2373 bmap.br_blockcount = len;
2374 bmap.br_startoff = 0;
2375 bmap.br_state = XFS_EXT_NORM;
2376
2377 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2378 XFS_DATA_FORK, &bmap);
2379 }
2380
2381 /* Schedule the deletion of an rmap for non-file data. */
2382 int
2383 xfs_rmap_free_extent(
2384 struct xfs_mount *mp,
2385 struct xfs_defer_ops *dfops,
2386 xfs_agnumber_t agno,
2387 xfs_agblock_t bno,
2388 xfs_extlen_t len,
2389 uint64_t owner)
2390 {
2391 struct xfs_bmbt_irec bmap;
2392
2393 if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2394 return 0;
2395
2396 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2397 bmap.br_blockcount = len;
2398 bmap.br_startoff = 0;
2399 bmap.br_state = XFS_EXT_NORM;
2400
2401 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2402 XFS_DATA_FORK, &bmap);
2403 }
2404
2405 /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2406 int
2407 xfs_rmap_compare(
2408 const struct xfs_rmap_irec *a,
2409 const struct xfs_rmap_irec *b)
2410 {
2411 __u64 oa;
2412 __u64 ob;
2413
2414 oa = xfs_rmap_irec_offset_pack(a);
2415 ob = xfs_rmap_irec_offset_pack(b);
2416
2417 if (a->rm_startblock < b->rm_startblock)
2418 return -1;
2419 else if (a->rm_startblock > b->rm_startblock)
2420 return 1;
2421 else if (a->rm_owner < b->rm_owner)
2422 return -1;
2423 else if (a->rm_owner > b->rm_owner)
2424 return 1;
2425 else if (oa < ob)
2426 return -1;
2427 else if (oa > ob)
2428 return 1;
2429 else
2430 return 0;
2431 }
2432
2433 /* Is there a record covering a given extent? */
2434 int
2435 xfs_rmap_has_record(
2436 struct xfs_btree_cur *cur,
2437 xfs_agblock_t bno,
2438 xfs_extlen_t len,
2439 bool *exists)
2440 {
2441 union xfs_btree_irec low;
2442 union xfs_btree_irec high;
2443
2444 memset(&low, 0, sizeof(low));
2445 low.r.rm_startblock = bno;
2446 memset(&high, 0xFF, sizeof(high));
2447 high.r.rm_startblock = bno + len - 1;
2448
2449 return xfs_btree_has_record(cur, &low, &high, exists);
2450 }
2451
2452 /*
2453 * Is there a record for this owner completely covering a given physical
2454 * extent? If so, *has_rmap will be set to true. If there is no record
2455 * or the record only covers part of the range, we set *has_rmap to false.
2456 * This function doesn't perform range lookups or offset checks, so it is
2457 * not suitable for checking data fork blocks.
2458 */
2459 int
2460 xfs_rmap_record_exists(
2461 struct xfs_btree_cur *cur,
2462 xfs_agblock_t bno,
2463 xfs_extlen_t len,
2464 struct xfs_owner_info *oinfo,
2465 bool *has_rmap)
2466 {
2467 uint64_t owner;
2468 uint64_t offset;
2469 unsigned int flags;
2470 int has_record;
2471 struct xfs_rmap_irec irec;
2472 int error;
2473
2474 xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2475 ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2476 (flags & XFS_RMAP_BMBT_BLOCK));
2477
2478 error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2479 &has_record);
2480 if (error)
2481 return error;
2482 if (!has_record) {
2483 *has_rmap = false;
2484 return 0;
2485 }
2486
2487 error = xfs_rmap_get_rec(cur, &irec, &has_record);
2488 if (error)
2489 return error;
2490 if (!has_record) {
2491 *has_rmap = false;
2492 return 0;
2493 }
2494
2495 *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2496 irec.rm_startblock + irec.rm_blockcount >= bno + len);
2497 return 0;
2498 }
2499
2500 struct xfs_rmap_key_state {
2501 uint64_t owner;
2502 uint64_t offset;
2503 unsigned int flags;
2504 bool has_rmap;
2505 };
2506
2507 /* For each rmap given, figure out if it doesn't match the key we want. */
2508 STATIC int
2509 xfs_rmap_has_other_keys_helper(
2510 struct xfs_btree_cur *cur,
2511 struct xfs_rmap_irec *rec,
2512 void *priv)
2513 {
2514 struct xfs_rmap_key_state *rks = priv;
2515
2516 if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2517 ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2518 return 0;
2519 rks->has_rmap = true;
2520 return XFS_BTREE_QUERY_RANGE_ABORT;
2521 }
2522
2523 /*
2524 * Given an extent and some owner info, can we find records overlapping
2525 * the extent whose owner info does not match the given owner?
2526 */
2527 int
2528 xfs_rmap_has_other_keys(
2529 struct xfs_btree_cur *cur,
2530 xfs_agblock_t bno,
2531 xfs_extlen_t len,
2532 struct xfs_owner_info *oinfo,
2533 bool *has_rmap)
2534 {
2535 struct xfs_rmap_irec low = {0};
2536 struct xfs_rmap_irec high;
2537 struct xfs_rmap_key_state rks;
2538 int error;
2539
2540 xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2541 rks.has_rmap = false;
2542
2543 low.rm_startblock = bno;
2544 memset(&high, 0xFF, sizeof(high));
2545 high.rm_startblock = bno + len - 1;
2546
2547 error = xfs_rmap_query_range(cur, &low, &high,
2548 xfs_rmap_has_other_keys_helper, &rks);
2549 *has_rmap = rks.has_rmap;
2550 return error;
2551 }