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