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