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