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