xfs_bmap_btree.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,360 行 · 第 1/5 页
C
2,360 行
xfs_bmbt_ptr_t *cpp;#ifdef DEBUG int error;#endif#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_killroot";#endif int i; xfs_bmbt_key_t *kp; xfs_inode_t *ip; xfs_ifork_t *ifp; int level; xfs_bmbt_ptr_t *pp; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); level = cur->bc_nlevels - 1; ASSERT(level >= 1); /* * Don't deal with the root block needs to be a leaf case. * We're just going to turn the thing back into extents anyway. */ if (level == 1) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); return 0; } block = xfs_bmbt_get_block(cur, level, &cbp); /* * Give up if the root has multiple children. */ if (INT_GET(block->bb_numrecs, ARCH_CONVERT) != 1) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); return 0; } /* * Only do this if the next level will fit. * Then the data must be copied up to the inode, * instead of freeing the root you free the next level. */ cbp = cur->bc_bufs[level - 1]; cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); if (INT_GET(cblock->bb_numrecs, ARCH_CONVERT) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); return 0; } ASSERT(INT_GET(cblock->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO); ASSERT(INT_GET(cblock->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO); ip = cur->bc_private.b.ip; ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); i = (int)(INT_GET(cblock->bb_numrecs, ARCH_CONVERT) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); if (i) { xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); block = ifp->if_broot; } INT_MOD(block->bb_numrecs, ARCH_CONVERT, i); ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) == INT_GET(cblock->bb_numrecs, ARCH_CONVERT)); kp = XFS_BMAP_KEY_IADDR(block, 1, cur); ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); memcpy(kp, ckp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*kp)); pp = XFS_BMAP_PTR_IADDR(block, 1, cur); cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);#ifdef DEBUG for (i = 0; i < INT_GET(cblock->bb_numrecs, ARCH_CONVERT); i++) { if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } }#endif memcpy(pp, cpp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*pp)); xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, cur->bc_private.b.flist, cur->bc_mp); ip->i_d.di_nblocks--; XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(cur->bc_tp, cbp); cur->bc_bufs[level - 1] = NULL; INT_MOD(block->bb_level, ARCH_CONVERT, -1); xfs_trans_log_inode(cur->bc_tp, ip, XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); cur->bc_nlevels--; XFS_BMBT_TRACE_CURSOR(cur, EXIT); return 0;}/* * Log key values from the btree block. */STATIC voidxfs_bmbt_log_keys( xfs_btree_cur_t *cur, xfs_buf_t *bp, int kfirst, int klast){#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_log_keys";#endif xfs_trans_t *tp; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); tp = cur->bc_tp; if (bp) { xfs_bmbt_block_t *block; int first; xfs_bmbt_key_t *kp; int last; block = XFS_BUF_TO_BMBT_BLOCK(bp); kp = XFS_BMAP_KEY_DADDR(block, 1, cur); first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); xfs_trans_log_buf(tp, bp, first, last); } else { xfs_inode_t *ip; ip = cur->bc_private.b.ip; xfs_trans_log_inode(tp, ip, XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); } XFS_BMBT_TRACE_CURSOR(cur, EXIT);}/* * Log pointer values from the btree block. */STATIC voidxfs_bmbt_log_ptrs( xfs_btree_cur_t *cur, xfs_buf_t *bp, int pfirst, int plast){#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_log_ptrs";#endif xfs_trans_t *tp; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); tp = cur->bc_tp; if (bp) { xfs_bmbt_block_t *block; int first; int last; xfs_bmbt_ptr_t *pp; block = XFS_BUF_TO_BMBT_BLOCK(bp); pp = XFS_BMAP_PTR_DADDR(block, 1, cur); first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); xfs_trans_log_buf(tp, bp, first, last); } else { xfs_inode_t *ip; ip = cur->bc_private.b.ip; xfs_trans_log_inode(tp, ip, XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); } XFS_BMBT_TRACE_CURSOR(cur, EXIT);}/* * Lookup the record. The cursor is made to point to it, based on dir. */STATIC int /* error */xfs_bmbt_lookup( xfs_btree_cur_t *cur, xfs_lookup_t dir, int *stat) /* success/failure */{ xfs_bmbt_block_t *block=NULL; xfs_buf_t *bp; xfs_daddr_t d; xfs_sfiloff_t diff; int error; /* error return value */#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_lookup";#endif xfs_fsblock_t fsbno=0; int high; int i; int keyno=0; xfs_bmbt_key_t *kkbase=NULL; xfs_bmbt_key_t *kkp; xfs_bmbt_rec_t *krbase=NULL; xfs_bmbt_rec_t *krp; int level; int low; xfs_mount_t *mp; xfs_bmbt_ptr_t *pp; xfs_bmbt_irec_t *rp; xfs_fileoff_t startoff; xfs_trans_t *tp; XFS_STATS_INC(xs_bmbt_lookup); XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGI(cur, (int)dir); tp = cur->bc_tp; mp = cur->bc_mp; rp = &cur->bc_rec.b; for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { if (level < cur->bc_nlevels - 1) { d = XFS_FSB_TO_DADDR(mp, fsbno); bp = cur->bc_bufs[level]; if (bp && XFS_BUF_ADDR(bp) != d) bp = (xfs_buf_t *)0; if (!bp) { if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } xfs_btree_setbuf(cur, level, bp); block = XFS_BUF_TO_BMBT_BLOCK(bp); if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } } else block = XFS_BUF_TO_BMBT_BLOCK(bp); } else block = xfs_bmbt_get_block(cur, level, &bp); if (diff == 0) keyno = 1; else { if (level > 0) kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur); else krbase = XFS_BMAP_REC_IADDR(block, 1, cur); low = 1; if (!(high = INT_GET(block->bb_numrecs, ARCH_CONVERT))) { ASSERT(level == 0); cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } while (low <= high) { XFS_STATS_INC(xs_bmbt_compare); keyno = (low + high) >> 1; if (level > 0) { kkp = kkbase + keyno - 1; startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT); } else { krp = krbase + keyno - 1; startoff = xfs_bmbt_disk_get_startoff(krp); } diff = (xfs_sfiloff_t) (startoff - rp->br_startoff); if (diff < 0) low = keyno + 1; else if (diff > 0) high = keyno - 1; else break; } } if (level > 0) { if (diff > 0 && --keyno < 1) keyno = 1; pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);#ifdef DEBUG if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif fsbno = INT_GET(*pp, ARCH_CONVERT); cur->bc_ptrs[level] = keyno; } } if (dir != XFS_LOOKUP_LE && diff < 0) { keyno++; /* * If ge search and we went off the end of the block, but it's * not the last block, we're in the wrong block. */ if (dir == XFS_LOOKUP_GE && keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT) && INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) { cur->bc_ptrs[0] = keyno; if ((error = xfs_bmbt_increment(cur, 0, &i))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } XFS_WANT_CORRUPTED_RETURN(i == 1); XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0; } } else if (dir == XFS_LOOKUP_LE && diff > 0) keyno--; cur->bc_ptrs[0] = keyno; if (keyno == 0 || keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT)) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; } else { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0)); } return 0;}/* * Move 1 record left from cur/level if possible. * Update cur to reflect the new path. */STATIC int /* error */xfs_bmbt_lshift( xfs_btree_cur_t *cur, int level, int *stat) /* success/failure */{ int error; /* error return value */#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_lshift";#endif#ifdef DEBUG int i; /* loop counter */#endif xfs_bmbt_key_t key; /* bmap btree key */ xfs_buf_t *lbp; /* left buffer pointer */ xfs_bmbt_block_t *left; /* left btree block */ xfs_bmbt_key_t *lkp=NULL; /* left btree key */ xfs_bmbt_ptr_t *lpp; /* left address pointer */ int lrecs; /* left record count */ xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */ xfs_mount_t *mp; /* file system mount point */ xfs_buf_t *rbp; /* right buffer pointer */ xfs_bmbt_block_t *right; /* right btree block */ xfs_bmbt_key_t *rkp=NULL; /* right btree key */ xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */ xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ int rrecs; /* right record count */ 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; } rbp = cur->bc_bufs[level]; right = XFS_BUF_TO_BMBT_BLOCK(rbp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif if (INT_GET(right->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } if (cur->bc_ptrs[level] <= 1) { 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(right->bb_leftsib, ARCH_CONVERT), 0, &lbp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } left = XFS_BUF_TO_BMBT_BLOCK(lbp); if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } if (INT_GET(left->bb_numrecs, ARCH_CONVERT) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1; if (level > 0) { lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); *lkp = *rkp; xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);#ifdef DEBUG if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif *lpp = *rpp; /* INT_: direct copy */ xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); } else { lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); rrp = XFS_BMAP_REC_IADDR(right, 1, cur); *lrp = *rrp; xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); } INT_SET(left->bb_numrecs, ARCH_CONVERT, lrecs); xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);#ifdef DEBUG if (level > 0) xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); else xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp);#endif rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; INT_SET(right->bb_numrecs, ARCH_CONVERT, rrecs); xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); if (level > 0) {#ifdef DEBUG for (i = 0; i < rrecs; i++) { if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT), level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } }#endif memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); xfs_bmbt_log_keys(cur, rbp, 1, rrecs); xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); } else { memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); xfs_bmbt_log_recs(cur, rbp, 1, rrecs); INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rrp)); rkp = &key; } if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } cur->bc_ptrs[level]--; XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;}/* * Move 1 record right from cur/level if possible. * Update cur to reflect the new path. */STATIC int /* error */xfs_bmbt_rshift( xfs_btree_cur_t *cur, int level, int *stat) /* success/failure */{ int error; /* error return value */#ifdef XFS_BMBT_TRACE static char fname[] = "xfs_bmbt_rshift";#endif int i; /* loop counter */ xfs_bmbt_key_t key; /* bmap btree key */ 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_mount_t *mp; /* file system mount point */ 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_rec_t *rrp=NULL; /* right record pointer */ struct xfs_btree_cur *tcur; /* temporary btree cursor */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?