xfs_alloc_btree.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,070 行 · 第 1/5 页
C
2,070 行
return error; }#endif memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); /* INT_: copy */ memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp)); /* INT_: copy */ xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); *keyp = *rkp; } /* * For leaf blocks, copy records over to the new block. */ else { xfs_alloc_rec_t *lrp; /* left btree record pointer */ xfs_alloc_rec_t *rrp; /* right btree record pointer */ lrp = XFS_ALLOC_REC_ADDR(left, i, cur); rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp)); xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); keyp->ar_startblock = rrp->ar_startblock; /* INT_: direct copy */ keyp->ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */ } /* * Find the left block number by looking in the buffer. * Adjust numrecs, sibling pointers. */ lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp)); INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT))); right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */ INT_SET(left->bb_rightsib, ARCH_CONVERT, rbno); INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno); xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS); xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); /* * If there's a block to the new block's right, make that block * point back to right instead of to left. */ if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) { xfs_alloc_block_t *rrblock; /* rr btree block */ xfs_buf_t *rrbp; /* buffer for rrblock */ if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno, INT_GET(right->bb_rightsib, ARCH_CONVERT), 0, &rrbp, XFS_ALLOC_BTREE_REF))) return error; rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp); if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) return error; INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, rbno); xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); } /* * If the cursor is really in the right block, move it there. * If it's just pointing past the last entry in left, then we'll * insert there, so don't change anything in that case. */ if (cur->bc_ptrs[level] > INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1) { xfs_btree_setbuf(cur, level, rbp); cur->bc_ptrs[level] -= INT_GET(left->bb_numrecs, ARCH_CONVERT); } /* * If there are more levels, we'll need another cursor which refers to * the right block, no matter where this cursor was. */ if (level + 1 < cur->bc_nlevels) { if ((error = xfs_btree_dup_cursor(cur, curp))) return error; (*curp)->bc_ptrs[level + 1]++; } *bnop = rbno; *stat = 1; return 0;}/* * Update keys at all levels from here to the root along the cursor's path. */STATIC int /* error */xfs_alloc_updkey( xfs_btree_cur_t *cur, /* btree cursor */ xfs_alloc_key_t *keyp, /* new key value to update to */ int level) /* starting level for update */{ int ptr; /* index of key in block */ /* * Go up the tree from this level toward the root. * At each level, update the key value to the value input. * Stop when we reach a level where the cursor isn't pointing * at the first entry in the block. */ for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { xfs_alloc_block_t *block; /* btree block */ xfs_buf_t *bp; /* buffer for block */#ifdef DEBUG int error; /* error return value */#endif xfs_alloc_key_t *kp; /* ptr to btree block keys */ 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 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 (INT_GET(block->bb_leftsib, ARCH_CONVERT) == 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 = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT); 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] = INT_GET(block->bb_numrecs, ARCH_CONVERT); } *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 > INT_GET(block->bb_numrecs, ARCH_CONVERT) || 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 = INT_GET(rec->ar_startblock, ARCH_CONVERT); *len = INT_GET(rec->ar_blockcount, ARCH_CONVERT); } *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] <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) { *stat = 1; return 0; } /* * If we just went off the right edge of the tree, return failure. */ if (INT_GET(block->bb_rightsib, ARCH_CONVERT) == 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] <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) 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 = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT); 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; INT_SET(nrec.ar_startblock, ARCH_CONVERT, cur->bc_rec.a.ar_startblock); INT_SET(nrec.ar_blockcount, ARCH_CONVERT, cur->bc_rec.a.ar_blockcount); ncur = (xfs_btree_cur_t *)0; 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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?