Commit 29b3e94a authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong

xfs: rewrite xfs_bmap_first_unused to make better use of xfs_iext_get_extent

Look at the return value of xfs_iext_get_extent instead of figuring out
the extent count first and looping up to it.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 5936dc54
...@@ -1285,57 +1285,53 @@ xfs_bmap_read_extents( ...@@ -1285,57 +1285,53 @@ xfs_bmap_read_extents(
} }
/* /*
* Returns the file-relative block number of the first unused block(s) * Returns the relative block number of the first unused block(s) in the given
* in the file with at least "len" logically contiguous blocks free. * fork with at least "len" logically contiguous blocks free. This is the
* This is the lowest-address hole if the file has holes, else the first block * lowest-address hole if the fork has holes, else the first block past the end
* past the end of file. * of fork. Return 0 if the fork is currently local (in-inode).
* Return 0 if the file is currently local (in-inode).
*/ */
int /* error */ int /* error */
xfs_bmap_first_unused( xfs_bmap_first_unused(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode */ struct xfs_inode *ip, /* incore inode */
xfs_extlen_t len, /* size of hole to find */ xfs_extlen_t len, /* size of hole to find */
xfs_fileoff_t *first_unused, /* unused block */ xfs_fileoff_t *first_unused, /* unused block */
int whichfork) /* data or attr fork */ int whichfork) /* data or attr fork */
{ {
int error; /* error return value */ struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
int idx; /* extent record index */ struct xfs_bmbt_irec got;
xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extnum_t idx = 0;
xfs_fileoff_t lastaddr; /* last block number seen */ xfs_fileoff_t lastaddr = 0;
xfs_fileoff_t lowest; /* lowest useful block */ xfs_fileoff_t lowest, max;
xfs_fileoff_t max; /* starting useful block */ int error;
xfs_extnum_t nextents; /* number of extent entries */
ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE || ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS || XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
*first_unused = 0; *first_unused = 0;
return 0; return 0;
} }
ifp = XFS_IFORK_PTR(ip, whichfork);
if (!(ifp->if_flags & XFS_IFEXTENTS) &&
(error = xfs_iread_extents(tp, ip, whichfork)))
return error;
lowest = *first_unused;
nextents = xfs_iext_count(ifp);
for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
struct xfs_bmbt_irec got;
xfs_iext_get_extent(ifp, idx, &got); if (!(ifp->if_flags & XFS_IFEXTENTS)) {
error = xfs_iread_extents(tp, ip, whichfork);
if (error)
return error;
}
lowest = max = *first_unused;
while (xfs_iext_get_extent(ifp, idx++, &got)) {
/* /*
* See if the hole before this extent will work. * See if the hole before this extent will work.
*/ */
if (got.br_startoff >= lowest + len && if (got.br_startoff >= lowest + len &&
got.br_startoff - max >= len) { got.br_startoff - max >= len)
*first_unused = max; break;
return 0;
}
lastaddr = got.br_startoff + got.br_blockcount; lastaddr = got.br_startoff + got.br_blockcount;
max = XFS_FILEOFF_MAX(lastaddr, lowest); max = XFS_FILEOFF_MAX(lastaddr, lowest);
} }
*first_unused = max; *first_unused = max;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment