📄 xfs_bmap.c
字号:
ASSERT(0); } *curp = cur; if (delta) { temp2 += temp; if (delta->xed_startoff > temp) delta->xed_startoff = temp; if (delta->xed_blockcount < temp2) delta->xed_blockcount = temp2; }done: *logflagsp = rval; return error;#undef LEFT#undef RIGHT#undef PREV#undef MASK#undef MASK2#undef MASK3#undef MASK4#undef STATE_SET#undef STATE_TEST#undef STATE_SET_TEST#undef SWITCH_STATE}/* * Called by xfs_bmap_add_extent to handle cases converting an unwritten * allocation to a real allocation or vice versa. */STATIC int /* error */xfs_bmap_add_extent_unwritten_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ xfs_extdelta_t *delta) /* Change made to incore extents */{ xfs_btree_cur_t *cur; /* btree cursor */ xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ int error; /* error return value */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t new_endoff; /* end offset of new entry */ xfs_exntst_t newext; /* new extent state */ xfs_exntst_t oldext; /* old extent state */ xfs_bmbt_irec_t r[3]; /* neighbor extent entries */ /* left is 0, right is 1, prev is 2 */ int rval=0; /* return value (logging flags) */ int state = 0;/* state bits, accessed thru macros */ xfs_filblks_t temp=0; xfs_filblks_t temp2=0; enum { /* bit number definitions for state */ LEFT_CONTIG, RIGHT_CONTIG, LEFT_FILLING, RIGHT_FILLING, LEFT_DELAY, RIGHT_DELAY, LEFT_VALID, RIGHT_VALID };#define LEFT r[0]#define RIGHT r[1]#define PREV r[2]#define MASK(b) (1 << (b))#define MASK2(a,b) (MASK(a) | MASK(b))#define MASK3(a,b,c) (MASK2(a,b) | MASK(c))#define MASK4(a,b,c,d) (MASK3(a,b,c) | MASK(d))#define STATE_SET(b,v) ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))#define STATE_TEST(b) (state & MASK(b))#define STATE_SET_TEST(b,v) ((v) ? ((state |= MASK(b)), 1) : \ ((state &= ~MASK(b)), 0))#define SWITCH_STATE \ (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG)) /* * Set up a bunch of variables to make the tests simpler. */ error = 0; cur = *curp; ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &PREV); newext = new->br_state; oldext = (newext == XFS_EXT_UNWRITTEN) ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; ASSERT(PREV.br_state == oldext); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(PREV.br_startoff <= new->br_startoff); ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); /* * Set flags determining what part of the previous oldext allocation * extent is being replaced by a newext allocation. */ STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff); STATE_SET(RIGHT_FILLING, PREV.br_startoff + PREV.br_blockcount == new_endoff); /* * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ if (STATE_SET_TEST(LEFT_VALID, idx > 0)) { xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT); STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock)); } STATE_SET(LEFT_CONTIG, STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) && LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff && LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock && LEFT.br_state == newext && LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN); /* * Check and set flags if this segment has a right neighbor. * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ if (STATE_SET_TEST(RIGHT_VALID, idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) { xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT); STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock)); } STATE_SET(RIGHT_CONTIG, STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) && new_endoff == RIGHT.br_startoff && new->br_startblock + new->br_blockcount == RIGHT.br_startblock && newext == RIGHT.br_state && new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN && ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) != MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) || LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN)); /* * Switch out based on the FILLING and CONTIG state bits. */ switch (SWITCH_STATE) { case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): /* * Setting all of a previous oldext extent to newext. * The left and right neighbors are both contiguous with new. */ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1, XFS_DATA_FORK); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1, XFS_DATA_FORK); XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK); xfs_iext_remove(ifp, idx, 2); ip->i_df.if_lastex = idx - 1; ip->i_d.di_nextents -= 2; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount, LEFT.br_state))) goto done; } /* DELTA: Three in-core extents are replaced by one. */ temp = LEFT.br_startoff; temp2 = LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount; break; case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): /* * Setting all of a previous oldext extent to newext. * The left neighbor is contiguous, the right is not. */ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1, XFS_DATA_FORK); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK); xfs_iext_remove(ifp, idx, 1); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + PREV.br_blockcount, LEFT.br_state))) goto done; } /* DELTA: Two in-core extents are replaced by one. */ temp = LEFT.br_startoff; temp2 = LEFT.br_blockcount + PREV.br_blockcount; break; case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): /* * Setting all of a previous oldext extent to newext. * The right neighbor is contiguous, the left is not. */ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount + RIGHT.br_blockcount); xfs_bmbt_set_state(ep, newext); XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK); ip->i_df.if_lastex = idx; XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK); xfs_iext_remove(ifp, idx + 1, 1); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, RIGHT.br_startblock, RIGHT.br_blockcount, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_update(cur, new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext))) goto done; } /* DELTA: Two in-core extents are replaced by one. */ temp = PREV.br_startoff; temp2 = PREV.br_blockcount + RIGHT.br_blockcount; break; case MASK2(LEFT_FILLING, RIGHT_FILLING): /* * Setting all of a previous oldext extent to newext. * Neither the left nor right neighbors are contiguous with * the new one. */ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_state(ep, newext); XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK); ip->i_df.if_lastex = idx; if (cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_update(cur, new->br_startoff, new->br_startblock, new->br_blockcount, newext))) goto done; } /* DELTA: The in-core extent described by new changed type. */ temp = new->br_startoff; temp2 = new->br_blockcount; break; case MASK2(LEFT_FILLING, LEFT_CONTIG): /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is contiguous. */ XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK); XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_startblock(ep, new->br_startblock + new->br_blockcount); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; if (cur == NULL) rval = XFS_ILOG_DEXT; else { rval = 0; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_update(cur, PREV.br_startoff + new->br_blockcount, PREV.br_startblock + new->br_blockcount, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; if ((error = xfs_bmbt_decrement(cur, 0, &i))) goto done; if (xfs_bmbt_update(cur, LEFT.br_startoff, LEFT.br_startblock, LEFT.br_blockcount + new->br_blockcount, LEFT.br_state)) goto done; } /* DELTA: The boundary between two in-core extents moved. */ temp = LEFT.br_startoff; temp2 = LEFT.br_blockcount + PREV.br_blockcount; break; case MASK(LEFT_FILLING): /* * Setting the first part of a previous oldext extent to newext. * The left neighbor is not contiguous. */ XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK); ASSERT(ep && xfs_bmbt_get_state(ep) == oldext); xfs_bmbt_set_startoff(ep, new_endoff); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); xfs_bmbt_set_startblock(ep, new->br_startblock + new->br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK); XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL, XFS_DATA_FORK); xfs_iext_insert(ifp, idx, 1, new); ip->i_df.if_lastex = idx; ip->i_d.di_nextents++; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { rval = XFS_ILOG_CORE; if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_update(cur, PREV.br_startoff + new->br_blockcount, PREV.br_startblock + new->br_blockcount, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; cur->bc_rec.b = *new; if ((error = xfs_bmbt_insert(cur, &i))) goto done; ASSERT(i == 1); } /* DELTA: One in-core extent is split in two. */ temp = PREV.br_startoff; temp2 = PREV.br_blockcount; break; case MASK2(RIGHT_FILLING, RIGHT_CONTIG): /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is contiguous with the new allocation. */ XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK); XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -