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_bmap_btree.h"
19 : #include "xfs_bmap.h"
20 : #include "xfs_error.h"
21 : #include "xfs_quota.h"
22 : #include "xfs_trace.h"
23 : #include "xfs_rmap.h"
24 : #include "xfs_ag.h"
25 :
26 : static struct kmem_cache *xfs_bmbt_cur_cache;
27 :
28 : /*
29 : * Convert on-disk form of btree root to in-memory form.
30 : */
31 : void
32 3718174 : xfs_bmdr_to_bmbt(
33 : struct xfs_inode *ip,
34 : xfs_bmdr_block_t *dblock,
35 : int dblocklen,
36 : struct xfs_btree_block *rblock,
37 : int rblocklen)
38 : {
39 3718174 : struct xfs_mount *mp = ip->i_mount;
40 3718174 : int dmxr;
41 3718174 : xfs_bmbt_key_t *fkp;
42 3718174 : __be64 *fpp;
43 3718174 : xfs_bmbt_key_t *tkp;
44 3718174 : __be64 *tpp;
45 :
46 3718174 : xfs_btree_init_block_int(mp, rblock, XFS_BUF_DADDR_NULL,
47 : XFS_BTNUM_BMAP, 0, 0, ip->i_ino,
48 : XFS_BTREE_LONG_PTRS);
49 3718173 : rblock->bb_level = dblock->bb_level;
50 3718173 : ASSERT(be16_to_cpu(rblock->bb_level) > 0);
51 3718173 : rblock->bb_numrecs = dblock->bb_numrecs;
52 3718173 : dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
53 3718173 : fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
54 7436346 : tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
55 3718173 : fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
56 3718173 : tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
57 3718173 : dmxr = be16_to_cpu(dblock->bb_numrecs);
58 7436346 : memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
59 7436346 : memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
60 3718173 : }
61 :
62 : void
63 1395962537 : xfs_bmbt_disk_get_all(
64 : const struct xfs_bmbt_rec *rec,
65 : struct xfs_bmbt_irec *irec)
66 : {
67 2791925074 : uint64_t l0 = get_unaligned_be64(&rec->l0);
68 1395962537 : uint64_t l1 = get_unaligned_be64(&rec->l1);
69 :
70 1395962537 : irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
71 1395962537 : irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
72 1395962537 : irec->br_blockcount = l1 & xfs_mask64lo(21);
73 1395962537 : if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
74 129713177 : irec->br_state = XFS_EXT_UNWRITTEN;
75 : else
76 1266249360 : irec->br_state = XFS_EXT_NORM;
77 1395962537 : }
78 :
79 : /*
80 : * Extract the blockcount field from an on disk bmap extent record.
81 : */
82 : xfs_filblks_t
83 >10443*10^7 : xfs_bmbt_disk_get_blockcount(
84 : const struct xfs_bmbt_rec *r)
85 : {
86 >10443*10^7 : return (xfs_filblks_t)(be64_to_cpu(r->l1) & xfs_mask64lo(21));
87 : }
88 :
89 : /*
90 : * Extract the startoff field from a disk format bmap extent record.
91 : */
92 : xfs_fileoff_t
93 >20998*10^7 : xfs_bmbt_disk_get_startoff(
94 : const struct xfs_bmbt_rec *r)
95 : {
96 >20998*10^7 : return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
97 >20998*10^7 : xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
98 : }
99 :
100 : /*
101 : * Set all the fields in a bmap extent record from the uncompressed form.
102 : */
103 : void
104 1081322626 : xfs_bmbt_disk_set_all(
105 : struct xfs_bmbt_rec *r,
106 : struct xfs_bmbt_irec *s)
107 : {
108 1081322626 : int extent_flag = (s->br_state != XFS_EXT_NORM);
109 :
110 1081322626 : ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
111 1081322626 : ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
112 1081322626 : ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
113 1081322626 : ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
114 :
115 1081322626 : put_unaligned_be64(
116 1081322626 : ((xfs_bmbt_rec_base_t)extent_flag << 63) |
117 1081322626 : ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
118 1081322626 : ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
119 1081348225 : put_unaligned_be64(
120 1081348225 : ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
121 1081348225 : ((xfs_bmbt_rec_base_t)s->br_blockcount &
122 1081348225 : (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
123 1081349592 : }
124 :
125 : /*
126 : * Convert in-memory form of btree root to on-disk form.
127 : */
128 : void
129 450016 : xfs_bmbt_to_bmdr(
130 : struct xfs_mount *mp,
131 : struct xfs_btree_block *rblock,
132 : int rblocklen,
133 : xfs_bmdr_block_t *dblock,
134 : int dblocklen)
135 : {
136 450016 : int dmxr;
137 450016 : xfs_bmbt_key_t *fkp;
138 450016 : __be64 *fpp;
139 450016 : xfs_bmbt_key_t *tkp;
140 450016 : __be64 *tpp;
141 :
142 450016 : if (xfs_has_crc(mp)) {
143 450016 : ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
144 450016 : ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
145 : &mp->m_sb.sb_meta_uuid));
146 450016 : ASSERT(rblock->bb_u.l.bb_blkno ==
147 : cpu_to_be64(XFS_BUF_DADDR_NULL));
148 : } else
149 0 : ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC));
150 450016 : ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
151 450016 : ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
152 450016 : ASSERT(rblock->bb_level != 0);
153 450016 : dblock->bb_level = rblock->bb_level;
154 450016 : dblock->bb_numrecs = rblock->bb_numrecs;
155 450016 : dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
156 900032 : fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
157 450016 : tkp = XFS_BMDR_KEY_ADDR(dblock, 1);
158 450016 : fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
159 450016 : tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
160 450016 : dmxr = be16_to_cpu(dblock->bb_numrecs);
161 900032 : memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
162 900032 : memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
163 450016 : }
164 :
165 : STATIC struct xfs_btree_cur *
166 41202495 : xfs_bmbt_dup_cursor(
167 : struct xfs_btree_cur *cur)
168 : {
169 41202495 : struct xfs_btree_cur *new;
170 :
171 41202495 : new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
172 41202495 : cur->bc_ino.ip, cur->bc_ino.whichfork);
173 :
174 : /*
175 : * Copy the firstblock, dfops, and flags values,
176 : * since init cursor doesn't get them.
177 : */
178 41202472 : new->bc_ino.flags = cur->bc_ino.flags;
179 :
180 41202472 : return new;
181 : }
182 :
183 : STATIC void
184 204865 : xfs_bmbt_update_cursor(
185 : struct xfs_btree_cur *src,
186 : struct xfs_btree_cur *dst)
187 : {
188 204865 : ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
189 : (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
190 :
191 204865 : dst->bc_ino.allocated += src->bc_ino.allocated;
192 204865 : dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
193 :
194 204865 : src->bc_ino.allocated = 0;
195 204865 : }
196 :
197 : STATIC int
198 207069 : xfs_bmbt_alloc_block(
199 : struct xfs_btree_cur *cur,
200 : const union xfs_btree_ptr *start,
201 : union xfs_btree_ptr *new,
202 : int *stat)
203 : {
204 207069 : struct xfs_alloc_arg args;
205 207069 : int error;
206 :
207 207069 : memset(&args, 0, sizeof(args));
208 207069 : args.tp = cur->bc_tp;
209 207069 : args.mp = cur->bc_mp;
210 207069 : xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
211 207069 : cur->bc_ino.whichfork);
212 207069 : args.minlen = args.maxlen = args.prod = 1;
213 207069 : args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
214 207069 : if (!args.wasdel && args.tp->t_blk_res == 0)
215 : return -ENOSPC;
216 :
217 : /*
218 : * If we are coming here from something like unwritten extent
219 : * conversion, there has been no data extent allocation already done, so
220 : * we have to ensure that we attempt to locate the entire set of bmbt
221 : * allocations in the same AG, as xfs_bmapi_write() would have reserved.
222 : */
223 207069 : if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
224 194519 : args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
225 : cur->bc_ino.whichfork);
226 :
227 207069 : error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
228 207069 : if (error)
229 : return error;
230 :
231 207065 : if (args.fsbno == NULLFSBLOCK && args.minleft) {
232 : /*
233 : * Could not find an AG with enough free space to satisfy
234 : * a full btree split. Try again and if
235 : * successful activate the lowspace algorithm.
236 : */
237 0 : args.minleft = 0;
238 0 : error = xfs_alloc_vextent_start_ag(&args, 0);
239 0 : if (error)
240 : return error;
241 0 : cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE;
242 : }
243 207065 : if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
244 0 : *stat = 0;
245 0 : return 0;
246 : }
247 :
248 207065 : ASSERT(args.len == 1);
249 207065 : cur->bc_ino.allocated++;
250 207065 : cur->bc_ino.ip->i_nblocks++;
251 207065 : xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
252 207065 : xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
253 : XFS_TRANS_DQ_BCOUNT, 1L);
254 :
255 207065 : new->l = cpu_to_be64(args.fsbno);
256 :
257 207065 : *stat = 1;
258 207065 : return 0;
259 : }
260 :
261 : STATIC int
262 140046 : xfs_bmbt_free_block(
263 : struct xfs_btree_cur *cur,
264 : struct xfs_buf *bp)
265 : {
266 140046 : struct xfs_mount *mp = cur->bc_mp;
267 140046 : struct xfs_inode *ip = cur->bc_ino.ip;
268 140046 : struct xfs_trans *tp = cur->bc_tp;
269 140046 : xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
270 140046 : struct xfs_owner_info oinfo;
271 140046 : int error;
272 :
273 140046 : xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
274 140046 : error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
275 : XFS_AG_RESV_NONE);
276 140046 : if (error)
277 : return error;
278 :
279 140046 : ip->i_nblocks--;
280 140046 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
281 140046 : xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
282 140046 : return 0;
283 : }
284 :
285 : STATIC int
286 76928715 : xfs_bmbt_get_minrecs(
287 : struct xfs_btree_cur *cur,
288 : int level)
289 : {
290 76928715 : if (level == cur->bc_nlevels - 1) {
291 2425781 : struct xfs_ifork *ifp;
292 :
293 2425781 : ifp = xfs_ifork_ptr(cur->bc_ino.ip,
294 2425781 : cur->bc_ino.whichfork);
295 :
296 2425781 : return xfs_bmbt_maxrecs(cur->bc_mp,
297 4851562 : ifp->if_broot_bytes, level == 0) / 2;
298 : }
299 :
300 74502934 : return cur->bc_mp->m_bmap_dmnr[level != 0];
301 : }
302 :
303 : int
304 775585836 : xfs_bmbt_get_maxrecs(
305 : struct xfs_btree_cur *cur,
306 : int level)
307 : {
308 775585836 : if (level == cur->bc_nlevels - 1) {
309 159518445 : struct xfs_ifork *ifp;
310 :
311 159518445 : ifp = xfs_ifork_ptr(cur->bc_ino.ip,
312 159518445 : cur->bc_ino.whichfork);
313 :
314 159518632 : return xfs_bmbt_maxrecs(cur->bc_mp,
315 159518632 : ifp->if_broot_bytes, level == 0);
316 : }
317 :
318 616067391 : return cur->bc_mp->m_bmap_dmxr[level != 0];
319 :
320 : }
321 :
322 : /*
323 : * Get the maximum records we could store in the on-disk format.
324 : *
325 : * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but
326 : * for the root node this checks the available space in the dinode fork
327 : * so that we can resize the in-memory buffer to match it. After a
328 : * resize to the maximum size this function returns the same value
329 : * as xfs_bmbt_get_maxrecs for the root node, too.
330 : */
331 : STATIC int
332 2538604 : xfs_bmbt_get_dmaxrecs(
333 : struct xfs_btree_cur *cur,
334 : int level)
335 : {
336 2538604 : if (level != cur->bc_nlevels - 1)
337 0 : return cur->bc_mp->m_bmap_dmxr[level != 0];
338 2538604 : return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
339 : }
340 :
341 : STATIC void
342 1185903425 : xfs_bmbt_init_key_from_rec(
343 : union xfs_btree_key *key,
344 : const union xfs_btree_rec *rec)
345 : {
346 1185903425 : key->bmbt.br_startoff =
347 1185903425 : cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
348 1185903425 : }
349 :
350 : STATIC void
351 0 : xfs_bmbt_init_high_key_from_rec(
352 : union xfs_btree_key *key,
353 : const union xfs_btree_rec *rec)
354 : {
355 0 : key->bmbt.br_startoff = cpu_to_be64(
356 : xfs_bmbt_disk_get_startoff(&rec->bmbt) +
357 : xfs_bmbt_disk_get_blockcount(&rec->bmbt) - 1);
358 0 : }
359 :
360 : STATIC void
361 58578753 : xfs_bmbt_init_rec_from_cur(
362 : struct xfs_btree_cur *cur,
363 : union xfs_btree_rec *rec)
364 : {
365 58578753 : xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
366 58578755 : }
367 :
368 : STATIC void
369 122915258 : xfs_bmbt_init_ptr_from_cur(
370 : struct xfs_btree_cur *cur,
371 : union xfs_btree_ptr *ptr)
372 : {
373 122915258 : ptr->l = 0;
374 122915258 : }
375 :
376 : STATIC int64_t
377 1592995947 : xfs_bmbt_key_diff(
378 : struct xfs_btree_cur *cur,
379 : const union xfs_btree_key *key)
380 : {
381 1592995947 : return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
382 1592995947 : cur->bc_rec.b.br_startoff;
383 : }
384 :
385 : STATIC int64_t
386 197628933 : xfs_bmbt_diff_two_keys(
387 : struct xfs_btree_cur *cur,
388 : const union xfs_btree_key *k1,
389 : const union xfs_btree_key *k2,
390 : const union xfs_btree_key *mask)
391 : {
392 197628933 : uint64_t a = be64_to_cpu(k1->bmbt.br_startoff);
393 197628933 : uint64_t b = be64_to_cpu(k2->bmbt.br_startoff);
394 :
395 197628933 : ASSERT(!mask || mask->bmbt.br_startoff);
396 :
397 : /*
398 : * Note: This routine previously casted a and b to int64 and subtracted
399 : * them to generate a result. This lead to problems if b was the
400 : * "maximum" key value (all ones) being signed incorrectly, hence this
401 : * somewhat less efficient version.
402 : */
403 197628933 : if (a > b)
404 : return 1;
405 8869414 : if (b > a)
406 0 : return -1;
407 : return 0;
408 : }
409 :
410 : static xfs_failaddr_t
411 10944719 : xfs_bmbt_verify(
412 : struct xfs_buf *bp)
413 : {
414 10944719 : struct xfs_mount *mp = bp->b_mount;
415 10944719 : struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
416 10944719 : xfs_failaddr_t fa;
417 10944719 : unsigned int level;
418 :
419 10944719 : if (!xfs_verify_magic(bp, block->bb_magic))
420 0 : return __this_address;
421 :
422 10944716 : if (xfs_has_crc(mp)) {
423 : /*
424 : * XXX: need a better way of verifying the owner here. Right now
425 : * just make sure there has been one set.
426 : */
427 10944721 : fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
428 10944723 : if (fa)
429 : return fa;
430 : }
431 :
432 : /*
433 : * numrecs and level verification.
434 : *
435 : * We don't know what fork we belong to, so just verify that the level
436 : * is less than the maximum of the two. Later checks will be more
437 : * precise.
438 : */
439 10944718 : level = be16_to_cpu(block->bb_level);
440 10944718 : if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
441 7 : return __this_address;
442 :
443 10944715 : return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
444 : }
445 :
446 : static void
447 4497353 : xfs_bmbt_read_verify(
448 : struct xfs_buf *bp)
449 : {
450 4497353 : xfs_failaddr_t fa;
451 :
452 4497353 : if (!xfs_btree_lblock_verify_crc(bp))
453 4 : xfs_verifier_error(bp, -EFSBADCRC, __this_address);
454 : else {
455 4497349 : fa = xfs_bmbt_verify(bp);
456 4497349 : if (fa)
457 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
458 : }
459 :
460 4497353 : if (bp->b_error)
461 4 : trace_xfs_btree_corrupt(bp, _RET_IP_);
462 4497353 : }
463 :
464 : static void
465 2577952 : xfs_bmbt_write_verify(
466 : struct xfs_buf *bp)
467 : {
468 2577952 : xfs_failaddr_t fa;
469 :
470 2577952 : fa = xfs_bmbt_verify(bp);
471 2577952 : if (fa) {
472 0 : trace_xfs_btree_corrupt(bp, _RET_IP_);
473 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
474 0 : return;
475 : }
476 2577952 : xfs_btree_lblock_calc_crc(bp);
477 : }
478 :
479 : const struct xfs_buf_ops xfs_bmbt_buf_ops = {
480 : .name = "xfs_bmbt",
481 : .magic = { cpu_to_be32(XFS_BMAP_MAGIC),
482 : cpu_to_be32(XFS_BMAP_CRC_MAGIC) },
483 : .verify_read = xfs_bmbt_read_verify,
484 : .verify_write = xfs_bmbt_write_verify,
485 : .verify_struct = xfs_bmbt_verify,
486 : };
487 :
488 :
489 : STATIC int
490 561317 : xfs_bmbt_keys_inorder(
491 : struct xfs_btree_cur *cur,
492 : const union xfs_btree_key *k1,
493 : const union xfs_btree_key *k2)
494 : {
495 561317 : return be64_to_cpu(k1->bmbt.br_startoff) <
496 561317 : be64_to_cpu(k2->bmbt.br_startoff);
497 : }
498 :
499 : STATIC int
500 232682204 : xfs_bmbt_recs_inorder(
501 : struct xfs_btree_cur *cur,
502 : const union xfs_btree_rec *r1,
503 : const union xfs_btree_rec *r2)
504 : {
505 232682204 : return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
506 232682204 : xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
507 232682204 : xfs_bmbt_disk_get_startoff(&r2->bmbt);
508 : }
509 :
510 : STATIC enum xbtree_key_contig
511 0 : xfs_bmbt_keys_contiguous(
512 : struct xfs_btree_cur *cur,
513 : const union xfs_btree_key *key1,
514 : const union xfs_btree_key *key2,
515 : const union xfs_btree_key *mask)
516 : {
517 0 : ASSERT(!mask || mask->bmbt.br_startoff);
518 :
519 0 : return xbtree_key_contig(be64_to_cpu(key1->bmbt.br_startoff),
520 0 : be64_to_cpu(key2->bmbt.br_startoff));
521 : }
522 :
523 : static const struct xfs_btree_ops xfs_bmbt_ops = {
524 : .rec_len = sizeof(xfs_bmbt_rec_t),
525 : .key_len = sizeof(xfs_bmbt_key_t),
526 :
527 : .dup_cursor = xfs_bmbt_dup_cursor,
528 : .update_cursor = xfs_bmbt_update_cursor,
529 : .alloc_block = xfs_bmbt_alloc_block,
530 : .free_block = xfs_bmbt_free_block,
531 : .get_maxrecs = xfs_bmbt_get_maxrecs,
532 : .get_minrecs = xfs_bmbt_get_minrecs,
533 : .get_dmaxrecs = xfs_bmbt_get_dmaxrecs,
534 : .init_key_from_rec = xfs_bmbt_init_key_from_rec,
535 : .init_high_key_from_rec = xfs_bmbt_init_high_key_from_rec,
536 : .init_rec_from_cur = xfs_bmbt_init_rec_from_cur,
537 : .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur,
538 : .key_diff = xfs_bmbt_key_diff,
539 : .diff_two_keys = xfs_bmbt_diff_two_keys,
540 : .buf_ops = &xfs_bmbt_buf_ops,
541 : .keys_inorder = xfs_bmbt_keys_inorder,
542 : .recs_inorder = xfs_bmbt_recs_inorder,
543 : .keys_contiguous = xfs_bmbt_keys_contiguous,
544 : };
545 :
546 : /*
547 : * Allocate a new bmap btree cursor.
548 : */
549 : struct xfs_btree_cur * /* new bmap btree cursor */
550 146551989 : xfs_bmbt_init_cursor(
551 : struct xfs_mount *mp, /* file system mount point */
552 : struct xfs_trans *tp, /* transaction pointer */
553 : struct xfs_inode *ip, /* inode owning the btree */
554 : int whichfork) /* data or attr fork */
555 : {
556 146551989 : struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
557 146552311 : struct xfs_btree_cur *cur;
558 146552311 : ASSERT(whichfork != XFS_COW_FORK);
559 :
560 293104165 : cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP,
561 146552311 : mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
562 146552612 : cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
563 146552612 : cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
564 :
565 146552612 : cur->bc_ops = &xfs_bmbt_ops;
566 146552612 : cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
567 146552612 : if (xfs_has_crc(mp))
568 146552734 : cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
569 :
570 146552612 : cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
571 146552612 : cur->bc_ino.ip = ip;
572 146552612 : cur->bc_ino.allocated = 0;
573 146552612 : cur->bc_ino.flags = 0;
574 146552612 : cur->bc_ino.whichfork = whichfork;
575 :
576 146552612 : return cur;
577 : }
578 :
579 : /* Calculate number of records in a block mapping btree block. */
580 : static inline unsigned int
581 : xfs_bmbt_block_maxrecs(
582 : unsigned int blocklen,
583 : bool leaf)
584 : {
585 1106651807 : if (leaf)
586 22501 : return blocklen / sizeof(xfs_bmbt_rec_t);
587 1102461117 : return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t));
588 : }
589 :
590 : /*
591 : * Calculate number of records in a bmap btree block.
592 : */
593 : int
594 940539205 : xfs_bmbt_maxrecs(
595 : struct xfs_mount *mp,
596 : int blocklen,
597 : int leaf)
598 : {
599 1102483618 : blocklen -= XFS_BMBT_BLOCK_LEN(mp);
600 1268596220 : return xfs_bmbt_block_maxrecs(blocklen, leaf);
601 : }
602 :
603 : /*
604 : * Calculate the maximum possible height of the btree that the on-disk format
605 : * supports. This is used for sizing structures large enough to support every
606 : * possible configuration of a filesystem that might get mounted.
607 : */
608 : unsigned int
609 45002 : xfs_bmbt_maxlevels_ondisk(void)
610 : {
611 45002 : unsigned int minrecs[2];
612 45002 : unsigned int blocklen;
613 :
614 45002 : blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
615 : XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
616 :
617 45002 : minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
618 45002 : minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
619 :
620 : /* One extra level for the inode root. */
621 45002 : return xfs_btree_compute_maxlevels(minrecs,
622 45002 : XFS_MAX_EXTCNT_DATA_FORK_LARGE) + 1;
623 : }
624 :
625 : /*
626 : * Calculate number of records in a bmap btree inode root.
627 : */
628 : int
629 44990 : xfs_bmdr_maxrecs(
630 : int blocklen,
631 : int leaf)
632 : {
633 6751783 : blocklen -= sizeof(xfs_bmdr_block_t);
634 :
635 2583594 : if (leaf)
636 0 : return blocklen / sizeof(xfs_bmdr_rec_t);
637 6751783 : return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
638 : }
639 :
640 : /*
641 : * Change the owner of a btree format fork fo the inode passed in. Change it to
642 : * the owner of that is passed in so that we can change owners before or after
643 : * we switch forks between inodes. The operation that the caller is doing will
644 : * determine whether is needs to change owner before or after the switch.
645 : *
646 : * For demand paged transactional modification, the fork switch should be done
647 : * after reading in all the blocks, modifying them and pinning them in the
648 : * transaction. For modification when the buffers are already pinned in memory,
649 : * the fork switch can be done before changing the owner as we won't need to
650 : * validate the owner until the btree buffers are unpinned and writes can occur
651 : * again.
652 : *
653 : * For recovery based ownership change, there is no transactional context and
654 : * so a buffer list must be supplied so that we can record the buffers that we
655 : * modified for the caller to issue IO on.
656 : */
657 : int
658 0 : xfs_bmbt_change_owner(
659 : struct xfs_trans *tp,
660 : struct xfs_inode *ip,
661 : int whichfork,
662 : xfs_ino_t new_owner,
663 : struct list_head *buffer_list)
664 : {
665 0 : struct xfs_btree_cur *cur;
666 0 : int error;
667 :
668 0 : ASSERT(tp || buffer_list);
669 0 : ASSERT(!(tp && buffer_list));
670 0 : ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
671 :
672 0 : cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
673 0 : cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
674 :
675 0 : error = xfs_btree_change_owner(cur, new_owner, buffer_list);
676 0 : xfs_btree_del_cursor(cur, error);
677 0 : return error;
678 : }
679 :
680 : /* Calculate the bmap btree size for some records. */
681 : unsigned long long
682 0 : xfs_bmbt_calc_size(
683 : struct xfs_mount *mp,
684 : unsigned long long len)
685 : {
686 0 : return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
687 : }
688 :
689 : int __init
690 12 : xfs_bmbt_init_cur_cache(void)
691 : {
692 12 : xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
693 12 : xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
694 : 0, 0, NULL);
695 :
696 12 : if (!xfs_bmbt_cur_cache)
697 0 : return -ENOMEM;
698 : return 0;
699 : }
700 :
701 : void
702 12 : xfs_bmbt_destroy_cur_cache(void)
703 : {
704 12 : kmem_cache_destroy(xfs_bmbt_cur_cache);
705 12 : xfs_bmbt_cur_cache = NULL;
706 12 : }
|