summaryrefslogtreecommitdiffstats
path: root/bin/dd/dd.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2016-02-28 10:27:12 +0000
committertrasz <trasz@FreeBSD.org>2016-02-28 10:27:12 +0000
commit5050f4bc8348f5b3dce257e767153950360d4b3f (patch)
tree233da3f0cc2462266ddb07aecfa08135640ca7fa /bin/dd/dd.c
parentd887d37a7a4f3942aa978daad85a76d2f066923e (diff)
downloadFreeBSD-src-5050f4bc8348f5b3dce257e767153950360d4b3f.zip
FreeBSD-src-5050f4bc8348f5b3dce257e767153950360d4b3f.tar.gz
Add speed limit to dd(1). This is useful for testing RCTL disk io limits
(when they actually get committed, that is), and might also come in handy in other situations. Reviewed by: wblock@ (man page) MFC after: 1 month Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'bin/dd/dd.c')
-rw-r--r--bin/dd/dd.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
index 4c31a5e..56f8efe 100644
--- a/bin/dd/dd.c
+++ b/bin/dd/dd.c
@@ -82,6 +82,7 @@ size_t cbsz; /* conversion block size */
uintmax_t files_cnt = 1; /* # of files to copy */
const u_char *ctab; /* conversion table */
char fill_char; /* Character to fill with if defined */
+size_t speed = 0; /* maximum speed, in bytes per second */
volatile sig_atomic_t need_summary;
int
@@ -276,6 +277,29 @@ getfdtype(IO *io)
io->flags |= ISSEEK;
}
+/*
+ * Limit the speed by adding a delay before every block read.
+ * The delay (t_usleep) is equal to the time computed from block
+ * size and the specified speed limit (t_target) minus the time
+ * spent on actual read and write operations (t_io).
+ */
+static void
+speed_limit(void)
+{
+ static double t_prev, t_usleep;
+ double t_now, t_io, t_target;
+
+ t_now = secs_elapsed();
+ t_io = t_now - t_prev - t_usleep;
+ t_target = (double)in.dbsz / (double)speed;
+ t_usleep = t_target - t_io;
+ if (t_usleep > 0)
+ usleep(t_usleep * 1000000);
+ else
+ t_usleep = 0;
+ t_prev = t_now;
+}
+
static void
dd_in(void)
{
@@ -293,6 +317,9 @@ dd_in(void)
break;
}
+ if (speed > 0)
+ speed_limit();
+
/*
* Zero the buffer first if sync; if doing block operations,
* use spaces.
OpenPOWER on IntegriCloud