📄 xfs_ialloc_btree.c
字号:
xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); keyp->ir_startino = rrp->ir_startino; } /* * Find the left block number by looking in the buffer. * Adjust numrecs, sibling pointers. */ be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); right->bb_rightsib = left->bb_rightsib; left->bb_rightsib = cpu_to_be32(args.agbno); right->bb_leftsib = cpu_to_be32(lbno); xfs_inobt_log_block(args.tp, rbp, XFS_BB_ALL_BITS); xfs_inobt_log_block(args.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 (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) { xfs_inobt_block_t *rrblock; /* rr btree block */ xfs_buf_t *rrbp; /* buffer for rrblock */ if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, be32_to_cpu(right->bb_rightsib), 0, &rrbp, XFS_INO_BTREE_REF))) return error; rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) return error; rrblock->bb_leftsib = cpu_to_be32(args.agbno); xfs_inobt_log_block(args.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] > be16_to_cpu(left->bb_numrecs) + 1) { xfs_btree_setbuf(cur, level, rbp); cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); } /* * If there are more levels, we'll need another cursor which refers * 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 = args.agbno; *stat = 1; return 0;}/* * Update keys at all levels from here to the root along the cursor's path. */STATIC int /* error */xfs_inobt_updkey( xfs_btree_cur_t *cur, /* btree cursor */ xfs_inobt_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_buf_t *bp; /* buffer for block */ xfs_inobt_block_t *block; /* btree block */#ifdef DEBUG int error; /* error return value */#endif xfs_inobt_key_t *kp; /* ptr to btree block keys */ bp = cur->bc_bufs[level]; block = XFS_BUF_TO_INOBT_BLOCK(bp);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, level, bp))) return error;#endif ptr = cur->bc_ptrs[level]; kp = XFS_INOBT_KEY_ADDR(block, ptr, cur); *kp = *keyp; xfs_inobt_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_inobt_decrement( xfs_btree_cur_t *cur, /* btree cursor */ int level, /* level in btree, 0 is leaf */ int *stat) /* success/failure */{ xfs_inobt_block_t *block; /* btree block */ int error; 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_INOBT_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_INOBT_BLOCK(cur->bc_bufs[lev]); lev > level; ) { xfs_agblock_t agbno; /* block number of btree block */ xfs_buf_t *bp; /* buffer containing btree block */ agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.i.agno, agbno, 0, &bp, XFS_INO_BTREE_REF))) return error; lev--; xfs_btree_setbuf(cur, lev, bp); block = XFS_BUF_TO_INOBT_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_inobt_delete( xfs_btree_cur_t *cur, /* btree cursor */ int *stat) /* success/failure */{ int error; 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_inobt_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_inobt_decrement(cur, level, &i))) return error; break; } } } *stat = i; return 0;}/* * Get the data from the pointed-to record. */int /* error */xfs_inobt_get_rec( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agino_t *ino, /* output: starting inode of chunk */ __int32_t *fcnt, /* output: number of free inodes */ xfs_inofree_t *free, /* output: free inode mask */ int *stat) /* output: success/failure */{ xfs_inobt_block_t *block; /* btree block */ xfs_buf_t *bp; /* buffer containing btree block */#ifdef DEBUG int error; /* error return value */#endif int ptr; /* record number */ xfs_inobt_rec_t *rec; /* record data */ bp = cur->bc_bufs[0]; ptr = cur->bc_ptrs[0]; block = XFS_BUF_TO_INOBT_BLOCK(bp);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, 0, bp))) 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. */ rec = XFS_INOBT_REC_ADDR(block, ptr, cur); *ino = be32_to_cpu(rec->ir_startino); *fcnt = be32_to_cpu(rec->ir_freecount); *free = be64_to_cpu(rec->ir_free); *stat = 1; return 0;}/* * Increment cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int /* error */xfs_inobt_increment( xfs_btree_cur_t *cur, /* btree cursor */ int level, /* level in btree, 0 is leaf */ int *stat) /* success/failure */{ xfs_inobt_block_t *block; /* btree block */ xfs_buf_t *bp; /* buffer containing btree block */ 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_INOBT_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_INOBT_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_INOBT_BLOCK(bp); lev > level; ) { xfs_agblock_t agbno; /* block number of btree block */ agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.i.agno, agbno, 0, &bp, XFS_INO_BTREE_REF))) return error; lev--; xfs_btree_setbuf(cur, lev, bp); block = XFS_BUF_TO_INOBT_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_inobt_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_inobt_rec_t nrec; /* record being inserted this level */ xfs_btree_cur_t *pcur; /* previous level's cursor */ level = 0; nbno = NULLAGBLOCK; nrec.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); nrec.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); nrec.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); 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_inobt_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 ino in the btree given by cur. */int /* error */xfs_inobt_lookup_eq( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agino_t ino, /* starting inode of chunk */ __int32_t fcnt, /* free inode count */ xfs_inofree_t free, /* free inode mask */ int *stat) /* success/failure */{ cur->bc_rec.i.ir_startino = ino; cur->bc_rec.i.ir_freecount = fcnt; cur->bc_rec.i.ir_free = free; return xfs_inobt_lookup(cur, XFS_LOOKUP_EQ, stat);}/* * Lookup the first record greater than or equal to ino * in the btree given by cur. */int /* error */xfs_inobt_lookup_ge( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agino_t ino, /* starting inode of chunk */ __int32_t fcnt, /* free inode count */ xfs_inofree_t free, /* free inode mask */ int *stat) /* success/failure */{ cur->bc_rec.i.ir_startino = ino; cur->bc_rec.i.ir_freecount = fcnt; cur->bc_rec.i.ir_free = free; return xfs_inobt_lookup(cur, XFS_LOOKUP_GE, stat);}/* * Lookup the first record less than or equal to ino * in the btree given by cur. */int /* error */xfs_inobt_lookup_le( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agino_t ino, /* starting inode of chunk */ __int32_t fcnt, /* free inode count */ xfs_inofree_t free, /* free inode mask */ int *stat) /* success/failure */{ cur->bc_rec.i.ir_startino = ino; cur->bc_rec.i.ir_freecount = fcnt; cur->bc_rec.i.ir_free = free; return xfs_inobt_lookup(cur, XFS_LOOKUP_LE, stat);}/* * Update the record referred to by cur, to the value given * by [ino, fcnt, free]. * This either works (return 0) or gets an EFSCORRUPTED error. */int /* error */xfs_inobt_update( xfs_btree_cur_t *cur, /* btree cursor */ xfs_agino_t ino, /* starting inode of chunk */ __int32_t fcnt, /* free inode count */ xfs_inofree_t free) /* free inode mask */{ xfs_inobt_block_t *block; /* btree block to update */ xfs_buf_t *bp; /* buffer containing btree block */ int error; /* error return value */ int ptr; /* current record number (updating) */ xfs_inobt_rec_t *rp; /* pointer to updated record */ /* * Pick up the current block. */ bp = cur->bc_bufs[0]; block = XFS_BUF_TO_INOBT_BLOCK(bp);#ifdef DEBUG if ((error = xfs_btree_check_sblock(cur, block, 0, bp))) return error;#endif /* * Get the address of the rec to be updated. */ ptr = cur->bc_ptrs[0]; rp = XFS_INOBT_REC_ADDR(block, ptr, cur); /* * Fill in the new contents and log them. */ rp->ir_startino = cpu_to_be32(ino); rp->ir_freecount = cpu_to_be32(fcnt); rp->ir_free = cpu_to_be64(free); xfs_inobt_log_recs(cur, bp, ptr, ptr); /* * Updating first record in leaf. Pass new key value up to our parent. */ if (ptr == 1) { xfs_inobt_key_t key; /* key containing [ino] */ key.ir_startino = cpu_to_be32(ino); if ((error = xfs_inobt_updkey(cur, &key, 1))) return error; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -