📄 xfs_alloc_btree.c
字号:
#endif ptr = cur->bc_ptrs[level]; kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur); *kp = *keyp; xfs_alloc_log_keys(cur, bp, ptr, ptr); } return 0;}/* * Externally visible routines. *//* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int /* error */xfs_alloc_decrement( xfs_btree_cur_t *cur, /* btree cursor */ int level, /* level in btree, 0 is leaf */ int *stat) /* success/failure */{ xfs_alloc_block_t *block; /* btree block */ int error; /* error return value */ int lev; /* btree level */ ASSERT(level < cur->bc_nlevels); /* * Read-ahead to the left at this level. */ xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); /* * Decrement the ptr at this level. If we're still in the block * then we're done. */ if (--cur->bc_ptrs[level] > 0) { *stat = 1; return 0; } /* * Get a pointer to the btree block. */ block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[level]);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, level, cur->bc_bufs[level]))) return error;#endif /* * If we just went off the left edge of the tree, return failure. */ if (be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK) { *stat = 0; return 0; } /* * March up the tree decrementing pointers. * Stop when we don't go off the left edge of a block. */ for (lev = level + 1; lev < cur->bc_nlevels; lev++) { if (--cur->bc_ptrs[lev] > 0) break; /* * Read-ahead the left block, we're going to read it * in the next loop. */ xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); } /* * If we went off the root then we are seriously confused. */ ASSERT(lev < cur->bc_nlevels); /* * Now walk back down the tree, fixing up the cursor's buffer * pointers and key numbers. */ for (block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]); lev > level; ) { xfs_agblock_t agbno; /* block number of btree block */ xfs_buf_t *bp; /* buffer pointer for block */ agbno = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno, agbno, 0, &bp, XFS_ALLOC_BTREE_REF))) return error; lev--; xfs_btree_setbuf(cur, lev, bp); block = XFS_BUF_TO_ALLOC_BLOCK(bp); if ((error = xfs_btree_check_sblock(cur, block, lev, bp))) return error; cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs); } *stat = 1; return 0;}/* * Delete the record pointed to by cur. * The cursor refers to the place where the record was (could be inserted) * when the operation returns. */int /* error */xfs_alloc_delete( xfs_btree_cur_t *cur, /* btree cursor */ int *stat) /* success/failure */{ int error; /* error return value */ int i; /* result code */ int level; /* btree level */ /* * Go up the tree, starting at leaf level. * If 2 is returned then a join was done; go to the next level. * Otherwise we are done. */ for (level = 0, i = 2; i == 2; level++) { if ((error = xfs_alloc_delrec(cur, level, &i))) return error; } if (i == 0) { for (level = 1; level < cur->bc_nlevels; level++) { if (cur->bc_ptrs[level] == 0) { if ((error = xfs_alloc_decrement(cur, level, &i))) return error; break; } } } *stat = i; return 0;}/* * Get the data from the pointed-to record. */int /* error */xfs_alloc_get_rec( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agblock_t *bno, /* output: starting block of extent */ xfs_extlen_t *len, /* output: length of extent */ int *stat) /* output: success/failure */{ xfs_alloc_block_t *block; /* btree block */#ifdef DEBUG int error; /* error return value */#endif int ptr; /* record number */ ptr = cur->bc_ptrs[0]; block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0]))) return error;#endif /* * Off the right end or left end, return failure. */ if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { *stat = 0; return 0; } /* * Point to the record and extract its data. */ { xfs_alloc_rec_t *rec; /* record data */ rec = XFS_ALLOC_REC_ADDR(block, ptr, cur); *bno = be32_to_cpu(rec->ar_startblock); *len = be32_to_cpu(rec->ar_blockcount); } *stat = 1; return 0;}/* * Increment cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int /* error */xfs_alloc_increment( xfs_btree_cur_t *cur, /* btree cursor */ int level, /* level in btree, 0 is leaf */ int *stat) /* success/failure */{ xfs_alloc_block_t *block; /* btree block */ xfs_buf_t *bp; /* tree block buffer */ int error; /* error return value */ int lev; /* btree level */ ASSERT(level < cur->bc_nlevels); /* * Read-ahead to the right at this level. */ xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); /* * Get a pointer to the btree block. */ bp = cur->bc_bufs[level]; block = XFS_BUF_TO_ALLOC_BLOCK(bp);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, level, bp))) return error;#endif /* * Increment the ptr at this level. If we're still in the block * then we're done. */ if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) { *stat = 1; return 0; } /* * If we just went off the right edge of the tree, return failure. */ if (be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK) { *stat = 0; return 0; } /* * March up the tree incrementing pointers. * Stop when we don't go off the right edge of a block. */ for (lev = level + 1; lev < cur->bc_nlevels; lev++) { bp = cur->bc_bufs[lev]; block = XFS_BUF_TO_ALLOC_BLOCK(bp);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, lev, bp))) return error;#endif if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs)) break; /* * Read-ahead the right block, we're going to read it * in the next loop. */ xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); } /* * If we went off the root then we are seriously confused. */ ASSERT(lev < cur->bc_nlevels); /* * Now walk back down the tree, fixing up the cursor's buffer * pointers and key numbers. */ for (bp = cur->bc_bufs[lev], block = XFS_BUF_TO_ALLOC_BLOCK(bp); lev > level; ) { xfs_agblock_t agbno; /* block number of btree block */ agbno = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno, agbno, 0, &bp, XFS_ALLOC_BTREE_REF))) return error; lev--; xfs_btree_setbuf(cur, lev, bp); block = XFS_BUF_TO_ALLOC_BLOCK(bp); if ((error = xfs_btree_check_sblock(cur, block, lev, bp))) return error; cur->bc_ptrs[lev] = 1; } *stat = 1; return 0;}/* * Insert the current record at the point referenced by cur. * The cursor may be inconsistent on return if splits have been done. */int /* error */xfs_alloc_insert( xfs_btree_cur_t *cur, /* btree cursor */ int *stat) /* success/failure */{ int error; /* error return value */ int i; /* result value, 0 for failure */ int level; /* current level number in btree */ xfs_agblock_t nbno; /* new block number (split result) */ xfs_btree_cur_t *ncur; /* new cursor (split result) */ xfs_alloc_rec_t nrec; /* record being inserted this level */ xfs_btree_cur_t *pcur; /* previous level's cursor */ level = 0; nbno = NULLAGBLOCK; nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); ncur = NULL; pcur = cur; /* * Loop going up the tree, starting at the leaf level. * Stop when we don't get a split block, that must mean that * the insert is finished with this level. */ do { /* * Insert nrec/nbno into this level of the tree. * Note if we fail, nbno will be null. */ if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur, &i))) { if (pcur != cur) xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); return error; } /* * See if the cursor we just used is trash. * Can't trash the caller's cursor, but otherwise we should * if ncur is a new cursor or we're about to be done. */ if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { cur->bc_nlevels = pcur->bc_nlevels; xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); } /* * If we got a new cursor, switch to it. */ if (ncur) { pcur = ncur; ncur = NULL; } } while (nbno != NULLAGBLOCK); *stat = i; return 0;}/* * Lookup the record equal to [bno, len] in the btree given by cur. */int /* error */xfs_alloc_lookup_eq( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */{ cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; return xfs_alloc_lookup(cur, XFS_LOOKUP_EQ, stat);}/* * Lookup the first record greater than or equal to [bno, len] * in the btree given by cur. */int /* error */xfs_alloc_lookup_ge( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */{ cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; return xfs_alloc_lookup(cur, XFS_LOOKUP_GE, stat);}/* * Lookup the first record less than or equal to [bno, len] * in the btree given by cur. */int /* error */xfs_alloc_lookup_le( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */{ cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; return xfs_alloc_lookup(cur, XFS_LOOKUP_LE, stat);}/* * Update the record referred to by cur, to the value given by [bno, len]. * This either works (return 0) or gets an EFSCORRUPTED error. */int /* error */xfs_alloc_update( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ xfs_extlen_t len) /* length of extent */{ xfs_alloc_block_t *block; /* btree block to update */ int error; /* error return value */ int ptr; /* current record number (updating) */ ASSERT(len > 0); /* * Pick up the a.g. freelist struct and the current block. */ block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0]))) return error;#endif /* * Get the address of the rec to be updated. */ ptr = cur->bc_ptrs[0]; { xfs_alloc_rec_t *rp; /* pointer to updated record */ rp = XFS_ALLOC_REC_ADDR(block, ptr, cur); /* * Fill in the new contents and log them. */ rp->ar_startblock = cpu_to_be32(bno); rp->ar_blockcount = cpu_to_be32(len); xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr); } /* * If it's the by-size btree and it's the last leaf block and * it's the last record... then update the size of the longest * extent in the a.g., which we cache in the a.g. freelist header. */ if (cur->bc_btnum == XFS_BTNUM_CNT && be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && ptr == be16_to_cpu(block->bb_numrecs)) { xfs_agf_t *agf; /* a.g. freespace header */ xfs_agnumber_t seqno; agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); seqno = be32_to_cpu(agf->agf_seqno); cur->bc_mp->m_perag[seqno].pagf_longest = len; agf->agf_longest = cpu_to_be32(len); xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); } /* * Updating first record in leaf. Pass new key value up to our parent. */ if (ptr == 1) { xfs_alloc_key_t key; /* key containing [bno, len] */ key.ar_startblock = cpu_to_be32(bno); key.ar_blockcount = cpu_to_be32(len); if ((error = xfs_alloc_updkey(cur, &key, 1))) return error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -