📄 xfs_rtalloc.c
字号:
if (i >= 0) { /* * Try to allocate an extent starting in * this block. */ error = xfs_rtallocate_extent_block(mp, tp, bbno + i, minlen, maxlen, len, &n, rbpp, rsb, prod, &r); if (error) { return error; } /* * If it worked, return it. */ if (r != NULLRTBLOCK) { *rtblock = r; return 0; } } /* * On the negative side of the starting location. */ else { /* i < 0 */ /* * Loop backwards through the bitmap blocks from * the starting point-1 up to where we are now. * There should be an extent which ends in this * bitmap block and is long enough. */ for (j = -1; j > i; j--) { /* * Grab the summary information for * this bitmap block. */ error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1, bbno + j, rbpp, rsb, &any); if (error) { return error; } /* * If there's no extent given in the * summary that means the extent we * found must carry over from an * earlier block. If there is an * extent given, we've already tried * that allocation, don't do it again. */ if (any) continue; error = xfs_rtallocate_extent_block(mp, tp, bbno + j, minlen, maxlen, len, &n, rbpp, rsb, prod, &r); if (error) { return error; } /* * If it works, return the extent. */ if (r != NULLRTBLOCK) { *rtblock = r; return 0; } } /* * There weren't intervening bitmap blocks * with a long enough extent, or the * allocation didn't work for some reason * (i.e. it's a little * too short). * Try to allocate from the summary block * that we found. */ error = xfs_rtallocate_extent_block(mp, tp, bbno + i, minlen, maxlen, len, &n, rbpp, rsb, prod, &r); if (error) { return error; } /* * If it works, return the extent. */ if (r != NULLRTBLOCK) { *rtblock = r; return 0; } } } /* * Loop control. If we were on the positive side, and there's * still more blocks on the negative side, go there. */ if (i > 0 && (int)bbno - i >= 0) i = -i; /* * If positive, and no more negative, but there are more * positive, go there. */ else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1) i++; /* * If negative or 0 (just started), and there are positive * blocks to go, go there. The 0 case moves to block 1. */ else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1) i = 1 - i; /* * If negative or 0 and there are more negative blocks, * go there. */ else if (i <= 0 && (int)bbno + i > 0) i--; /* * Must be done. Return failure. */ else break; } *rtblock = NULLRTBLOCK; return 0;}/* * Allocate an extent of length minlen<=len<=maxlen, with no position * specified. If we don't get maxlen then use prod to trim * the length, if given. The lengths are all in rtextents. */STATIC int /* error */xfs_rtallocate_extent_size( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_extlen_t minlen, /* minimum length to allocate */ xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_extlen_t *len, /* out: actual length allocated */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb, /* in/out: summary block number */ xfs_extlen_t prod, /* extent product factor */ xfs_rtblock_t *rtblock) /* out: start block allocated */{ int error; /* error value */ int i; /* bitmap block number */ int l; /* level number (loop control) */ xfs_rtblock_t n; /* next block to be tried */ xfs_rtblock_t r; /* result block number */ xfs_suminfo_t sum; /* summary information for extents */ ASSERT(minlen % prod == 0 && maxlen % prod == 0); /* * Loop over all the levels starting with maxlen. * At each level, look at all the bitmap blocks, to see if there * are extents starting there that are long enough (>= maxlen). * Note, only on the initial level can the allocation fail if * the summary says there's an extent. */ for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) { /* * Loop over all the bitmap blocks. */ for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) { /* * Get the summary for this level/block. */ error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, &sum); if (error) { return error; } /* * Nothing there, on to the next block. */ if (!sum) continue; /* * Try allocating the extent. */ error = xfs_rtallocate_extent_block(mp, tp, i, maxlen, maxlen, len, &n, rbpp, rsb, prod, &r); if (error) { return error; } /* * If it worked, return that. */ if (r != NULLRTBLOCK) { *rtblock = r; return 0; } /* * If the "next block to try" returned from the * allocator is beyond the next bitmap block, * skip to that bitmap block. */ if (XFS_BITTOBLOCK(mp, n) > i + 1) i = XFS_BITTOBLOCK(mp, n) - 1; } } /* * Didn't find any maxlen blocks. Try smaller ones, unless * we're asking for a fixed size extent. */ if (minlen > --maxlen) { *rtblock = NULLRTBLOCK; return 0; } /* * Loop over sizes, from maxlen down to minlen. * This time, when we do the allocations, allow smaller ones * to succeed. */ for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) { /* * Loop over all the bitmap blocks, try an allocation * starting in that block. */ for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) { /* * Get the summary information for this level/block. */ error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, &sum); if (error) { return error; } /* * If nothing there, go on to next. */ if (!sum) continue; /* * Try the allocation. Make sure the specified * minlen/maxlen are in the possible range for * this summary level. */ error = xfs_rtallocate_extent_block(mp, tp, i, XFS_RTMAX(minlen, 1 << l), XFS_RTMIN(maxlen, (1 << (l + 1)) - 1), len, &n, rbpp, rsb, prod, &r); if (error) { return error; } /* * If it worked, return that extent. */ if (r != NULLRTBLOCK) { *rtblock = r; return 0; } /* * If the "next block to try" returned from the * allocator is beyond the next bitmap block, * skip to that bitmap block. */ if (XFS_BITTOBLOCK(mp, n) > i + 1) i = XFS_BITTOBLOCK(mp, n) - 1; } } /* * Got nothing, return failure. */ *rtblock = NULLRTBLOCK; return 0;}/* * Mark an extent specified by start and len allocated. * Updates all the summary information as well as the bitmap. */STATIC int /* error */xfs_rtallocate_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* start block to allocate */ xfs_extlen_t len, /* length to allocate */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb) /* in/out: summary block number */{ xfs_rtblock_t end; /* end of the allocated extent */ int error; /* error value */ xfs_rtblock_t postblock; /* first block allocated > end */ xfs_rtblock_t preblock; /* first block allocated < start */ end = start + len - 1; /* * Assume we're allocating out of the middle of a free extent. * We need to find the beginning and end of the extent so we can * properly update the summary. */ error = xfs_rtfind_back(mp, tp, start, 0, &preblock); if (error) { return error; } /* * Find the next allocated block (end of free extent). */ error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, &postblock); if (error) { return error; } /* * Decrement the summary information corresponding to the entire * (old) free extent. */ error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); if (error) { return error; } /* * If there are blocks not being allocated at the front of the * old extent, add summary data for them to be free. */ if (preblock < start) { error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(start - preblock), XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); if (error) { return error; } } /* * If there are blocks not being allocated at the end of the * old extent, add summary data for them to be free. */ if (postblock > end) { error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(postblock - end), XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); if (error) { return error; } } /* * Modify the bitmap to mark this extent allocated. */ error = xfs_rtmodify_range(mp, tp, start, len, 0); return error;}/* * Return whether there are any free extents in the size range given * by low and high, for the bitmap block bbno. */STATIC int /* error */xfs_rtany_summary( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ int low, /* low log2 extent size */ int high, /* high log2 extent size */ xfs_rtblock_t bbno, /* bitmap block number */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb, /* in/out: summary block number */ int *stat) /* out: any good extents here? */{ int error; /* error value */ int log; /* loop counter, log2 of ext. size */ xfs_suminfo_t sum; /* summary data */ /* * Loop over logs of extent sizes. Order is irrelevant. */ for (log = low; log <= high; log++) { /* * Get one summary datum. */ error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); if (error) { return error; } /* * If there are any, return success. */ if (sum) { *stat = 1; return 0; } } /* * Found nothing, return failure. */ *stat = 0; return 0;}/* * Get a buffer for the bitmap or summary file block specified. * The buffer is returned read and locked. */STATIC int /* error */xfs_rtbuf_get( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t block, /* block number in bitmap or summary */ int issum, /* is summary not bitmap */ xfs_buf_t **bpp) /* output: buffer for the block */{ xfs_buf_t *bp; /* block buffer, result */ xfs_daddr_t d; /* disk addr of block */ int error; /* error value */ xfs_fsblock_t fsb; /* fs block number for block */ xfs_inode_t *ip; /* bitmap or summary inode */ ip = issum ? mp->m_rsumip : mp->m_rbmip; /* * Map from the file offset (block) and inode number to the * file system block. */ error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block); if (error) { return error; } ASSERT(fsb != NULLFSBLOCK); /* * Convert to disk address for buffer cache. */ d = XFS_FSB_TO_DADDR(mp, fsb); /* * Read the buffer. */ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, mp->m_bsize, 0, &bp); if (error) { return error; } ASSERT(bp && !XFS_BUF_GETERROR(bp)); *bpp = bp; return 0;}#ifdef DEBUG/* * Check that the given extent (block range) is allocated already. */STATIC int /* error */xfs_rtcheck_alloc_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ int *stat) /* out: 1 for allocated, 0 for not */{ xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);}#endif/* * Check that the given range is either all allocated (val = 0) or * all free (val = 1). */STATIC int /* error */xfs_rtcheck_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ int val, /* 1 for free, 0 for allocated */ xfs_rtblock_t *new, /* out: first block not matching */ int *stat) /* out: 1 for matches, 0 for not */{ xfs_rtword_t *b; /* current word in buffer */ int bit; /* bit number in the word */ xfs_rtblock_t block; /* bitmap block number */ xfs_buf_t *bp; /* buf for the block */ xfs_rtword_t *bufp; /* starting word in buffer */ int error; /* error value */ xfs_rtblock_t i; /* current bit number rel. to start */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -