Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2003,2005 Silicon Graphics, 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_inode.h"
15 : #include "xfs_trans.h"
16 : #include "xfs_alloc.h"
17 : #include "xfs_btree.h"
18 : #include "xfs_btree_staging.h"
19 : #include "xfs_bmap_btree.h"
20 : #include "xfs_bmap.h"
21 : #include "xfs_error.h"
22 : #include "xfs_quota.h"
23 : #include "xfs_trace.h"
24 : #include "xfs_rmap.h"
25 : #include "xfs_ag.h"
26 :
27 : static struct kmem_cache *xfs_bmbt_cur_cache;
28 :
29 : /*
30 : * Convert on-disk form of btree root to in-memory form.
31 : */
32 : void
33 12989722 : xfs_bmdr_to_bmbt(
34 : struct xfs_inode *ip,
35 : xfs_bmdr_block_t *dblock,
36 : int dblocklen,
37 : struct xfs_btree_block *rblock,
38 : int rblocklen)
39 : {
40 12989722 : struct xfs_mount *mp = ip->i_mount;
41 12989722 : int dmxr;
42 12989722 : xfs_bmbt_key_t *fkp;
43 12989722 : __be64 *fpp;
44 12989722 : xfs_bmbt_key_t *tkp;
45 12989722 : __be64 *tpp;
46 :
47 12989722 : xfs_btree_init_block(mp, rblock, &xfs_bmbt_ops, 0, 0, ip->i_ino);
48 12989714 : rblock->bb_level = dblock->bb_level;
49 12989714 : ASSERT(be16_to_cpu(rblock->bb_level) > 0);
50 12989714 : rblock->bb_numrecs = dblock->bb_numrecs;
51 12989714 : dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
52 12989714 : fkp = xfs_bmdr_key_addr(dblock, 1);
53 12989714 : tkp = xfs_bmbt_key_addr(mp, rblock, 1);
54 12989714 : fpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr);
55 12989714 : tpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen);
56 12989714 : dmxr = be16_to_cpu(dblock->bb_numrecs);
57 25979428 : memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
58 25979428 : memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
59 12989714 : }
60 :
61 : void
62 2332369594 : xfs_bmbt_disk_get_all(
63 : const struct xfs_bmbt_rec *rec,
64 : struct xfs_bmbt_irec *irec)
65 : {
66 2332369594 : uint64_t l0 = get_unaligned_be64(&rec->l0);
67 : uint64_t l1 = get_unaligned_be64(&rec->l1);
68 :
69 2332369594 : irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
70 2332369594 : irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
71 2332369594 : irec->br_blockcount = l1 & xfs_mask64lo(21);
72 2332369594 : if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
73 126578491 : irec->br_state = XFS_EXT_UNWRITTEN;
74 : else
75 2205791103 : irec->br_state = XFS_EXT_NORM;
76 2332369594 : }
77 :
78 : /*
79 : * Extract the blockcount field from an on disk bmap extent record.
80 : */
81 : xfs_filblks_t
82 >15011*10^7 : xfs_bmbt_disk_get_blockcount(
83 : const struct xfs_bmbt_rec *r)
84 : {
85 >15106*10^7 : return (xfs_filblks_t)(be64_to_cpu(r->l1) & xfs_mask64lo(21));
86 : }
87 :
88 : /*
89 : * Extract the startoff field from a disk format bmap extent record.
90 : */
91 : xfs_fileoff_t
92 >30254*10^7 : xfs_bmbt_disk_get_startoff(
93 : const struct xfs_bmbt_rec *r)
94 : {
95 >30763*10^7 : return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
96 >30763*10^7 : xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
97 : }
98 :
99 : /*
100 : * Set all the fields in a bmap extent record from the uncompressed form.
101 : */
102 : void
103 3687568823 : xfs_bmbt_disk_set_all(
104 : struct xfs_bmbt_rec *r,
105 : struct xfs_bmbt_irec *s)
106 : {
107 3687568823 : int extent_flag = (s->br_state != XFS_EXT_NORM);
108 :
109 3687568823 : ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
110 3687568823 : ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
111 3687568823 : ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
112 3687568823 : ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
113 :
114 3687568823 : put_unaligned_be64(
115 3687568823 : ((xfs_bmbt_rec_base_t)extent_flag << 63) |
116 3687568823 : ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
117 3687568823 : ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
118 3687568823 : put_unaligned_be64(
119 3687568823 : ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
120 3687568823 : ((xfs_bmbt_rec_base_t)s->br_blockcount &
121 : (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
122 3687568823 : }
123 :
124 : /*
125 : * Convert in-memory form of btree root to on-disk form.
126 : */
127 : void
128 3791502 : xfs_bmbt_to_bmdr(
129 : struct xfs_mount *mp,
130 : struct xfs_btree_block *rblock,
131 : int rblocklen,
132 : xfs_bmdr_block_t *dblock,
133 : int dblocklen)
134 : {
135 3791502 : int dmxr;
136 3791502 : xfs_bmbt_key_t *fkp;
137 3791502 : __be64 *fpp;
138 3791502 : xfs_bmbt_key_t *tkp;
139 3791502 : __be64 *tpp;
140 :
141 3791502 : if (xfs_has_crc(mp)) {
142 3791502 : ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
143 3791502 : ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
144 : &mp->m_sb.sb_meta_uuid));
145 3791502 : ASSERT(rblock->bb_u.l.bb_blkno ==
146 : cpu_to_be64(XFS_BUF_DADDR_NULL));
147 : } else
148 0 : ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC));
149 3791502 : ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
150 3791502 : ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
151 3791502 : ASSERT(rblock->bb_level != 0);
152 3791502 : dblock->bb_level = rblock->bb_level;
153 3791502 : dblock->bb_numrecs = rblock->bb_numrecs;
154 3791502 : dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
155 3791502 : fkp = xfs_bmbt_key_addr(mp, rblock, 1);
156 3791502 : tkp = xfs_bmdr_key_addr(dblock, 1);
157 3791502 : fpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen);
158 3791502 : tpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr);
159 3791502 : dmxr = be16_to_cpu(dblock->bb_numrecs);
160 7583004 : memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
161 7583004 : memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
162 3791502 : }
163 :
164 : STATIC struct xfs_btree_cur *
165 59043696 : xfs_bmbt_dup_cursor(
166 : struct xfs_btree_cur *cur)
167 : {
168 59043696 : struct xfs_btree_cur *new;
169 :
170 59043696 : new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
171 59043696 : cur->bc_ino.ip, cur->bc_ino.whichfork);
172 :
173 : /*
174 : * Copy the firstblock, dfops, and flags values,
175 : * since init cursor doesn't get them.
176 : */
177 59044008 : new->bc_ino.flags = cur->bc_ino.flags;
178 :
179 59044008 : return new;
180 : }
181 :
182 : STATIC void
183 665184 : xfs_bmbt_update_cursor(
184 : struct xfs_btree_cur *src,
185 : struct xfs_btree_cur *dst)
186 : {
187 665184 : ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
188 : (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
189 :
190 665184 : dst->bc_ino.allocated += src->bc_ino.allocated;
191 665184 : dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
192 :
193 665184 : src->bc_ino.allocated = 0;
194 665184 : }
195 :
196 : STATIC int
197 668541 : xfs_bmbt_alloc_block(
198 : struct xfs_btree_cur *cur,
199 : const union xfs_btree_ptr *start,
200 : union xfs_btree_ptr *new,
201 : int *stat)
202 : {
203 668541 : struct xfs_alloc_arg args;
204 668541 : int error;
205 :
206 668541 : memset(&args, 0, sizeof(args));
207 668541 : args.tp = cur->bc_tp;
208 668541 : args.mp = cur->bc_mp;
209 668541 : xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
210 668541 : cur->bc_ino.whichfork);
211 668541 : args.minlen = args.maxlen = args.prod = 1;
212 668541 : args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
213 668541 : if (!args.wasdel && args.tp->t_blk_res == 0)
214 : return -ENOSPC;
215 :
216 : /*
217 : * If we are coming here from something like unwritten extent
218 : * conversion, there has been no data extent allocation already done, so
219 : * we have to ensure that we attempt to locate the entire set of bmbt
220 : * allocations in the same AG, as xfs_bmapi_write() would have reserved.
221 : */
222 668541 : if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
223 611118 : args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
224 : cur->bc_ino.whichfork);
225 :
226 668541 : error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
227 668542 : if (error)
228 : return error;
229 :
230 668538 : if (args.fsbno == NULLFSBLOCK && args.minleft) {
231 : /*
232 : * Could not find an AG with enough free space to satisfy
233 : * a full btree split. Try again and if
234 : * successful activate the lowspace algorithm.
235 : */
236 0 : args.minleft = 0;
237 0 : error = xfs_alloc_vextent_start_ag(&args, 0);
238 0 : if (error)
239 : return error;
240 0 : cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE;
241 : }
242 668538 : if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
243 0 : *stat = 0;
244 0 : return 0;
245 : }
246 :
247 668538 : ASSERT(args.len == 1);
248 668538 : cur->bc_ino.allocated++;
249 668538 : cur->bc_ino.ip->i_nblocks++;
250 668538 : xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
251 668538 : xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
252 : XFS_TRANS_DQ_BCOUNT, 1L);
253 :
254 668538 : new->l = cpu_to_be64(args.fsbno);
255 :
256 668538 : *stat = 1;
257 668538 : return 0;
258 : }
259 :
260 : STATIC int
261 183902 : xfs_bmbt_free_block(
262 : struct xfs_btree_cur *cur,
263 : struct xfs_buf *bp)
264 : {
265 183902 : struct xfs_mount *mp = cur->bc_mp;
266 183902 : struct xfs_inode *ip = cur->bc_ino.ip;
267 183902 : struct xfs_trans *tp = cur->bc_tp;
268 183902 : xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
269 183902 : struct xfs_owner_info oinfo;
270 183902 : int error;
271 :
272 183902 : xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
273 183902 : error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
274 : XFS_AG_RESV_NONE, 0);
275 183902 : if (error)
276 : return error;
277 :
278 183902 : ip->i_nblocks--;
279 183902 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
280 183902 : xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
281 183902 : return 0;
282 : }
283 :
284 : STATIC int
285 138074245 : xfs_bmbt_get_minrecs(
286 : struct xfs_btree_cur *cur,
287 : int level)
288 : {
289 138074245 : if (level == cur->bc_nlevels - 1) {
290 2508496 : struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur);
291 :
292 2508425 : return xfs_bmbt_maxrecs(cur->bc_mp,
293 2508425 : ifp->if_broot_bytes, level == 0) / 2;
294 : }
295 :
296 135565749 : return cur->bc_mp->m_bmap_dmnr[level != 0];
297 : }
298 :
299 : int
300 2388850835 : xfs_bmbt_get_maxrecs(
301 : struct xfs_btree_cur *cur,
302 : int level)
303 : {
304 2388850835 : if (level == cur->bc_nlevels - 1) {
305 525807960 : struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur);
306 :
307 525806311 : return xfs_bmbt_maxrecs(cur->bc_mp,
308 525806311 : ifp->if_broot_bytes, level == 0);
309 : }
310 :
311 1863042875 : return cur->bc_mp->m_bmap_dmxr[level != 0];
312 :
313 : }
314 :
315 : /*
316 : * Get the maximum records we could store in the on-disk format.
317 : *
318 : * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but
319 : * for the root node this checks the available space in the dinode fork
320 : * so that we can resize the in-memory buffer to match it. After a
321 : * resize to the maximum size this function returns the same value
322 : * as xfs_bmbt_get_maxrecs for the root node, too.
323 : */
324 : STATIC int
325 3353544 : xfs_bmbt_get_dmaxrecs(
326 : struct xfs_btree_cur *cur,
327 : int level)
328 : {
329 3353544 : if (level != cur->bc_nlevels - 1)
330 211242 : return cur->bc_mp->m_bmap_dmxr[level != 0];
331 3142302 : return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
332 : }
333 :
334 : STATIC void
335 4144397854 : xfs_bmbt_init_key_from_rec(
336 : union xfs_btree_key *key,
337 : const union xfs_btree_rec *rec)
338 : {
339 4144397854 : key->bmbt.br_startoff =
340 4144397854 : cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
341 4144397854 : }
342 :
343 : STATIC void
344 0 : xfs_bmbt_init_high_key_from_rec(
345 : union xfs_btree_key *key,
346 : const union xfs_btree_rec *rec)
347 : {
348 0 : key->bmbt.br_startoff = cpu_to_be64(
349 : xfs_bmbt_disk_get_startoff(&rec->bmbt) +
350 : xfs_bmbt_disk_get_blockcount(&rec->bmbt) - 1);
351 0 : }
352 :
353 : STATIC void
354 307496939 : xfs_bmbt_init_rec_from_cur(
355 : struct xfs_btree_cur *cur,
356 : union xfs_btree_rec *rec)
357 : {
358 307496939 : xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
359 307496171 : }
360 :
361 : STATIC void
362 509117797 : xfs_bmbt_init_ptr_from_cur(
363 : struct xfs_btree_cur *cur,
364 : union xfs_btree_ptr *ptr)
365 : {
366 509117797 : ptr->l = 0;
367 509117797 : }
368 :
369 : STATIC int64_t
370 5491437452 : xfs_bmbt_key_diff(
371 : struct xfs_btree_cur *cur,
372 : const union xfs_btree_key *key)
373 : {
374 5491437452 : return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
375 5491437452 : cur->bc_rec.b.br_startoff;
376 : }
377 :
378 : STATIC int64_t
379 717165527 : xfs_bmbt_diff_two_keys(
380 : struct xfs_btree_cur *cur,
381 : const union xfs_btree_key *k1,
382 : const union xfs_btree_key *k2,
383 : const union xfs_btree_key *mask)
384 : {
385 717165527 : uint64_t a = be64_to_cpu(k1->bmbt.br_startoff);
386 717165527 : uint64_t b = be64_to_cpu(k2->bmbt.br_startoff);
387 :
388 717165527 : ASSERT(!mask || mask->bmbt.br_startoff);
389 :
390 : /*
391 : * Note: This routine previously casted a and b to int64 and subtracted
392 : * them to generate a result. This lead to problems if b was the
393 : * "maximum" key value (all ones) being signed incorrectly, hence this
394 : * somewhat less efficient version.
395 : */
396 717165527 : if (a > b)
397 : return 1;
398 16276697 : if (b > a)
399 0 : return -1;
400 : return 0;
401 : }
402 :
403 : static xfs_failaddr_t
404 34971909 : xfs_bmbt_verify(
405 : struct xfs_buf *bp)
406 : {
407 34971909 : struct xfs_mount *mp = bp->b_mount;
408 34971909 : struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
409 34971909 : xfs_failaddr_t fa;
410 34971909 : unsigned int level;
411 :
412 34971909 : if (!xfs_verify_magic(bp, block->bb_magic))
413 0 : return __this_address;
414 :
415 34971740 : if (xfs_has_crc(mp)) {
416 : /*
417 : * XXX: need a better way of verifying the owner here. Right now
418 : * just make sure there has been one set.
419 : */
420 34971708 : fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
421 34971802 : if (fa)
422 : return fa;
423 : }
424 :
425 : /*
426 : * numrecs and level verification.
427 : *
428 : * We don't know what fork we belong to, so just verify that the level
429 : * is less than the maximum of the two. Later checks will be more
430 : * precise.
431 : */
432 34971852 : level = be16_to_cpu(block->bb_level);
433 34971852 : if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
434 0 : return __this_address;
435 :
436 34971852 : return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
437 : }
438 :
439 : static void
440 5166785 : xfs_bmbt_read_verify(
441 : struct xfs_buf *bp)
442 : {
443 5166785 : xfs_failaddr_t fa;
444 :
445 5166785 : if (!xfs_btree_lblock_verify_crc(bp))
446 20 : xfs_verifier_error(bp, -EFSBADCRC, __this_address);
447 : else {
448 5166765 : fa = xfs_bmbt_verify(bp);
449 5166765 : if (fa)
450 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
451 : }
452 :
453 5166785 : if (bp->b_error)
454 20 : trace_xfs_btree_corrupt(bp, _RET_IP_);
455 5166785 : }
456 :
457 : static void
458 19774776 : xfs_bmbt_write_verify(
459 : struct xfs_buf *bp)
460 : {
461 19774776 : xfs_failaddr_t fa;
462 :
463 19774776 : fa = xfs_bmbt_verify(bp);
464 19774774 : if (fa) {
465 0 : trace_xfs_btree_corrupt(bp, _RET_IP_);
466 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
467 0 : return;
468 : }
469 19774774 : xfs_btree_lblock_calc_crc(bp);
470 : }
471 :
472 : const struct xfs_buf_ops xfs_bmbt_buf_ops = {
473 : .name = "xfs_bmbt",
474 : .magic = { cpu_to_be32(XFS_BMAP_MAGIC),
475 : cpu_to_be32(XFS_BMAP_CRC_MAGIC) },
476 : .verify_read = xfs_bmbt_read_verify,
477 : .verify_write = xfs_bmbt_write_verify,
478 : .verify_struct = xfs_bmbt_verify,
479 : };
480 :
481 :
482 : STATIC int
483 3123793 : xfs_bmbt_keys_inorder(
484 : struct xfs_btree_cur *cur,
485 : const union xfs_btree_key *k1,
486 : const union xfs_btree_key *k2)
487 : {
488 3123793 : return be64_to_cpu(k1->bmbt.br_startoff) <
489 3123793 : be64_to_cpu(k2->bmbt.br_startoff);
490 : }
491 :
492 : STATIC int
493 944720602 : xfs_bmbt_recs_inorder(
494 : struct xfs_btree_cur *cur,
495 : const union xfs_btree_rec *r1,
496 : const union xfs_btree_rec *r2)
497 : {
498 944720602 : return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
499 944720602 : xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
500 : xfs_bmbt_disk_get_startoff(&r2->bmbt);
501 : }
502 :
503 : STATIC enum xbtree_key_contig
504 0 : xfs_bmbt_keys_contiguous(
505 : struct xfs_btree_cur *cur,
506 : const union xfs_btree_key *key1,
507 : const union xfs_btree_key *key2,
508 : const union xfs_btree_key *mask)
509 : {
510 0 : ASSERT(!mask || mask->bmbt.br_startoff);
511 :
512 0 : return xbtree_key_contig(be64_to_cpu(key1->bmbt.br_startoff),
513 0 : be64_to_cpu(key2->bmbt.br_startoff));
514 : }
515 :
516 : /* Move the bmap btree root from one incore buffer to another. */
517 : static void
518 233496 : xfs_bmbt_broot_move(
519 : struct xfs_inode *ip,
520 : int whichfork,
521 : struct xfs_btree_block *dst_broot,
522 : size_t dst_bytes,
523 : struct xfs_btree_block *src_broot,
524 : size_t src_bytes,
525 : unsigned int level,
526 : unsigned int numrecs)
527 : {
528 233496 : struct xfs_mount *mp = ip->i_mount;
529 233496 : void *dptr;
530 233496 : void *sptr;
531 :
532 233496 : ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork));
533 233496 : ASSERT(level > 0);
534 :
535 : /*
536 : * We always have to move the pointers because they are not butted
537 : * against the btree block header.
538 : */
539 233496 : if (numrecs) {
540 233496 : sptr = xfs_bmap_broot_ptr_addr(mp, src_broot, 1, src_bytes);
541 233496 : dptr = xfs_bmap_broot_ptr_addr(mp, dst_broot, 1, dst_bytes);
542 466992 : memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t));
543 : }
544 :
545 233496 : if (src_broot == dst_broot)
546 : return;
547 :
548 : /*
549 : * If the root is being totally relocated, we have to migrate the block
550 : * header and the keys that come after it.
551 : */
552 75636 : memcpy(dst_broot, src_broot, xfs_bmbt_block_len(mp));
553 :
554 : /* Now copy the keys, which come right after the header. */
555 37818 : if (numrecs) {
556 37818 : sptr = xfs_bmbt_key_addr(mp, src_broot, 1);
557 37818 : dptr = xfs_bmbt_key_addr(mp, dst_broot, 1);
558 75636 : memcpy(dptr, sptr, numrecs * sizeof(struct xfs_bmbt_key));
559 : }
560 : }
561 :
562 : static const struct xfs_ifork_broot_ops xfs_bmbt_iroot_ops = {
563 : .maxrecs = xfs_bmbt_maxrecs,
564 : .size = xfs_bmap_broot_space_calc,
565 : .move = xfs_bmbt_broot_move,
566 : };
567 :
568 : const struct xfs_btree_ops xfs_bmbt_ops = {
569 : .rec_len = sizeof(xfs_bmbt_rec_t),
570 : .key_len = sizeof(xfs_bmbt_key_t),
571 : .lru_refs = XFS_BMAP_BTREE_REF,
572 : .geom_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE,
573 :
574 : .dup_cursor = xfs_bmbt_dup_cursor,
575 : .update_cursor = xfs_bmbt_update_cursor,
576 : .alloc_block = xfs_bmbt_alloc_block,
577 : .free_block = xfs_bmbt_free_block,
578 : .get_maxrecs = xfs_bmbt_get_maxrecs,
579 : .get_minrecs = xfs_bmbt_get_minrecs,
580 : .get_dmaxrecs = xfs_bmbt_get_dmaxrecs,
581 : .init_key_from_rec = xfs_bmbt_init_key_from_rec,
582 : .init_high_key_from_rec = xfs_bmbt_init_high_key_from_rec,
583 : .init_rec_from_cur = xfs_bmbt_init_rec_from_cur,
584 : .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur,
585 : .key_diff = xfs_bmbt_key_diff,
586 : .diff_two_keys = xfs_bmbt_diff_two_keys,
587 : .buf_ops = &xfs_bmbt_buf_ops,
588 : .keys_inorder = xfs_bmbt_keys_inorder,
589 : .recs_inorder = xfs_bmbt_recs_inorder,
590 : .keys_contiguous = xfs_bmbt_keys_contiguous,
591 : .iroot_ops = &xfs_bmbt_iroot_ops,
592 : };
593 :
594 : /*
595 : * Allocate a new bmap btree cursor.
596 : */
597 : static struct xfs_btree_cur * /* new bmap btree cursor */
598 541636988 : xfs_bmbt_init_common(
599 : struct xfs_mount *mp, /* file system mount point */
600 : struct xfs_trans *tp, /* transaction pointer */
601 : struct xfs_inode *ip, /* inode owning the btree */
602 : int whichfork)
603 : {
604 541636988 : struct xfs_btree_cur *cur;
605 :
606 541636988 : ASSERT(whichfork != XFS_COW_FORK);
607 :
608 1083276305 : cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, &xfs_bmbt_ops,
609 541636988 : mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
610 541646672 : cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
611 :
612 541646672 : cur->bc_ino.ip = ip;
613 541646672 : cur->bc_ino.allocated = 0;
614 541646672 : cur->bc_ino.flags = 0;
615 :
616 541646672 : return cur;
617 : }
618 :
619 : /*
620 : * Allocate a new bmap btree cursor.
621 : */
622 : struct xfs_btree_cur * /* new bmap btree cursor */
623 538304488 : xfs_bmbt_init_cursor(
624 : struct xfs_mount *mp, /* file system mount point */
625 : struct xfs_trans *tp, /* transaction pointer */
626 : struct xfs_inode *ip, /* inode owning the btree */
627 : int whichfork) /* data or attr fork */
628 : {
629 538304488 : struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
630 538297019 : struct xfs_btree_cur *cur;
631 :
632 538297019 : cur = xfs_bmbt_init_common(mp, tp, ip, whichfork);
633 :
634 538306715 : cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
635 538306715 : cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
636 538306715 : cur->bc_ino.whichfork = whichfork;
637 :
638 538306715 : return cur;
639 : }
640 :
641 : /* Calculate number of records in a block mapping btree block. */
642 : static inline unsigned int
643 : xfs_bmbt_block_maxrecs(
644 : unsigned int blocklen,
645 : bool leaf)
646 : {
647 1335910728 : if (leaf)
648 66982 : return blocklen / sizeof(xfs_bmbt_rec_t);
649 1318829034 : return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t));
650 : }
651 :
652 : /*
653 : * Allocate a new bmap btree cursor for reloading an inode block mapping data
654 : * structure. Note that callers can use the staged cursor to reload extents
655 : * format inode forks if they rebuild the iext tree and commit the staged
656 : * cursor immediately.
657 : */
658 : struct xfs_btree_cur *
659 3340419 : xfs_bmbt_stage_cursor(
660 : struct xfs_mount *mp,
661 : struct xfs_inode *ip,
662 : struct xbtree_ifakeroot *ifake)
663 : {
664 3340419 : struct xfs_btree_cur *cur;
665 3340419 : struct xfs_btree_ops *ops;
666 :
667 3340419 : cur = xfs_bmbt_init_common(mp, NULL, ip, ifake->if_whichfork);
668 3340419 : cur->bc_nlevels = ifake->if_levels;
669 3340419 : cur->bc_ino.forksize = ifake->if_fork_size;
670 : /* Don't let anyone think we're attached to the real fork yet. */
671 3340419 : cur->bc_ino.whichfork = -1;
672 3340419 : xfs_btree_stage_ifakeroot(cur, ifake, &ops);
673 3340419 : ops->update_cursor = NULL;
674 3340419 : return cur;
675 : }
676 :
677 : /*
678 : * Swap in the new inode fork root. Once we pass this point the newly rebuilt
679 : * mappings are in place and we have to kill off any old btree blocks.
680 : */
681 : void
682 3340405 : xfs_bmbt_commit_staged_btree(
683 : struct xfs_btree_cur *cur,
684 : struct xfs_trans *tp,
685 : int whichfork)
686 : {
687 3340405 : struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
688 3340405 : struct xfs_ifork *ifp;
689 3340405 : static const short brootflag[2] =
690 : { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
691 3340405 : static const short extflag[2] =
692 : { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
693 3340405 : int flags = XFS_ILOG_CORE;
694 :
695 3340405 : ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
696 3340405 : ASSERT(whichfork != XFS_COW_FORK);
697 :
698 : /*
699 : * Free any resources hanging off the real fork, then shallow-copy the
700 : * staging fork's contents into the real fork to transfer everything
701 : * we just built.
702 : */
703 3340405 : ifp = xfs_ifork_ptr(cur->bc_ino.ip, whichfork);
704 3340405 : xfs_idestroy_fork(ifp);
705 6680806 : memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
706 :
707 3340403 : switch (ifp->if_format) {
708 3241364 : case XFS_DINODE_FMT_EXTENTS:
709 3241364 : flags |= extflag[whichfork];
710 3241364 : break;
711 99039 : case XFS_DINODE_FMT_BTREE:
712 99039 : flags |= brootflag[whichfork];
713 99040 : break;
714 0 : default:
715 0 : ASSERT(0);
716 0 : break;
717 : }
718 3340404 : xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
719 3340404 : xfs_btree_commit_ifakeroot(cur, tp, whichfork, &xfs_bmbt_ops);
720 3340404 : }
721 :
722 : /*
723 : * Calculate number of records in a bmap btree block.
724 : */
725 : unsigned int
726 790581280 : xfs_bmbt_maxrecs(
727 : struct xfs_mount *mp,
728 : unsigned int blocklen,
729 : bool leaf)
730 : {
731 1319129512 : blocklen -= xfs_bmbt_block_len(mp);
732 1335910728 : return xfs_bmbt_block_maxrecs(blocklen, leaf);
733 : }
734 :
735 : /*
736 : * Calculate the maximum possible height of the btree that the on-disk format
737 : * supports. This is used for sizing structures large enough to support every
738 : * possible configuration of a filesystem that might get mounted.
739 : */
740 : unsigned int
741 134003 : xfs_bmbt_maxlevels_ondisk(void)
742 : {
743 134003 : unsigned int minrecs[2];
744 134003 : unsigned int blocklen;
745 :
746 134003 : blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
747 : XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
748 :
749 134003 : minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
750 134003 : minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
751 :
752 : /* One extra level for the inode root. */
753 134003 : return xfs_btree_compute_maxlevels(minrecs,
754 134003 : XFS_MAX_EXTCNT_DATA_FORK_LARGE) + 1;
755 : }
756 :
757 : /*
758 : * Calculate number of records in a bmap btree inode root.
759 : */
760 : int
761 133944 : xfs_bmdr_maxrecs(
762 : int blocklen,
763 : int leaf)
764 : {
765 20057462 : blocklen -= sizeof(xfs_bmdr_block_t);
766 :
767 3276246 : if (leaf)
768 198110 : return blocklen / sizeof(xfs_bmdr_rec_t);
769 19859352 : return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
770 : }
771 :
772 : /*
773 : * Change the owner of a btree format fork fo the inode passed in. Change it to
774 : * the owner of that is passed in so that we can change owners before or after
775 : * we switch forks between inodes. The operation that the caller is doing will
776 : * determine whether is needs to change owner before or after the switch.
777 : *
778 : * For demand paged transactional modification, the fork switch should be done
779 : * after reading in all the blocks, modifying them and pinning them in the
780 : * transaction. For modification when the buffers are already pinned in memory,
781 : * the fork switch can be done before changing the owner as we won't need to
782 : * validate the owner until the btree buffers are unpinned and writes can occur
783 : * again.
784 : *
785 : * For recovery based ownership change, there is no transactional context and
786 : * so a buffer list must be supplied so that we can record the buffers that we
787 : * modified for the caller to issue IO on.
788 : */
789 : int
790 2707 : xfs_bmbt_change_owner(
791 : struct xfs_trans *tp,
792 : struct xfs_inode *ip,
793 : int whichfork,
794 : xfs_ino_t new_owner,
795 : struct list_head *buffer_list)
796 : {
797 2707 : struct xfs_btree_cur *cur;
798 2707 : int error;
799 :
800 2707 : ASSERT(tp || buffer_list);
801 2707 : ASSERT(!(tp && buffer_list));
802 2707 : ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
803 :
804 2707 : cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
805 2707 : cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
806 :
807 2707 : error = xfs_btree_change_owner(cur, new_owner, buffer_list);
808 2707 : xfs_btree_del_cursor(cur, error);
809 2707 : return error;
810 : }
811 :
812 : /* Calculate the bmap btree size for some records. */
813 : unsigned long long
814 242690 : xfs_bmbt_calc_size(
815 : struct xfs_mount *mp,
816 : unsigned long long len)
817 : {
818 242690 : return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
819 : }
820 :
821 : int __init
822 59 : xfs_bmbt_init_cur_cache(void)
823 : {
824 59 : xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
825 59 : xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
826 : 0, 0, NULL);
827 :
828 59 : if (!xfs_bmbt_cur_cache)
829 0 : return -ENOMEM;
830 : return 0;
831 : }
832 :
833 : void
834 58 : xfs_bmbt_destroy_cur_cache(void)
835 : {
836 58 : kmem_cache_destroy(xfs_bmbt_cur_cache);
837 58 : xfs_bmbt_cur_cache = NULL;
838 58 : }
839 :
840 : /* Create an incore bmbt btree root block. */
841 : void
842 3746201 : xfs_bmbt_iroot_alloc(
843 : struct xfs_inode *ip,
844 : int whichfork)
845 : {
846 3746201 : struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
847 :
848 3746196 : xfs_iroot_alloc(ip, whichfork,
849 : xfs_bmap_broot_space_calc(ip->i_mount, 1, 1));
850 :
851 : /* Fill in the root. */
852 3746204 : xfs_btree_init_block(ip->i_mount, ifp->if_broot, &xfs_bmbt_ops, 1, 1,
853 : ip->i_ino);
854 3746196 : }
|