~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_alloc_btree.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (c) 2000-2001,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_mount.h"
 13 #include "xfs_btree.h"
 14 #include "xfs_btree_staging.h"
 15 #include "xfs_alloc_btree.h"
 16 #include "xfs_alloc.h"
 17 #include "xfs_extent_busy.h"
 18 #include "xfs_error.h"
 19 #include "xfs_health.h"
 20 #include "xfs_trace.h"
 21 #include "xfs_trans.h"
 22 #include "xfs_ag.h"
 23 
 24 static struct kmem_cache        *xfs_allocbt_cur_cache;
 25 
 26 STATIC struct xfs_btree_cur *
 27 xfs_bnobt_dup_cursor(
 28         struct xfs_btree_cur    *cur)
 29 {
 30         return xfs_bnobt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_ag.agbp,
 31                         cur->bc_ag.pag);
 32 }
 33 
 34 STATIC struct xfs_btree_cur *
 35 xfs_cntbt_dup_cursor(
 36         struct xfs_btree_cur    *cur)
 37 {
 38         return xfs_cntbt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_ag.agbp,
 39                         cur->bc_ag.pag);
 40 }
 41 
 42 
 43 STATIC void
 44 xfs_allocbt_set_root(
 45         struct xfs_btree_cur            *cur,
 46         const union xfs_btree_ptr       *ptr,
 47         int                             inc)
 48 {
 49         struct xfs_buf          *agbp = cur->bc_ag.agbp;
 50         struct xfs_agf          *agf = agbp->b_addr;
 51 
 52         ASSERT(ptr->s != 0);
 53 
 54         if (xfs_btree_is_bno(cur->bc_ops)) {
 55                 agf->agf_bno_root = ptr->s;
 56                 be32_add_cpu(&agf->agf_bno_level, inc);
 57                 cur->bc_ag.pag->pagf_bno_level += inc;
 58         } else {
 59                 agf->agf_cnt_root = ptr->s;
 60                 be32_add_cpu(&agf->agf_cnt_level, inc);
 61                 cur->bc_ag.pag->pagf_cnt_level += inc;
 62         }
 63 
 64         xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
 65 }
 66 
 67 STATIC int
 68 xfs_allocbt_alloc_block(
 69         struct xfs_btree_cur            *cur,
 70         const union xfs_btree_ptr       *start,
 71         union xfs_btree_ptr             *new,
 72         int                             *stat)
 73 {
 74         int                     error;
 75         xfs_agblock_t           bno;
 76 
 77         /* Allocate the new block from the freelist. If we can't, give up.  */
 78         error = xfs_alloc_get_freelist(cur->bc_ag.pag, cur->bc_tp,
 79                         cur->bc_ag.agbp, &bno, 1);
 80         if (error)
 81                 return error;
 82 
 83         if (bno == NULLAGBLOCK) {
 84                 *stat = 0;
 85                 return 0;
 86         }
 87 
 88         atomic64_inc(&cur->bc_mp->m_allocbt_blks);
 89         xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.pag, bno, 1, false);
 90 
 91         new->s = cpu_to_be32(bno);
 92 
 93         *stat = 1;
 94         return 0;
 95 }
 96 
 97 STATIC int
 98 xfs_allocbt_free_block(
 99         struct xfs_btree_cur    *cur,
100         struct xfs_buf          *bp)
101 {
102         struct xfs_buf          *agbp = cur->bc_ag.agbp;
103         xfs_agblock_t           bno;
104         int                     error;
105 
106         bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
107         error = xfs_alloc_put_freelist(cur->bc_ag.pag, cur->bc_tp, agbp, NULL,
108                         bno, 1);
109         if (error)
110                 return error;
111 
112         atomic64_dec(&cur->bc_mp->m_allocbt_blks);
113         xfs_extent_busy_insert(cur->bc_tp, agbp->b_pag, bno, 1,
114                               XFS_EXTENT_BUSY_SKIP_DISCARD);
115         return 0;
116 }
117 
118 STATIC int
119 xfs_allocbt_get_minrecs(
120         struct xfs_btree_cur    *cur,
121         int                     level)
122 {
123         return cur->bc_mp->m_alloc_mnr[level != 0];
124 }
125 
126 STATIC int
127 xfs_allocbt_get_maxrecs(
128         struct xfs_btree_cur    *cur,
129         int                     level)
130 {
131         return cur->bc_mp->m_alloc_mxr[level != 0];
132 }
133 
134 STATIC void
135 xfs_allocbt_init_key_from_rec(
136         union xfs_btree_key             *key,
137         const union xfs_btree_rec       *rec)
138 {
139         key->alloc.ar_startblock = rec->alloc.ar_startblock;
140         key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
141 }
142 
143 STATIC void
144 xfs_bnobt_init_high_key_from_rec(
145         union xfs_btree_key             *key,
146         const union xfs_btree_rec       *rec)
147 {
148         __u32                           x;
149 
150         x = be32_to_cpu(rec->alloc.ar_startblock);
151         x += be32_to_cpu(rec->alloc.ar_blockcount) - 1;
152         key->alloc.ar_startblock = cpu_to_be32(x);
153         key->alloc.ar_blockcount = 0;
154 }
155 
156 STATIC void
157 xfs_cntbt_init_high_key_from_rec(
158         union xfs_btree_key             *key,
159         const union xfs_btree_rec       *rec)
160 {
161         key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
162         key->alloc.ar_startblock = 0;
163 }
164 
165 STATIC void
166 xfs_allocbt_init_rec_from_cur(
167         struct xfs_btree_cur    *cur,
168         union xfs_btree_rec     *rec)
169 {
170         rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
171         rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
172 }
173 
174 STATIC void
175 xfs_allocbt_init_ptr_from_cur(
176         struct xfs_btree_cur    *cur,
177         union xfs_btree_ptr     *ptr)
178 {
179         struct xfs_agf          *agf = cur->bc_ag.agbp->b_addr;
180 
181         ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));
182 
183         if (xfs_btree_is_bno(cur->bc_ops))
184                 ptr->s = agf->agf_bno_root;
185         else
186                 ptr->s = agf->agf_cnt_root;
187 }
188 
189 STATIC int64_t
190 xfs_bnobt_key_diff(
191         struct xfs_btree_cur            *cur,
192         const union xfs_btree_key       *key)
193 {
194         struct xfs_alloc_rec_incore     *rec = &cur->bc_rec.a;
195         const struct xfs_alloc_rec      *kp = &key->alloc;
196 
197         return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
198 }
199 
200 STATIC int64_t
201 xfs_cntbt_key_diff(
202         struct xfs_btree_cur            *cur,
203         const union xfs_btree_key       *key)
204 {
205         struct xfs_alloc_rec_incore     *rec = &cur->bc_rec.a;
206         const struct xfs_alloc_rec      *kp = &key->alloc;
207         int64_t                         diff;
208 
209         diff = (int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount;
210         if (diff)
211                 return diff;
212 
213         return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
214 }
215 
216 STATIC int64_t
217 xfs_bnobt_diff_two_keys(
218         struct xfs_btree_cur            *cur,
219         const union xfs_btree_key       *k1,
220         const union xfs_btree_key       *k2,
221         const union xfs_btree_key       *mask)
222 {
223         ASSERT(!mask || mask->alloc.ar_startblock);
224 
225         return (int64_t)be32_to_cpu(k1->alloc.ar_startblock) -
226                         be32_to_cpu(k2->alloc.ar_startblock);
227 }
228 
229 STATIC int64_t
230 xfs_cntbt_diff_two_keys(
231         struct xfs_btree_cur            *cur,
232         const union xfs_btree_key       *k1,
233         const union xfs_btree_key       *k2,
234         const union xfs_btree_key       *mask)
235 {
236         int64_t                         diff;
237 
238         ASSERT(!mask || (mask->alloc.ar_blockcount &&
239                          mask->alloc.ar_startblock));
240 
241         diff =  be32_to_cpu(k1->alloc.ar_blockcount) -
242                 be32_to_cpu(k2->alloc.ar_blockcount);
243         if (diff)
244                 return diff;
245 
246         return  be32_to_cpu(k1->alloc.ar_startblock) -
247                 be32_to_cpu(k2->alloc.ar_startblock);
248 }
249 
250 static xfs_failaddr_t
251 xfs_allocbt_verify(
252         struct xfs_buf          *bp)
253 {
254         struct xfs_mount        *mp = bp->b_mount;
255         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
256         struct xfs_perag        *pag = bp->b_pag;
257         xfs_failaddr_t          fa;
258         unsigned int            level;
259 
260         if (!xfs_verify_magic(bp, block->bb_magic))
261                 return __this_address;
262 
263         if (xfs_has_crc(mp)) {
264                 fa = xfs_btree_agblock_v5hdr_verify(bp);
265                 if (fa)
266                         return fa;
267         }
268 
269         /*
270          * The perag may not be attached during grow operations or fully
271          * initialized from the AGF during log recovery. Therefore we can only
272          * check against maximum tree depth from those contexts.
273          *
274          * Otherwise check against the per-tree limit. Peek at one of the
275          * verifier magic values to determine the type of tree we're verifying
276          * against.
277          */
278         level = be16_to_cpu(block->bb_level);
279         if (pag && xfs_perag_initialised_agf(pag)) {
280                 unsigned int    maxlevel, repair_maxlevel = 0;
281 
282                 /*
283                  * Online repair could be rewriting the free space btrees, so
284                  * we'll validate against the larger of either tree while this
285                  * is going on.
286                  */
287                 if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC)) {
288                         maxlevel = pag->pagf_cnt_level;
289 #ifdef CONFIG_XFS_ONLINE_REPAIR
290                         repair_maxlevel = pag->pagf_repair_cnt_level;
291 #endif
292                 } else {
293                         maxlevel = pag->pagf_bno_level;
294 #ifdef CONFIG_XFS_ONLINE_REPAIR
295                         repair_maxlevel = pag->pagf_repair_bno_level;
296 #endif
297                 }
298 
299                 if (level >= max(maxlevel, repair_maxlevel))
300                         return __this_address;
301         } else if (level >= mp->m_alloc_maxlevels)
302                 return __this_address;
303 
304         return xfs_btree_agblock_verify(bp, mp->m_alloc_mxr[level != 0]);
305 }
306 
307 static void
308 xfs_allocbt_read_verify(
309         struct xfs_buf  *bp)
310 {
311         xfs_failaddr_t  fa;
312 
313         if (!xfs_btree_agblock_verify_crc(bp))
314                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
315         else {
316                 fa = xfs_allocbt_verify(bp);
317                 if (fa)
318                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
319         }
320 
321         if (bp->b_error)
322                 trace_xfs_btree_corrupt(bp, _RET_IP_);
323 }
324 
325 static void
326 xfs_allocbt_write_verify(
327         struct xfs_buf  *bp)
328 {
329         xfs_failaddr_t  fa;
330 
331         fa = xfs_allocbt_verify(bp);
332         if (fa) {
333                 trace_xfs_btree_corrupt(bp, _RET_IP_);
334                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
335                 return;
336         }
337         xfs_btree_agblock_calc_crc(bp);
338 
339 }
340 
341 const struct xfs_buf_ops xfs_bnobt_buf_ops = {
342         .name = "xfs_bnobt",
343         .magic = { cpu_to_be32(XFS_ABTB_MAGIC),
344                    cpu_to_be32(XFS_ABTB_CRC_MAGIC) },
345         .verify_read = xfs_allocbt_read_verify,
346         .verify_write = xfs_allocbt_write_verify,
347         .verify_struct = xfs_allocbt_verify,
348 };
349 
350 const struct xfs_buf_ops xfs_cntbt_buf_ops = {
351         .name = "xfs_cntbt",
352         .magic = { cpu_to_be32(XFS_ABTC_MAGIC),
353                    cpu_to_be32(XFS_ABTC_CRC_MAGIC) },
354         .verify_read = xfs_allocbt_read_verify,
355         .verify_write = xfs_allocbt_write_verify,
356         .verify_struct = xfs_allocbt_verify,
357 };
358 
359 STATIC int
360 xfs_bnobt_keys_inorder(
361         struct xfs_btree_cur            *cur,
362         const union xfs_btree_key       *k1,
363         const union xfs_btree_key       *k2)
364 {
365         return be32_to_cpu(k1->alloc.ar_startblock) <
366                be32_to_cpu(k2->alloc.ar_startblock);
367 }
368 
369 STATIC int
370 xfs_bnobt_recs_inorder(
371         struct xfs_btree_cur            *cur,
372         const union xfs_btree_rec       *r1,
373         const union xfs_btree_rec       *r2)
374 {
375         return be32_to_cpu(r1->alloc.ar_startblock) +
376                 be32_to_cpu(r1->alloc.ar_blockcount) <=
377                 be32_to_cpu(r2->alloc.ar_startblock);
378 }
379 
380 STATIC int
381 xfs_cntbt_keys_inorder(
382         struct xfs_btree_cur            *cur,
383         const union xfs_btree_key       *k1,
384         const union xfs_btree_key       *k2)
385 {
386         return be32_to_cpu(k1->alloc.ar_blockcount) <
387                 be32_to_cpu(k2->alloc.ar_blockcount) ||
388                 (k1->alloc.ar_blockcount == k2->alloc.ar_blockcount &&
389                  be32_to_cpu(k1->alloc.ar_startblock) <
390                  be32_to_cpu(k2->alloc.ar_startblock));
391 }
392 
393 STATIC int
394 xfs_cntbt_recs_inorder(
395         struct xfs_btree_cur            *cur,
396         const union xfs_btree_rec       *r1,
397         const union xfs_btree_rec       *r2)
398 {
399         return be32_to_cpu(r1->alloc.ar_blockcount) <
400                 be32_to_cpu(r2->alloc.ar_blockcount) ||
401                 (r1->alloc.ar_blockcount == r2->alloc.ar_blockcount &&
402                  be32_to_cpu(r1->alloc.ar_startblock) <
403                  be32_to_cpu(r2->alloc.ar_startblock));
404 }
405 
406 STATIC enum xbtree_key_contig
407 xfs_allocbt_keys_contiguous(
408         struct xfs_btree_cur            *cur,
409         const union xfs_btree_key       *key1,
410         const union xfs_btree_key       *key2,
411         const union xfs_btree_key       *mask)
412 {
413         ASSERT(!mask || mask->alloc.ar_startblock);
414 
415         return xbtree_key_contig(be32_to_cpu(key1->alloc.ar_startblock),
416                                  be32_to_cpu(key2->alloc.ar_startblock));
417 }
418 
419 const struct xfs_btree_ops xfs_bnobt_ops = {
420         .name                   = "bno",
421         .type                   = XFS_BTREE_TYPE_AG,
422 
423         .rec_len                = sizeof(xfs_alloc_rec_t),
424         .key_len                = sizeof(xfs_alloc_key_t),
425         .ptr_len                = XFS_BTREE_SHORT_PTR_LEN,
426 
427         .lru_refs               = XFS_ALLOC_BTREE_REF,
428         .statoff                = XFS_STATS_CALC_INDEX(xs_abtb_2),
429         .sick_mask              = XFS_SICK_AG_BNOBT,
430 
431         .dup_cursor             = xfs_bnobt_dup_cursor,
432         .set_root               = xfs_allocbt_set_root,
433         .alloc_block            = xfs_allocbt_alloc_block,
434         .free_block             = xfs_allocbt_free_block,
435         .get_minrecs            = xfs_allocbt_get_minrecs,
436         .get_maxrecs            = xfs_allocbt_get_maxrecs,
437         .init_key_from_rec      = xfs_allocbt_init_key_from_rec,
438         .init_high_key_from_rec = xfs_bnobt_init_high_key_from_rec,
439         .init_rec_from_cur      = xfs_allocbt_init_rec_from_cur,
440         .init_ptr_from_cur      = xfs_allocbt_init_ptr_from_cur,
441         .key_diff               = xfs_bnobt_key_diff,
442         .buf_ops                = &xfs_bnobt_buf_ops,
443         .diff_two_keys          = xfs_bnobt_diff_two_keys,
444         .keys_inorder           = xfs_bnobt_keys_inorder,
445         .recs_inorder           = xfs_bnobt_recs_inorder,
446         .keys_contiguous        = xfs_allocbt_keys_contiguous,
447 };
448 
449 const struct xfs_btree_ops xfs_cntbt_ops = {
450         .name                   = "cnt",
451         .type                   = XFS_BTREE_TYPE_AG,
452 
453         .rec_len                = sizeof(xfs_alloc_rec_t),
454         .key_len                = sizeof(xfs_alloc_key_t),
455         .ptr_len                = XFS_BTREE_SHORT_PTR_LEN,
456 
457         .lru_refs               = XFS_ALLOC_BTREE_REF,
458         .statoff                = XFS_STATS_CALC_INDEX(xs_abtc_2),
459         .sick_mask              = XFS_SICK_AG_CNTBT,
460 
461         .dup_cursor             = xfs_cntbt_dup_cursor,
462         .set_root               = xfs_allocbt_set_root,
463         .alloc_block            = xfs_allocbt_alloc_block,
464         .free_block             = xfs_allocbt_free_block,
465         .get_minrecs            = xfs_allocbt_get_minrecs,
466         .get_maxrecs            = xfs_allocbt_get_maxrecs,
467         .init_key_from_rec      = xfs_allocbt_init_key_from_rec,
468         .init_high_key_from_rec = xfs_cntbt_init_high_key_from_rec,
469         .init_rec_from_cur      = xfs_allocbt_init_rec_from_cur,
470         .init_ptr_from_cur      = xfs_allocbt_init_ptr_from_cur,
471         .key_diff               = xfs_cntbt_key_diff,
472         .buf_ops                = &xfs_cntbt_buf_ops,
473         .diff_two_keys          = xfs_cntbt_diff_two_keys,
474         .keys_inorder           = xfs_cntbt_keys_inorder,
475         .recs_inorder           = xfs_cntbt_recs_inorder,
476         .keys_contiguous        = NULL, /* not needed right now */
477 };
478 
479 /*
480  * Allocate a new bnobt cursor.
481  *
482  * For staging cursors tp and agbp are NULL.
483  */
484 struct xfs_btree_cur *
485 xfs_bnobt_init_cursor(
486         struct xfs_mount        *mp,
487         struct xfs_trans        *tp,
488         struct xfs_buf          *agbp,
489         struct xfs_perag        *pag)
490 {
491         struct xfs_btree_cur    *cur;
492 
493         cur = xfs_btree_alloc_cursor(mp, tp, &xfs_bnobt_ops,
494                         mp->m_alloc_maxlevels, xfs_allocbt_cur_cache);
495         cur->bc_ag.pag = xfs_perag_hold(pag);
496         cur->bc_ag.agbp = agbp;
497         if (agbp) {
498                 struct xfs_agf          *agf = agbp->b_addr;
499 
500                 cur->bc_nlevels = be32_to_cpu(agf->agf_bno_level);
501         }
502         return cur;
503 }
504 
505 /*
506  * Allocate a new cntbt cursor.
507  *
508  * For staging cursors tp and agbp are NULL.
509  */
510 struct xfs_btree_cur *
511 xfs_cntbt_init_cursor(
512         struct xfs_mount        *mp,
513         struct xfs_trans        *tp,
514         struct xfs_buf          *agbp,
515         struct xfs_perag        *pag)
516 {
517         struct xfs_btree_cur    *cur;
518 
519         cur = xfs_btree_alloc_cursor(mp, tp, &xfs_cntbt_ops,
520                         mp->m_alloc_maxlevels, xfs_allocbt_cur_cache);
521         cur->bc_ag.pag = xfs_perag_hold(pag);
522         cur->bc_ag.agbp = agbp;
523         if (agbp) {
524                 struct xfs_agf          *agf = agbp->b_addr;
525 
526                 cur->bc_nlevels = be32_to_cpu(agf->agf_cnt_level);
527         }
528         return cur;
529 }
530 
531 /*
532  * Install a new free space btree root.  Caller is responsible for invalidating
533  * and freeing the old btree blocks.
534  */
535 void
536 xfs_allocbt_commit_staged_btree(
537         struct xfs_btree_cur    *cur,
538         struct xfs_trans        *tp,
539         struct xfs_buf          *agbp)
540 {
541         struct xfs_agf          *agf = agbp->b_addr;
542         struct xbtree_afakeroot *afake = cur->bc_ag.afake;
543 
544         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
545 
546         if (xfs_btree_is_bno(cur->bc_ops)) {
547                 agf->agf_bno_root = cpu_to_be32(afake->af_root);
548                 agf->agf_bno_level = cpu_to_be32(afake->af_levels);
549         } else {
550                 agf->agf_cnt_root = cpu_to_be32(afake->af_root);
551                 agf->agf_cnt_level = cpu_to_be32(afake->af_levels);
552         }
553         xfs_alloc_log_agf(tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
554 
555         xfs_btree_commit_afakeroot(cur, tp, agbp);
556 }
557 
558 /* Calculate number of records in an alloc btree block. */
559 static inline unsigned int
560 xfs_allocbt_block_maxrecs(
561         unsigned int            blocklen,
562         bool                    leaf)
563 {
564         if (leaf)
565                 return blocklen / sizeof(xfs_alloc_rec_t);
566         return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t));
567 }
568 
569 /*
570  * Calculate number of records in an alloc btree block.
571  */
572 int
573 xfs_allocbt_maxrecs(
574         struct xfs_mount        *mp,
575         int                     blocklen,
576         int                     leaf)
577 {
578         blocklen -= XFS_ALLOC_BLOCK_LEN(mp);
579         return xfs_allocbt_block_maxrecs(blocklen, leaf);
580 }
581 
582 /* Free space btrees are at their largest when every other block is free. */
583 #define XFS_MAX_FREESP_RECORDS  ((XFS_MAX_AG_BLOCKS + 1) / 2)
584 
585 /* Compute the max possible height for free space btrees. */
586 unsigned int
587 xfs_allocbt_maxlevels_ondisk(void)
588 {
589         unsigned int            minrecs[2];
590         unsigned int            blocklen;
591 
592         blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
593                        XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
594 
595         minrecs[0] = xfs_allocbt_block_maxrecs(blocklen, true) / 2;
596         minrecs[1] = xfs_allocbt_block_maxrecs(blocklen, false) / 2;
597 
598         return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_FREESP_RECORDS);
599 }
600 
601 /* Calculate the freespace btree size for some records. */
602 xfs_extlen_t
603 xfs_allocbt_calc_size(
604         struct xfs_mount        *mp,
605         unsigned long long      len)
606 {
607         return xfs_btree_calc_size(mp->m_alloc_mnr, len);
608 }
609 
610 int __init
611 xfs_allocbt_init_cur_cache(void)
612 {
613         xfs_allocbt_cur_cache = kmem_cache_create("xfs_bnobt_cur",
614                         xfs_btree_cur_sizeof(xfs_allocbt_maxlevels_ondisk()),
615                         0, 0, NULL);
616 
617         if (!xfs_allocbt_cur_cache)
618                 return -ENOMEM;
619         return 0;
620 }
621 
622 void
623 xfs_allocbt_destroy_cur_cache(void)
624 {
625         kmem_cache_destroy(xfs_allocbt_cur_cache);
626         xfs_allocbt_cur_cache = NULL;
627 }
628 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php