Commit 15f04fdc authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: remove infinite loop when reserving free block pool

Infinite loops in kernel code are scary.  Calls to xfs_reserve_blocks
should be rare (people should just use the defaults!) so we really don't
need to try so hard.  Simplify the logic here by removing the infinite
loop.

Cc: Brian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent c8c56825
...@@ -430,46 +430,36 @@ xfs_reserve_blocks( ...@@ -430,46 +430,36 @@ xfs_reserve_blocks(
* If the request is larger than the current reservation, reserve the * If the request is larger than the current reservation, reserve the
* blocks before we update the reserve counters. Sample m_fdblocks and * blocks before we update the reserve counters. Sample m_fdblocks and
* perform a partial reservation if the request exceeds free space. * perform a partial reservation if the request exceeds free space.
*
* The code below estimates how many blocks it can request from
* fdblocks to stash in the reserve pool. This is a classic TOCTOU
* race since fdblocks updates are not always coordinated via
* m_sb_lock.
*/ */
error = -ENOSPC;
do {
free = percpu_counter_sum(&mp->m_fdblocks) - free = percpu_counter_sum(&mp->m_fdblocks) -
xfs_fdblocks_unavailable(mp); xfs_fdblocks_unavailable(mp);
if (free <= 0)
break;
delta = request - mp->m_resblks; delta = request - mp->m_resblks;
lcounter = free - delta; if (delta > 0 && free > 0) {
if (lcounter < 0)
/* We can't satisfy the request, just get what we can */
fdblks_delta = free;
else
fdblks_delta = delta;
/* /*
* We'll either succeed in getting space from the free block * We'll either succeed in getting space from the free block
* count or we'll get an ENOSPC. If we get a ENOSPC, it means * count or we'll get an ENOSPC. Don't set the reserved flag
* things changed while we were calculating fdblks_delta and so * here - we don't want to reserve the extra reserve blocks
* we should try again to see if there is anything left to * from the reserve.
* reserve.
*
* Don't set the reserved flag here - we don't want to reserve
* the extra reserve blocks from the reserve.....
*/ */
fdblks_delta = min(free, delta);
spin_unlock(&mp->m_sb_lock); spin_unlock(&mp->m_sb_lock);
error = xfs_mod_fdblocks(mp, -fdblks_delta, 0); error = xfs_mod_fdblocks(mp, -fdblks_delta, 0);
spin_lock(&mp->m_sb_lock); spin_lock(&mp->m_sb_lock);
} while (error == -ENOSPC);
/* /*
* Update the reserve counters if blocks have been successfully * Update the reserve counters if blocks have been successfully
* allocated. * allocated.
*/ */
if (!error && fdblks_delta) { if (!error) {
mp->m_resblks += fdblks_delta; mp->m_resblks += fdblks_delta;
mp->m_resblks_avail += fdblks_delta; mp->m_resblks_avail += fdblks_delta;
} }
}
out: out:
if (outval) { if (outval) {
outval->resblks = mp->m_resblks; outval->resblks = mp->m_resblks;
......
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