From f00dc4d4b33739c4549296b81dd2ed7307c8418c Mon Sep 17 00:00:00 2001 From: mav Date: Thu, 25 Sep 2014 09:11:01 +0000 Subject: [PATCH] MFC r271949: Fix UNMAP stuck if the last block descriptor in the list is empty. Approved by: re (glebius) git-svn-id: svn://svn.freebsd.org/base/stable/10@272100 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/cam/ctl/ctl.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index b6531e7f2..243295d16 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -6039,7 +6039,7 @@ ctl_unmap(struct ctl_scsiio *ctsio) struct scsi_unmap *cdb; struct ctl_ptr_len_flags *ptrlen; struct scsi_unmap_header *hdr; - struct scsi_unmap_desc *buf, *end; + struct scsi_unmap_desc *buf, *end, *endnz, *range; uint64_t lba; uint32_t num_blocks; int len, retval; @@ -6092,24 +6092,38 @@ ctl_unmap(struct ctl_scsiio *ctsio) buf = (struct scsi_unmap_desc *)(hdr + 1); end = buf + len / sizeof(*buf); - ptrlen = (struct ctl_ptr_len_flags *)&ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN]; - ptrlen->ptr = (void *)buf; - ptrlen->len = len; - ptrlen->flags = byte2; - - for (; buf < end; buf++) { - lba = scsi_8btou64(buf->lba); - num_blocks = scsi_4btoul(buf->length); + endnz = buf; + for (range = buf; range < end; range++) { + lba = scsi_8btou64(range->lba); + num_blocks = scsi_4btoul(range->length); if (((lba + num_blocks) > (lun->be_lun->maxlba + 1)) || ((lba + num_blocks) < lba)) { ctl_set_lba_out_of_range(ctsio); ctl_done((union ctl_io *)ctsio); return (CTL_RETVAL_COMPLETE); } + if (num_blocks != 0) + endnz = range + 1; } - retval = lun->backend->config_write((union ctl_io *)ctsio); + /* + * Block backend can not handle zero last range. + * Filter it out and return if there is nothing left. + */ + len = (uint8_t *)endnz - (uint8_t *)buf; + if (len == 0) { + ctl_set_success(ctsio); + ctl_done((union ctl_io *)ctsio); + return (CTL_RETVAL_COMPLETE); + } + + ptrlen = (struct ctl_ptr_len_flags *) + &ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN]; + ptrlen->ptr = (void *)buf; + ptrlen->len = len; + ptrlen->flags = byte2; + retval = lun->backend->config_write((union ctl_io *)ctsio); return (retval); } -- 2.45.0