mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
OpenZFS 6531 - Provide mechanism to artificially limit disk performance
Reviewed by: Paul Dagnelie <pcd@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Approved by: Dan McDonald <danmcd@omniti.com> Ported by: Tony Hutter <hutter2@llnl.gov> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> OpenZFS-issue: https://www.illumos.org/issues/6531 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/97e8130 Porting notes: - Added new IO delay tracepoints, and moved common ZIO tracepoint macros to a new trace_common.h file. - Used zio_delay_taskq() in place of OpenZFS's timeout_generic() function. - Updated zinject man page - Updated zpool_scrub test files
This commit is contained in:
committed by
Brian Behlendorf
parent
7e945072d1
commit
26ef0cc7db
@@ -40,6 +40,7 @@
|
||||
#include <sys/blkptr.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/trace_zio.h>
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
@@ -1390,6 +1391,76 @@ zio_interrupt(zio_t *zio)
|
||||
zio_taskq_dispatch(zio, ZIO_TASKQ_INTERRUPT, B_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
zio_delay_interrupt(zio_t *zio)
|
||||
{
|
||||
/*
|
||||
* The timeout_generic() function isn't defined in userspace, so
|
||||
* rather than trying to implement the function, the zio delay
|
||||
* functionality has been disabled for userspace builds.
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* If io_target_timestamp is zero, then no delay has been registered
|
||||
* for this IO, thus jump to the end of this function and "skip" the
|
||||
* delay; issuing it directly to the zio layer.
|
||||
*/
|
||||
if (zio->io_target_timestamp != 0) {
|
||||
hrtime_t now = gethrtime();
|
||||
|
||||
if (now >= zio->io_target_timestamp) {
|
||||
/*
|
||||
* This IO has already taken longer than the target
|
||||
* delay to complete, so we don't want to delay it
|
||||
* any longer; we "miss" the delay and issue it
|
||||
* directly to the zio layer. This is likely due to
|
||||
* the target latency being set to a value less than
|
||||
* the underlying hardware can satisfy (e.g. delay
|
||||
* set to 1ms, but the disks take 10ms to complete an
|
||||
* IO request).
|
||||
*/
|
||||
|
||||
DTRACE_PROBE2(zio__delay__miss, zio_t *, zio,
|
||||
hrtime_t, now);
|
||||
|
||||
zio_interrupt(zio);
|
||||
} else {
|
||||
taskqid_t tid;
|
||||
hrtime_t diff = zio->io_target_timestamp - now;
|
||||
clock_t expire_at_tick = ddi_get_lbolt() +
|
||||
NSEC_TO_TICK(diff);
|
||||
|
||||
DTRACE_PROBE3(zio__delay__hit, zio_t *, zio,
|
||||
hrtime_t, now, hrtime_t, diff);
|
||||
|
||||
if (NSEC_TO_TICK(diff) == 0) {
|
||||
/* Our delay is less than a jiffy - just spin */
|
||||
zfs_sleep_until(zio->io_target_timestamp);
|
||||
} else {
|
||||
/*
|
||||
* Use taskq_dispatch_delay() in the place of
|
||||
* OpenZFS's timeout_generic().
|
||||
*/
|
||||
tid = taskq_dispatch_delay(system_taskq,
|
||||
(task_func_t *) zio_interrupt,
|
||||
zio, TQ_NOSLEEP, expire_at_tick);
|
||||
if (!tid) {
|
||||
/*
|
||||
* Couldn't allocate a task. Just
|
||||
* finish the zio without a delay.
|
||||
*/
|
||||
zio_interrupt(zio);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DTRACE_PROBE1(zio__delay__skip, zio_t *, zio);
|
||||
zio_interrupt(zio);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the I/O pipeline until one of the following occurs:
|
||||
* (1) the I/O completes; (2) the pipeline stalls waiting for
|
||||
|
||||
Reference in New Issue
Block a user