Use buf to send speedup

It turns out there's a problem with using g_io to send the speedup. It leads to
a race when there's a resource shortage when a disk fails.

Instead, send BIO_SPEEDUP via struct buf. This is pretty straight forward,
except we need to transfer the bio_flags from b_ioflags for BIO_SPEEDUP commands
in g_vfs_strategy.

Reviewed by: kirk, chs
Differential Revision: https://reviews.freebsd.org/D23117
This commit is contained in:
Warner Losh 2020-01-17 01:16:19 +00:00
parent 8b522bdae6
commit 3cf5dd8401
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=356819
2 changed files with 20 additions and 5 deletions

View file

@ -191,6 +191,8 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp)
bip->bio_flags |= BIO_ORDERED;
bp->b_flags &= ~B_BARRIER;
}
if (bp->b_iocmd == BIO_SPEEDUP)
bip->bio_flags |= bp->b_ioflags;
bip->bio_done = g_vfs_done;
bip->bio_caller2 = bp;
#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)

View file

@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <geom/geom.h>
#include <geom/geom_vfs.h>
#include <ddb/ddb.h>
@ -1452,6 +1453,20 @@ worklist_speedup(mp)
wakeup(&ump->softdep_flushtd);
}
static void
softdep_send_speedup(struct ufsmount *ump, size_t shortage, u_int flags)
{
struct buf *bp;
bp = malloc(sizeof(*bp), M_TRIM, M_WAITOK | M_ZERO);
bp->b_iocmd = BIO_SPEEDUP;
bp->b_ioflags = flags;
bp->b_bcount = shortage;
g_vfs_strategy(ump->um_bo, bp);
bufwait(bp);
free(bp, M_TRIM);
}
static int
softdep_speedup(ump)
struct ufsmount *ump;
@ -13364,7 +13379,6 @@ softdep_request_cleanup(fs, vp, cred, resource)
struct ufsmount *ump;
struct mount *mp;
long starttime;
size_t resid;
ufs2_daddr_t needed;
int error, failed_vnode;
@ -13442,8 +13456,8 @@ softdep_request_cleanup(fs, vp, cred, resource)
retry:
if (resource == FLUSH_BLOCKS_WAIT &&
fs->fs_cstotal.cs_nbfree <= needed)
g_io_speedup(needed * fs->fs_bsize, BIO_SPEEDUP_TRIM, &resid,
ump->um_cp);
softdep_send_speedup(ump, needed * fs->fs_bsize,
BIO_SPEEDUP_TRIM);
if ((resource == FLUSH_BLOCKS_WAIT && ump->softdep_on_worklist > 0 &&
fs->fs_cstotal.cs_nbfree <= needed) ||
(resource == FLUSH_INODES_WAIT && fs->fs_pendinginodes > 0 &&
@ -13757,7 +13771,6 @@ check_clear_deps(mp)
struct mount *mp;
{
struct ufsmount *ump;
size_t resid;
/*
* Tell the lower layers that any TRIM or WRITE transactions
@ -13766,7 +13779,7 @@ check_clear_deps(mp)
*/
ump = VFSTOUFS(mp);
FREE_LOCK(ump);
g_io_speedup(0, BIO_SPEEDUP_TRIM | BIO_SPEEDUP_WRITE, &resid, ump->um_cp);
softdep_send_speedup(ump, 0, BIO_SPEEDUP_TRIM | BIO_SPEEDUP_WRITE);
ACQUIRE_LOCK(ump);