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 <ezomori.nozomu@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #7365
Closes #7404
This commit is contained in:
Brian Behlendorf 2018-04-08 19:41:15 -07:00 committed by Tony Hutter
parent 8bb800d6b4
commit 7440f10ec1
2 changed files with 37 additions and 4 deletions

View File

@ -1763,6 +1763,31 @@ Allow sending of corrupt data (ignore read/checksum errors when sending data)
Use \fB1\fR for yes and \fB0\fR for no (default). Use \fB1\fR for yes and \fB0\fR for no (default).
.RE .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 .sp
.ne 2 .ne 2
.na .na

View File

@ -61,8 +61,8 @@
/* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */ /* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
int zfs_send_corrupt_data = B_FALSE; int zfs_send_corrupt_data = B_FALSE;
int zfs_send_queue_length = 16 * 1024 * 1024; int zfs_send_queue_length = SPA_MAXBLOCKSIZE;
int zfs_recv_queue_length = 16 * 1024 * 1024; int zfs_recv_queue_length = SPA_MAXBLOCKSIZE;
/* Set this tunable to FALSE to disable setting of DRR_FLAG_FREERECORDS */ /* Set this tunable to FALSE to disable setting of DRR_FLAG_FREERECORDS */
int zfs_send_set_freerecords_bit = B_TRUE; int zfs_send_set_freerecords_bit = B_TRUE;
@ -944,7 +944,8 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *to_ds,
goto out; 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)); offsetof(struct send_block_record, ln));
to_arg.error_code = 0; to_arg.error_code = 0;
to_arg.cancel = B_FALSE; to_arg.cancel = B_FALSE;
@ -3173,7 +3174,8 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
goto out; 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)); offsetof(struct receive_record_arg, node));
cv_init(&rwa->cv, NULL, CV_DEFAULT, NULL); cv_init(&rwa->cv, NULL, CV_DEFAULT, NULL);
mutex_init(&rwa->mutex, NULL, MUTEX_DEFAULT, NULL); mutex_init(&rwa->mutex, NULL, MUTEX_DEFAULT, NULL);
@ -3550,4 +3552,10 @@ dmu_objset_is_receiving(objset_t *os)
#if defined(_KERNEL) #if defined(_KERNEL)
module_param(zfs_send_corrupt_data, int, 0644); module_param(zfs_send_corrupt_data, int, 0644);
MODULE_PARM_DESC(zfs_send_corrupt_data, "Allow sending corrupt data"); 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 #endif