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 14100517 : 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 14100517 : struct xfs_mount *mp = ip->i_mount;
41 14100517 : int dmxr;
42 14100517 : xfs_bmbt_key_t *fkp;
43 14100517 : __be64 *fpp;
44 14100517 : xfs_bmbt_key_t *tkp;
45 14100517 : __be64 *tpp;
46 :
47 14100517 : xfs_btree_init_block(mp, rblock, &xfs_bmbt_ops, 0, 0, ip->i_ino);
48 14100505 : rblock->bb_level = dblock->bb_level;
49 14100505 : ASSERT(be16_to_cpu(rblock->bb_level) > 0);
50 14100505 : rblock->bb_numrecs = dblock->bb_numrecs;
51 14100505 : dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
52 14100505 : fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
53 28201010 : tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
54 14100505 : fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
55 14100505 : tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
56 14100505 : dmxr = be16_to_cpu(dblock->bb_numrecs);
57 14100505 : memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
58 28201010 : memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
59 14100505 : }
60 :
61 : void
62 1775382157 : xfs_bmbt_disk_get_all(
63 : const struct xfs_bmbt_rec *rec,
64 : struct xfs_bmbt_irec *irec)
65 : {
66 1775382157 : uint64_t l0 = get_unaligned_be64(&rec->l0);
67 : uint64_t l1 = get_unaligned_be64(&rec->l1);
68 :
69 1775382157 : irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
70 1775382157 : irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
71 1775382157 : irec->br_blockcount = l1 & xfs_mask64lo(21);
72 1775382157 : if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
73 133745057 : irec->br_state = XFS_EXT_UNWRITTEN;
74 : else
75 1641637100 : irec->br_state = XFS_EXT_NORM;
76 1775382157 : }
77 :
78 : /*
79 : * Extract the blockcount field from an on disk bmap extent record.
80 : */
81 : xfs_filblks_t
82 >11647*10^7 : xfs_bmbt_disk_get_blockcount(
83 : const struct xfs_bmbt_rec *r)
84 : {
85 >11690*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 >23326*10^7 : xfs_bmbt_disk_get_startoff(
93 : const struct xfs_bmbt_rec *r)
94 : {
95 >23658*10^7 : return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
96 >23658*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 2681922893 : xfs_bmbt_disk_set_all(
104 : struct xfs_bmbt_rec *r,
105 : struct xfs_bmbt_irec *s)
106 : {
107 2681922893 : int extent_flag = (s->br_state != XFS_EXT_NORM);
108 :
109 2681922893 : ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
110 2681922893 : ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
111 2681922893 : ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
112 2681922893 : ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
113 :
114 2681922893 : put_unaligned_be64(
115 2681922893 : ((xfs_bmbt_rec_base_t)extent_flag << 63) |
116 2681922893 : ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
117 2681922893 : ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
118 2681922893 : put_unaligned_be64(
119 2681922893 : ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
120 2681922893 : ((xfs_bmbt_rec_base_t)s->br_blockcount &
121 : (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
122 2681922893 : }
123 :
124 : /*
125 : * Convert in-memory form of btree root to on-disk form.
126 : */
127 : void
128 2320692 : 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 2320692 : int dmxr;
136 2320692 : xfs_bmbt_key_t *fkp;
137 2320692 : __be64 *fpp;
138 2320692 : xfs_bmbt_key_t *tkp;
139 2320692 : __be64 *tpp;
140 :
141 2320692 : if (xfs_has_crc(mp)) {
142 2320692 : ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
143 2320692 : ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
144 : &mp->m_sb.sb_meta_uuid));
145 2320692 : 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 2320692 : ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
150 2320692 : ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
151 2320692 : ASSERT(rblock->bb_level != 0);
152 2320692 : dblock->bb_level = rblock->bb_level;
153 2320692 : dblock->bb_numrecs = rblock->bb_numrecs;
154 2320692 : dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
155 4641384 : fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
156 2320692 : tkp = XFS_BMDR_KEY_ADDR(dblock, 1);
157 2320692 : fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
158 2320692 : tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
159 2320692 : dmxr = be16_to_cpu(dblock->bb_numrecs);
160 2320692 : memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
161 4641384 : memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
162 2320692 : }
163 :
164 : STATIC struct xfs_btree_cur *
165 55259352 : xfs_bmbt_dup_cursor(
166 : struct xfs_btree_cur *cur)
167 : {
168 55259352 : struct xfs_btree_cur *new;
169 :
170 55259352 : new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
171 55259352 : 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 55260000 : new->bc_ino.flags = cur->bc_ino.flags;
178 :
179 55260000 : return new;
180 : }
181 :
182 : STATIC void
183 481093 : xfs_bmbt_update_cursor(
184 : struct xfs_btree_cur *src,
185 : struct xfs_btree_cur *dst)
186 : {
187 481093 : ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
188 : (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
189 :
190 481093 : dst->bc_ino.allocated += src->bc_ino.allocated;
191 481093 : dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
192 :
193 481093 : src->bc_ino.allocated = 0;
194 481093 : }
195 :
196 : STATIC int
197 483974 : 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 483974 : struct xfs_alloc_arg args;
204 483974 : int error;
205 :
206 483974 : memset(&args, 0, sizeof(args));
207 483974 : args.tp = cur->bc_tp;
208 483974 : args.mp = cur->bc_mp;
209 483974 : xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
210 483974 : cur->bc_ino.whichfork);
211 483974 : args.minlen = args.maxlen = args.prod = 1;
212 483974 : args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
213 483974 : 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 483974 : if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
223 445407 : args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
224 : cur->bc_ino.whichfork);
225 :
226 483976 : error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
227 483975 : if (error)
228 : return error;
229 :
230 483972 : 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 483972 : if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
243 0 : *stat = 0;
244 0 : return 0;
245 : }
246 :
247 483972 : ASSERT(args.len == 1);
248 483972 : cur->bc_ino.allocated++;
249 483972 : cur->bc_ino.ip->i_nblocks++;
250 483972 : xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
251 483972 : xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
252 : XFS_TRANS_DQ_BCOUNT, 1L);
253 :
254 483972 : new->l = cpu_to_be64(args.fsbno);
255 :
256 483972 : *stat = 1;
257 483972 : return 0;
258 : }
259 :
260 : STATIC int
261 188676 : xfs_bmbt_free_block(
262 : struct xfs_btree_cur *cur,
263 : struct xfs_buf *bp)
264 : {
265 188676 : struct xfs_mount *mp = cur->bc_mp;
266 188676 : struct xfs_inode *ip = cur->bc_ino.ip;
267 188676 : struct xfs_trans *tp = cur->bc_tp;
268 188676 : xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
269 188676 : struct xfs_owner_info oinfo;
270 188676 : int error;
271 :
272 188676 : xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
273 188676 : error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
274 : XFS_AG_RESV_NONE);
275 188676 : if (error)
276 : return error;
277 :
278 188676 : ip->i_nblocks--;
279 188676 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
280 188676 : xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
281 188676 : return 0;
282 : }
283 :
284 : STATIC int
285 121464498 : xfs_bmbt_get_minrecs(
286 : struct xfs_btree_cur *cur,
287 : int level)
288 : {
289 121464498 : if (level == cur->bc_nlevels - 1) {
290 2331362 : struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur);
291 :
292 2331098 : return xfs_bmbt_maxrecs(cur->bc_mp,
293 4662196 : ifp->if_broot_bytes, level == 0) / 2;
294 : }
295 :
296 119133136 : return cur->bc_mp->m_bmap_dmnr[level != 0];
297 : }
298 :
299 : int
300 1926761137 : xfs_bmbt_get_maxrecs(
301 : struct xfs_btree_cur *cur,
302 : int level)
303 : {
304 1926761137 : if (level == cur->bc_nlevels - 1) {
305 402437072 : struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur);
306 :
307 402431702 : return xfs_bmbt_maxrecs(cur->bc_mp,
308 402431702 : ifp->if_broot_bytes, level == 0);
309 : }
310 :
311 1524324065 : 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 2661452 : xfs_bmbt_get_dmaxrecs(
326 : struct xfs_btree_cur *cur,
327 : int level)
328 : {
329 2661452 : if (level != cur->bc_nlevels - 1)
330 47696 : return cur->bc_mp->m_bmap_dmxr[level != 0];
331 2613756 : return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
332 : }
333 :
334 : STATIC void
335 2889758210 : xfs_bmbt_init_key_from_rec(
336 : union xfs_btree_key *key,
337 : const union xfs_btree_rec *rec)
338 : {
339 2889758210 : key->bmbt.br_startoff =
340 2889758210 : cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
341 2889758210 : }
342 :
343 : STATIC void
344 8 : xfs_bmbt_init_high_key_from_rec(
345 : union xfs_btree_key *key,
346 : const union xfs_btree_rec *rec)
347 : {
348 8 : 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 8 : }
352 :
353 : STATIC void
354 157898970 : xfs_bmbt_init_rec_from_cur(
355 : struct xfs_btree_cur *cur,
356 : union xfs_btree_rec *rec)
357 : {
358 157898970 : xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
359 157899427 : }
360 :
361 : STATIC void
362 371551388 : xfs_bmbt_init_ptr_from_cur(
363 : struct xfs_btree_cur *cur,
364 : union xfs_btree_ptr *ptr)
365 : {
366 371551388 : ptr->l = 0;
367 371551388 : }
368 :
369 : STATIC int64_t
370 4543735708 : xfs_bmbt_key_diff(
371 : struct xfs_btree_cur *cur,
372 : const union xfs_btree_key *key)
373 : {
374 4543735708 : return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
375 4543735708 : cur->bc_rec.b.br_startoff;
376 : }
377 :
378 : STATIC int64_t
379 259746238 : 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 259746238 : uint64_t a = be64_to_cpu(k1->bmbt.br_startoff);
386 259746238 : uint64_t b = be64_to_cpu(k2->bmbt.br_startoff);
387 :
388 259746238 : 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 259746238 : if (a > b)
397 : return 1;
398 9665600 : if (b > a)
399 128 : return -1;
400 : return 0;
401 : }
402 :
403 : static xfs_failaddr_t
404 19492573 : xfs_bmbt_verify(
405 : struct xfs_buf *bp)
406 : {
407 19492573 : struct xfs_mount *mp = bp->b_mount;
408 19492573 : struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
409 19492573 : xfs_failaddr_t fa;
410 19492573 : unsigned int level;
411 :
412 19492573 : if (!xfs_verify_magic(bp, block->bb_magic))
413 0 : return __this_address;
414 :
415 19492143 : 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 19492264 : fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
421 19492566 : 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 19492479 : level = be16_to_cpu(block->bb_level);
433 19492479 : if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
434 0 : return __this_address;
435 :
436 19492479 : return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
437 : }
438 :
439 : static void
440 5467933 : xfs_bmbt_read_verify(
441 : struct xfs_buf *bp)
442 : {
443 5467933 : xfs_failaddr_t fa;
444 :
445 5467933 : if (!xfs_btree_lblock_verify_crc(bp))
446 20 : xfs_verifier_error(bp, -EFSBADCRC, __this_address);
447 : else {
448 5467913 : fa = xfs_bmbt_verify(bp);
449 5467913 : if (fa)
450 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
451 : }
452 :
453 5467933 : if (bp->b_error)
454 20 : trace_xfs_btree_corrupt(bp, _RET_IP_);
455 5467933 : }
456 :
457 : static void
458 9286042 : xfs_bmbt_write_verify(
459 : struct xfs_buf *bp)
460 : {
461 9286042 : xfs_failaddr_t fa;
462 :
463 9286042 : fa = xfs_bmbt_verify(bp);
464 9286042 : if (fa) {
465 0 : trace_xfs_btree_corrupt(bp, _RET_IP_);
466 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
467 0 : return;
468 : }
469 9286042 : 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 1091330 : 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 1091330 : return be64_to_cpu(k1->bmbt.br_startoff) <
489 1091330 : be64_to_cpu(k2->bmbt.br_startoff);
490 : }
491 :
492 : STATIC int
493 429091080 : 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 429091080 : return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
499 429091080 : 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 : const struct xfs_btree_ops xfs_bmbt_ops = {
517 : .rec_len = sizeof(xfs_bmbt_rec_t),
518 : .key_len = sizeof(xfs_bmbt_key_t),
519 : .lru_refs = XFS_BMAP_BTREE_REF,
520 : .geom_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE,
521 :
522 : .dup_cursor = xfs_bmbt_dup_cursor,
523 : .update_cursor = xfs_bmbt_update_cursor,
524 : .alloc_block = xfs_bmbt_alloc_block,
525 : .free_block = xfs_bmbt_free_block,
526 : .get_maxrecs = xfs_bmbt_get_maxrecs,
527 : .get_minrecs = xfs_bmbt_get_minrecs,
528 : .get_dmaxrecs = xfs_bmbt_get_dmaxrecs,
529 : .init_key_from_rec = xfs_bmbt_init_key_from_rec,
530 : .init_high_key_from_rec = xfs_bmbt_init_high_key_from_rec,
531 : .init_rec_from_cur = xfs_bmbt_init_rec_from_cur,
532 : .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur,
533 : .key_diff = xfs_bmbt_key_diff,
534 : .diff_two_keys = xfs_bmbt_diff_two_keys,
535 : .buf_ops = &xfs_bmbt_buf_ops,
536 : .keys_inorder = xfs_bmbt_keys_inorder,
537 : .recs_inorder = xfs_bmbt_recs_inorder,
538 : .keys_contiguous = xfs_bmbt_keys_contiguous,
539 : };
540 :
541 : /*
542 : * Allocate a new bmap btree cursor.
543 : */
544 : static struct xfs_btree_cur * /* new bmap btree cursor */
545 401211007 : xfs_bmbt_init_common(
546 : struct xfs_mount *mp, /* file system mount point */
547 : struct xfs_trans *tp, /* transaction pointer */
548 : struct xfs_inode *ip, /* inode owning the btree */
549 : int whichfork)
550 : {
551 401211007 : struct xfs_btree_cur *cur;
552 :
553 401211007 : ASSERT(whichfork != XFS_COW_FORK);
554 :
555 802423724 : cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, &xfs_bmbt_ops,
556 401211007 : mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
557 401220800 : cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
558 :
559 401220800 : cur->bc_ino.ip = ip;
560 401220800 : cur->bc_ino.allocated = 0;
561 401220800 : cur->bc_ino.flags = 0;
562 :
563 401220800 : return cur;
564 : }
565 :
566 : /*
567 : * Allocate a new bmap btree cursor.
568 : */
569 : struct xfs_btree_cur * /* new bmap btree cursor */
570 398646845 : xfs_bmbt_init_cursor(
571 : struct xfs_mount *mp, /* file system mount point */
572 : struct xfs_trans *tp, /* transaction pointer */
573 : struct xfs_inode *ip, /* inode owning the btree */
574 : int whichfork) /* data or attr fork */
575 : {
576 398646845 : struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
577 398642597 : struct xfs_btree_cur *cur;
578 :
579 398642597 : cur = xfs_bmbt_init_common(mp, tp, ip, whichfork);
580 :
581 398652100 : cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
582 398652100 : cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
583 398652100 : cur->bc_ino.whichfork = whichfork;
584 :
585 398652100 : return cur;
586 : }
587 :
588 : /* Calculate number of records in a block mapping btree block. */
589 : static inline unsigned int
590 : xfs_bmbt_block_maxrecs(
591 : unsigned int blocklen,
592 : bool leaf)
593 : {
594 842142337 : if (leaf)
595 60890 : return blocklen / sizeof(xfs_bmbt_rec_t);
596 825660250 : return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t));
597 : }
598 :
599 : /*
600 : * Allocate a new bmap btree cursor for reloading an inode block mapping data
601 : * structure. Note that callers can use the staged cursor to reload extents
602 : * format inode forks if they rebuild the iext tree and commit the staged
603 : * cursor immediately.
604 : */
605 : struct xfs_btree_cur *
606 2568677 : xfs_bmbt_stage_cursor(
607 : struct xfs_mount *mp,
608 : struct xfs_inode *ip,
609 : struct xbtree_ifakeroot *ifake)
610 : {
611 2568677 : struct xfs_btree_cur *cur;
612 2568677 : struct xfs_btree_ops *ops;
613 :
614 2568677 : cur = xfs_bmbt_init_common(mp, NULL, ip, ifake->if_whichfork);
615 2568677 : cur->bc_nlevels = ifake->if_levels;
616 2568677 : cur->bc_ino.forksize = ifake->if_fork_size;
617 : /* Don't let anyone think we're attached to the real fork yet. */
618 2568677 : cur->bc_ino.whichfork = -1;
619 2568677 : xfs_btree_stage_ifakeroot(cur, ifake, &ops);
620 2568677 : ops->update_cursor = NULL;
621 2568677 : return cur;
622 : }
623 :
624 : /*
625 : * Swap in the new inode fork root. Once we pass this point the newly rebuilt
626 : * mappings are in place and we have to kill off any old btree blocks.
627 : */
628 : void
629 2568665 : xfs_bmbt_commit_staged_btree(
630 : struct xfs_btree_cur *cur,
631 : struct xfs_trans *tp,
632 : int whichfork)
633 : {
634 2568665 : struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
635 2568665 : struct xfs_ifork *ifp;
636 2568665 : static const short brootflag[2] =
637 : { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
638 2568665 : static const short extflag[2] =
639 : { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
640 2568665 : int flags = XFS_ILOG_CORE;
641 :
642 2568665 : ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
643 2568665 : ASSERT(whichfork != XFS_COW_FORK);
644 :
645 : /*
646 : * Free any resources hanging off the real fork, then shallow-copy the
647 : * staging fork's contents into the real fork to transfer everything
648 : * we just built.
649 : */
650 2568665 : ifp = xfs_ifork_ptr(cur->bc_ino.ip, whichfork);
651 2568665 : xfs_idestroy_fork(ifp);
652 5137330 : memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
653 :
654 2568665 : switch (ifp->if_format) {
655 2544908 : case XFS_DINODE_FMT_EXTENTS:
656 2544908 : flags |= extflag[whichfork];
657 2544908 : break;
658 23757 : case XFS_DINODE_FMT_BTREE:
659 23757 : flags |= brootflag[whichfork];
660 23757 : break;
661 0 : default:
662 0 : ASSERT(0);
663 0 : break;
664 : }
665 2568665 : xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
666 2568665 : xfs_btree_commit_ifakeroot(cur, tp, whichfork, &xfs_bmbt_ops);
667 2568665 : }
668 :
669 : /*
670 : * Calculate number of records in a bmap btree block.
671 : */
672 : int
673 420958340 : xfs_bmbt_maxrecs(
674 : struct xfs_mount *mp,
675 : int blocklen,
676 : int leaf)
677 : {
678 825721140 : blocklen -= XFS_BMBT_BLOCK_LEN(mp);
679 1246905137 : return xfs_bmbt_block_maxrecs(blocklen, leaf);
680 : }
681 :
682 : /*
683 : * Calculate the maximum possible height of the btree that the on-disk format
684 : * supports. This is used for sizing structures large enough to support every
685 : * possible configuration of a filesystem that might get mounted.
686 : */
687 : unsigned int
688 121810 : xfs_bmbt_maxlevels_ondisk(void)
689 : {
690 121810 : unsigned int minrecs[2];
691 121810 : unsigned int blocklen;
692 :
693 121810 : blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
694 : XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
695 :
696 121810 : minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
697 121810 : minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
698 :
699 : /* One extra level for the inode root. */
700 121810 : return xfs_btree_compute_maxlevels(minrecs,
701 121810 : XFS_MAX_EXTCNT_DATA_FORK_LARGE) + 1;
702 : }
703 :
704 : /*
705 : * Calculate number of records in a bmap btree inode root.
706 : */
707 : int
708 121760 : xfs_bmdr_maxrecs(
709 : int blocklen,
710 : int leaf)
711 : {
712 19156713 : blocklen -= sizeof(xfs_bmdr_block_t);
713 :
714 2735516 : if (leaf)
715 47538 : return blocklen / sizeof(xfs_bmdr_rec_t);
716 19109175 : return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
717 : }
718 :
719 : /*
720 : * Change the owner of a btree format fork fo the inode passed in. Change it to
721 : * the owner of that is passed in so that we can change owners before or after
722 : * we switch forks between inodes. The operation that the caller is doing will
723 : * determine whether is needs to change owner before or after the switch.
724 : *
725 : * For demand paged transactional modification, the fork switch should be done
726 : * after reading in all the blocks, modifying them and pinning them in the
727 : * transaction. For modification when the buffers are already pinned in memory,
728 : * the fork switch can be done before changing the owner as we won't need to
729 : * validate the owner until the btree buffers are unpinned and writes can occur
730 : * again.
731 : *
732 : * For recovery based ownership change, there is no transactional context and
733 : * so a buffer list must be supplied so that we can record the buffers that we
734 : * modified for the caller to issue IO on.
735 : */
736 : int
737 13654 : xfs_bmbt_change_owner(
738 : struct xfs_trans *tp,
739 : struct xfs_inode *ip,
740 : int whichfork,
741 : xfs_ino_t new_owner,
742 : struct list_head *buffer_list)
743 : {
744 13654 : struct xfs_btree_cur *cur;
745 13654 : int error;
746 :
747 13654 : ASSERT(tp || buffer_list);
748 13654 : ASSERT(!(tp && buffer_list));
749 13654 : ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
750 :
751 13654 : cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
752 13654 : cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
753 :
754 13654 : error = xfs_btree_change_owner(cur, new_owner, buffer_list);
755 13654 : xfs_btree_del_cursor(cur, error);
756 13654 : return error;
757 : }
758 :
759 : /* Calculate the bmap btree size for some records. */
760 : unsigned long long
761 1421121 : xfs_bmbt_calc_size(
762 : struct xfs_mount *mp,
763 : unsigned long long len)
764 : {
765 1421121 : return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
766 : }
767 :
768 : int __init
769 50 : xfs_bmbt_init_cur_cache(void)
770 : {
771 50 : xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
772 50 : xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
773 : 0, 0, NULL);
774 :
775 50 : if (!xfs_bmbt_cur_cache)
776 0 : return -ENOMEM;
777 : return 0;
778 : }
779 :
780 : void
781 49 : xfs_bmbt_destroy_cur_cache(void)
782 : {
783 49 : kmem_cache_destroy(xfs_bmbt_cur_cache);
784 49 : xfs_bmbt_cur_cache = NULL;
785 49 : }
|