📄 xfs_bmap.c
字号:
xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1), new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext); XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, 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, PREV.br_startblock, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; if ((error = xfs_bmbt_increment(cur, 0, &i))) goto done; if ((error = xfs_bmbt_update(cur, new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext))) goto done; } /* DELTA: The boundary between two in-core extents moved. */ temp = PREV.br_startoff; temp2 = PREV.br_blockcount + RIGHT.br_blockcount; break; case MASK(RIGHT_FILLING): /* * Setting the last part of a previous oldext extent to newext. * The right neighbor is not contiguous. */ XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_blockcount(ep, PREV.br_blockcount - new->br_blockcount); XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK); XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL, XFS_DATA_FORK); xfs_iext_insert(ifp, idx + 1, 1, new); ip->i_df.if_lastex = 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_update(cur, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount - new->br_blockcount, oldext))) goto done; if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, new->br_startblock, new->br_blockcount, &i))) goto done; ASSERT(i == 0); cur->bc_rec.b.br_state = XFS_EXT_NORM; 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 0: /* * Setting the middle part of a previous oldext extent to * newext. Contiguity is impossible here. * One extent becomes three extents. */ XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK); xfs_bmbt_set_blockcount(ep, new->br_startoff - PREV.br_startoff); XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK); r[0] = *new; r[1].br_startoff = new_endoff; r[1].br_blockcount = PREV.br_startoff + PREV.br_blockcount - new_endoff; r[1].br_startblock = new->br_startblock + new->br_blockcount; r[1].br_state = oldext; XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1], XFS_DATA_FORK); xfs_iext_insert(ifp, idx + 1, 2, &r[0]); 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, PREV.br_startoff, PREV.br_startblock, PREV.br_blockcount, &i))) goto done; ASSERT(i == 1); /* new right extent - oldext */ if ((error = xfs_bmbt_update(cur, r[1].br_startoff, r[1].br_startblock, r[1].br_blockcount, r[1].br_state))) goto done; /* new left extent - oldext */ PREV.br_blockcount = new->br_startoff - PREV.br_startoff; cur->bc_rec.b = PREV; if ((error = xfs_bmbt_insert(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_increment(cur, 0, &i))) goto done; ASSERT(i == 1); /* new middle extent - newext */ 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 three. */ temp = PREV.br_startoff; temp2 = PREV.br_blockcount; break; case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): case MASK2(LEFT_FILLING, RIGHT_CONTIG): case MASK2(RIGHT_FILLING, LEFT_CONTIG): case MASK2(LEFT_CONTIG, RIGHT_CONTIG): case MASK(LEFT_CONTIG): case MASK(RIGHT_CONTIG): /* * These cases are all impossible. */ 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 a hole * to a delayed allocation. *//*ARGSUSED*/STATIC int /* error */xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ 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 */ int rsvd) /* OK to allocate reserved blocks */{ xfs_bmbt_rec_host_t *ep; /* extent record for idx */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_filblks_t newlen=0; /* new indirect size */ xfs_filblks_t oldlen=0; /* old indirect size */ xfs_bmbt_irec_t right; /* right neighbor extent entry */ int state; /* state bits, accessed thru macros */ xfs_filblks_t temp=0; /* temp for indirect calculations */ xfs_filblks_t temp2=0; enum { /* bit number definitions for state */ LEFT_CONTIG, RIGHT_CONTIG, LEFT_DELAY, RIGHT_DELAY, LEFT_VALID, RIGHT_VALID };#define MASK(b) (1 << (b))#define MASK2(a,b) (MASK(a) | MASK(b))#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 & MASK2(LEFT_CONTIG, RIGHT_CONTIG)) ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); ep = xfs_iext_get_ext(ifp, idx); state = 0; ASSERT(ISNULLSTARTBLOCK(new->br_startblock)); /* * Check and set flags if this segment has a left neighbor */ 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)); } /* * Check and set flags if the current (right) segment exists. * If it doesn't exist, we're converting the hole at end-of-file. */ if (STATE_SET_TEST(RIGHT_VALID, idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) { xfs_bmbt_get_all(ep, &right); STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock)); } /* * Set contiguity flags on the left and right neighbors. * Don't let extents get too large, even if the pieces are contiguous. */ STATE_SET(LEFT_CONTIG, STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) && left.br_startoff + left.br_blockcount == new->br_startoff && left.br_blockcount + new->br_blockcount <= MAXEXTLEN); STATE_SET(RIGHT_CONTIG, STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) && new->br_startoff + new->br_blockcount == right.br_startoff && new->br_blockcount + right.br_blockcount <= MAXEXTLEN && (!STATE_TEST(LEFT_CONTIG) || (left.br_blockcount + new->br_blockcount + right.br_blockcount <= MAXEXTLEN))); /* * Switch out based on the contiguity flags. */ switch (SWITCH_STATE) { case MASK2(LEFT_CONTIG, RIGHT_CONTIG): /* * New allocation is contiguous with delayed allocations * on the left and on the right. * Merge all three into a single extent record. */ temp = left.br_blockcount + new->br_blockcount + right.br_blockcount; XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1, XFS_DATA_FORK); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp); oldlen = STARTBLOCKVAL(left.br_startblock) + STARTBLOCKVAL(new->br_startblock) + STARTBLOCKVAL(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1), NULLSTARTBLOCK((int)newlen)); XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1, XFS_DATA_FORK); XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK); xfs_iext_remove(ifp, idx, 1); ip->i_df.if_lastex = idx - 1; /* DELTA: Two in-core extents were replaced by one. */ temp2 = temp; temp = left.br_startoff; break; case MASK(LEFT_CONTIG): /* * New allocation is contiguous with a delayed allocation * on the left. * Merge the new allocation with the left neighbor. */ temp = left.br_blockcount + new->br_blockcount; XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, XFS_DATA_FORK); xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp); oldlen = STARTBLOCKVAL(left.br_startblock) + STARTBLOCKVAL(new->br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1), NULLSTARTBLOCK((int)newlen)); XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; /* DELTA: One in-core extent grew into a hole. */ temp2 = temp; temp = left.br_startoff; break; case MASK(RIGHT_CONTIG): /* * New allocation is contiguous with a delayed allocation * on the right. * Merge the new allocation with the right neighbor. */ XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK); temp = new->br_blockcount + right.br_blockcount; oldlen = STARTBLOCKVAL(new->br_startblock) + STARTBLOCKVAL(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); xfs_bmbt_set_allf(ep, new->br_startoff, NULLSTARTBLOCK((int)newlen), temp, right.br_state); XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK); ip->i_df.if_lastex = idx; /* DELTA: One in-core extent grew into a hole. */ temp2 = temp; temp = new->br_startoff; break; case 0: /* * New allocation is not contiguous with another * delayed allocation. * Insert a new entry. */ oldlen = newlen = 0; XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, XFS_DATA_FORK); xfs_iext_insert(ifp, idx, 1, new); ip->i_df.if_lastex = idx; /* DELTA: A new in-core extent was added in a hole. */ temp2 = new->br_blockcount; temp = new->br_startoff; break; } if (oldlen != newlen) { ASSERT(oldlen > newlen); xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, (int64_t)(oldlen - newlen), rsvd); /* * Nothing to do for disk quota accounting here. */ } if (delta) { temp2 += temp; if (delta->xed_startoff > temp) delta->xed_startoff = temp; if (delta->xed_blockcount < temp2) delta->xed_blockcount = temp2; } *logflagsp = 0; return 0;#undef MASK#undef MASK2#undef STATE_SET#undef STATE_TEST#undef STATE_SET_TEST#undef SWITCH_STATE}/* * Called by xfs_bmap_add_extent to handle cases converting a hole * to a real allocation. */STATIC int /* error */xfs_bmap_add_extent_hole_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if 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 */ int whichfork) /* data or attr fork */{ xfs_bmbt_rec_host_t *ep; /* pointer to extent entry ins. point */ int error; /* error return value */ int i; /* temp state */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_bmbt_irec_t right; /* right neighbor extent entry */ int rval=0; /* return value (logging flags) */ int state; /* 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_DELAY, RIGHT_DELAY, LEFT_VALID, RIGHT_VALID };#define MASK(b) (1 << (b))#define MASK2(a,b) (MASK(a) | MASK(b))#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 & MASK2(LEFT_CONTIG, RIGHT_CONTIG)) ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); ep = xfs_iext_get_ext(ifp, idx); state = 0; /* * Check and set flags if this segment has a left neighbor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -