xfs_bmap_btree.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,360 行 · 第 1/5 页
C
2,360 行
XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGI(cur, level); if (level == cur->bc_nlevels - 1) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } lbp = cur->bc_bufs[level]; left = XFS_BUF_TO_BMBT_BLOCK(lbp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif if (INT_GET(left->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } if (cur->bc_ptrs[level] >= INT_GET(left->bb_numrecs, ARCH_CONVERT)) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } mp = cur->bc_mp; if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0, &rbp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } right = XFS_BUF_TO_BMBT_BLOCK(rbp); if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } if (INT_GET(right->bb_numrecs, ARCH_CONVERT) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } if (level > 0) { lkp = XFS_BMAP_KEY_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur); lpp = XFS_BMAP_PTR_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur); rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);#ifdef DEBUG for (i = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; i >= 0; i--) { if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } }#endif memmove(rkp + 1, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); memmove(rpp + 1, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));#ifdef DEBUG if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif *rkp = *lkp; *rpp = *lpp; /* INT_: direct copy */ xfs_bmbt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1); xfs_bmbt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1); } else { lrp = XFS_BMAP_REC_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur); rrp = XFS_BMAP_REC_IADDR(right, 1, cur); memmove(rrp + 1, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp)); *rrp = *lrp; xfs_bmbt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1); INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rrp)); rkp = &key; } INT_MOD(left->bb_numrecs, ARCH_CONVERT, -1); xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);#ifdef DEBUG if (level > 0) xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1); else xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1);#endif xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); if ((error = xfs_btree_dup_cursor(cur, &tcur))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } i = xfs_btree_lastrec(tcur, level); XFS_WANT_CORRUPTED_GOTO(i == 1, error0); if ((error = xfs_bmbt_increment(tcur, level, &i))) { XFS_BMBT_TRACE_CURSOR(tcur, ERROR); goto error1; } XFS_WANT_CORRUPTED_GOTO(i == 1, error0); if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) { XFS_BMBT_TRACE_CURSOR(tcur, ERROR); goto error1; } xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;error0: XFS_BMBT_TRACE_CURSOR(cur, ERROR);error1: xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); return error;}/* * Determine the extent state. *//* ARGSUSED */STATIC xfs_exntst_txfs_extent_state( xfs_filblks_t blks, int extent_flag){ if (extent_flag) { ASSERT(blks != 0); /* saved for DMIG */ return XFS_EXT_UNWRITTEN; } return XFS_EXT_NORM;}/* * Split cur/level block in half. * Return new block number and its first record (to be inserted into parent). */STATIC int /* error */xfs_bmbt_split( xfs_btree_cur_t *cur, int level, xfs_fsblock_t *bnop, xfs_bmbt_key_t *keyp, xfs_btree_cur_t **curp, int *stat) /* success/failure */{ xfs_alloc_arg_t args; /* block allocation args */ int error; /* error return value */#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_split";#endif int i; /* loop counter */ xfs_fsblock_t lbno; /* left sibling block number */ xfs_buf_t *lbp; /* left buffer pointer */ xfs_bmbt_block_t *left; /* left btree block */ xfs_bmbt_key_t *lkp; /* left btree key */ xfs_bmbt_ptr_t *lpp; /* left address pointer */ xfs_bmbt_rec_t *lrp; /* left record pointer */ xfs_buf_t *rbp; /* right buffer pointer */ xfs_bmbt_block_t *right; /* right btree block */ xfs_bmbt_key_t *rkp; /* right btree key */ xfs_bmbt_ptr_t *rpp; /* right address pointer */ xfs_bmbt_block_t *rrblock; /* right-right btree block */ xfs_buf_t *rrbp; /* right-right buffer pointer */ xfs_bmbt_rec_t *rrp; /* right record pointer */ XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp); args.tp = cur->bc_tp; args.mp = cur->bc_mp; lbp = cur->bc_bufs[level]; lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); left = XFS_BUF_TO_BMBT_BLOCK(lbp); args.fsbno = cur->bc_private.b.firstblock; if (args.fsbno == NULLFSBLOCK) { args.fsbno = lbno; args.type = XFS_ALLOCTYPE_START_BNO; } else if (cur->bc_private.b.flist->xbf_low) args.type = XFS_ALLOCTYPE_FIRST_AG; else args.type = XFS_ALLOCTYPE_NEAR_BNO; args.mod = args.minleft = args.alignment = args.total = args.isfl = args.userdata = args.minalignslop = 0; args.minlen = args.maxlen = args.prod = 1; args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return XFS_ERROR(ENOSPC); } if ((error = xfs_alloc_vextent(&args))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } if (args.fsbno == NULLFSBLOCK) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } ASSERT(args.len == 1); cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; cur->bc_private.b.ip->i_d.di_nblocks++; xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, XFS_TRANS_DQ_BCOUNT, 1L); rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); right = XFS_BUF_TO_BMBT_BLOCK(rbp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif INT_SET(right->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC); right->bb_level = left->bb_level; /* INT_: direct copy */ INT_SET(right->bb_numrecs, ARCH_CONVERT, (__uint16_t)(INT_GET(left->bb_numrecs, ARCH_CONVERT) / 2)); if ((INT_GET(left->bb_numrecs, ARCH_CONVERT) & 1) && cur->bc_ptrs[level] <= INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1) INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1); i = INT_GET(left->bb_numrecs, ARCH_CONVERT) - INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1; if (level > 0) { lkp = XFS_BMAP_KEY_IADDR(left, i, cur); lpp = XFS_BMAP_PTR_IADDR(left, i, cur); rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);#ifdef DEBUG for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) { if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } }#endif memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp)); xfs_bmbt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); xfs_bmbt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT); } else { lrp = XFS_BMAP_REC_IADDR(left, i, cur); rrp = XFS_BMAP_REC_IADDR(right, 1, cur); memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp)); xfs_bmbt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp); } 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, args.fsbno); INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno); xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) { if ((error = xfs_btree_read_bufl(args.mp, args.tp, INT_GET(right->bb_rightsib, ARCH_CONVERT), 0, &rrbp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, args.fsbno); xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); } 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 (level + 1 < cur->bc_nlevels) { if ((error = xfs_btree_dup_cursor(cur, curp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } (*curp)->bc_ptrs[level + 1]++; } *bnop = args.fsbno; XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;}/* * Update keys for the record. */STATIC intxfs_bmbt_updkey( xfs_btree_cur_t *cur, xfs_bmbt_key_t *keyp, /* on-disk format */ int level){ xfs_bmbt_block_t *block; xfs_buf_t *bp;#ifdef DEBUG int error;#endif#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_updkey";#endif xfs_bmbt_key_t *kp; int ptr; ASSERT(level >= 1); XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGIK(cur, level, keyp); for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { block = xfs_bmbt_get_block(cur, level, &bp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif ptr = cur->bc_ptrs[level]; kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); *kp = *keyp; xfs_bmbt_log_keys(cur, bp, ptr, ptr); } XFS_BMBT_TRACE_CURSOR(cur, EXIT); return 0;}/* * Convert on-disk form of btree root to in-memory form. */voidxfs_bmdr_to_bmbt( xfs_bmdr_block_t *dblock, int dblocklen, xfs_bmbt_block_t *rblock, int rblocklen){ int dmxr; xfs_bmbt_key_t *fkp; xfs_bmbt_ptr_t *fpp; xfs_bmbt_key_t *tkp; xfs_bmbt_ptr_t *tpp; INT_SET(rblock->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC); rblock->bb_level = dblock->bb_level; /* both in on-disk format */ ASSERT(INT_GET(rblock->bb_level, ARCH_CONVERT) > 0); rblock->bb_numrecs = dblock->bb_numrecs;/* both in on-disk format */ INT_SET(rblock->bb_leftsib, ARCH_CONVERT, NULLDFSBNO); INT_SET(rblock->bb_rightsib, ARCH_CONVERT, NULLDFSBNO); dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); dmxr = INT_GET(dblock->bb_numrecs, ARCH_CONVERT); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */}/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int /* error */xfs_bmbt_decrement( xfs_btree_cur_t *cur, int level, int *stat) /* success/failure */{ xfs_bmbt_block_t *block; xfs_buf_t *bp; int error; /* error return value */#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_decrement";#endif xfs_fsblock_t fsbno; int lev; xfs_mount_t *mp; xfs_trans_t *tp; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGI(cur, level); ASSERT(level < cur->bc_nlevels); if (level < cur->bc_nlevels - 1) xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); if (--cur->bc_ptrs[level] > 0) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0; } block = xfs_bmbt_get_block(cur, level, &bp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif if (INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } for (lev = level + 1; lev < cur->bc_nlevels; lev++) { if (--cur->bc_ptrs[lev] > 0) break; if (lev < cur->bc_nlevels - 1) xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); } if (lev == cur->bc_nlevels) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } tp = cur->bc_tp; mp = cur->bc_mp; for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT); if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } lev--; xfs_btree_setbuf(cur, lev, bp); block = XFS_BUF_TO_BMBT_BLOCK(bp); if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } cur->bc_ptrs[lev] = INT_GET(block->bb_numrecs, ARCH_CONVERT); } XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;}/* * Delete the record pointed to by cur. */int /* error */xfs_bmbt_delete( xfs_btree_cur_t *cur, int *stat) /* success/failure */{ int error; /* error return value */#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_delete";#endif int i; int level; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); for (level = 0, i = 2; i == 2; level++) { if ((error = xfs_bmbt_delrec(cur, level, &i))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } } if (i == 0) { for (level = 1; level < cur->bc_nlevels; level++) { if (cur->bc_ptrs[level] == 0) { if ((error = xfs_bmbt_decrement(cur, level, &i))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } break; } } } XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = i; return 0;}/* * Convert a compressed bmap extent record to an uncompressed form. * This code must be in sync with the routines xfs_bmbt_get_startoff,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?