From 3b0d99289a8e473b059605a83d4ce0bd505ec3d3 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Sun, 8 Apr 2018 19:41:15 -0700 Subject: [PATCH] Fix 'zfs send/recv' hang with 16M blocks When using 16MB blocks the send/recv queue's aren't quite big enough. This change leaves the default 16M queue size which a good value for most pools. But it additionally ensures that the queue sizes are at least twice the allowed zfs_max_recordsize. Reviewed-by: loli10K Signed-off-by: Brian Behlendorf Closes #7365 Closes #7404 --- man/man5/zfs-module-parameters.5 | 25 +++++++++++++++++++++++++ module/zfs/dmu_send.c | 16 ++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/man/man5/zfs-module-parameters.5 b/man/man5/zfs-module-parameters.5 index f7db35b19e..e3c6dd91a5 100644 --- a/man/man5/zfs-module-parameters.5 +++ b/man/man5/zfs-module-parameters.5 @@ -1919,6 +1919,31 @@ Allow sending of corrupt data (ignore read/checksum errors when sending data) Use \fB1\fR for yes and \fB0\fR for no (default). .RE +.sp +.ne 2 +.na +\fBzfs_send_queue_length\fR (int) +.ad +.RS 12n +The maximum number of bytes allowed in the \fBzfs send\fR queue. This value +must be at least twice the maximum block size in use. +.sp +Default value: \fB16,777,216\fR. +.RE + +.sp +.ne 2 +.na +\fBzfs_recv_queue_length\fR (int) +.ad +.RS 12n +.sp +The maximum number of bytes allowed in the \fBzfs receive\fR queue. This value +must be at least twice the maximum block size in use. +.sp +Default value: \fB16,777,216\fR. +.RE + .sp .ne 2 .na diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index e0e5fe22c3..a007e96baa 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -61,8 +61,8 @@ /* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */ int zfs_send_corrupt_data = B_FALSE; -int zfs_send_queue_length = 16 * 1024 * 1024; -int zfs_recv_queue_length = 16 * 1024 * 1024; +int zfs_send_queue_length = SPA_MAXBLOCKSIZE; +int zfs_recv_queue_length = SPA_MAXBLOCKSIZE; /* Set this tunable to FALSE to disable setting of DRR_FLAG_FREERECORDS */ int zfs_send_set_freerecords_bit = B_TRUE; @@ -1142,7 +1142,8 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *to_ds, goto out; } - err = bqueue_init(&to_arg.q, zfs_send_queue_length, + err = bqueue_init(&to_arg.q, + MAX(zfs_send_queue_length, 2 * zfs_max_recordsize), offsetof(struct send_block_record, ln)); to_arg.error_code = 0; to_arg.cancel = B_FALSE; @@ -3831,7 +3832,8 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp, goto out; } - (void) bqueue_init(&rwa->q, zfs_recv_queue_length, + (void) bqueue_init(&rwa->q, + MAX(zfs_recv_queue_length, 2 * zfs_max_recordsize), offsetof(struct receive_record_arg, node)); cv_init(&rwa->cv, NULL, CV_DEFAULT, NULL); mutex_init(&rwa->mutex, NULL, MUTEX_DEFAULT, NULL); @@ -4242,4 +4244,10 @@ dmu_objset_is_receiving(objset_t *os) #if defined(_KERNEL) module_param(zfs_send_corrupt_data, int, 0644); MODULE_PARM_DESC(zfs_send_corrupt_data, "Allow sending corrupt data"); + +module_param(zfs_send_queue_length, int, 0644); +MODULE_PARM_DESC(zfs_send_queue_length, "Maximum send queue length"); + +module_param(zfs_recv_queue_length, int, 0644); +MODULE_PARM_DESC(zfs_recv_queue_length, "Maximum receive queue length"); #endif