diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index df9538e57dcb..c75b8c1b114e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -370,6 +370,15 @@ thin_provisioning_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(thin_provisioning);
 
+static ssize_t
+ndob_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+	return sprintf(buf, "%u\n", sdkp->ndob);
+}
+static DEVICE_ATTR_RO(ndob);
+
 /* sysfs_match_string() requires dense arrays */
 static const char *lbp_mode[] = {
 	[SD_LBP_FULL]		= "full",
@@ -533,6 +542,7 @@ static struct attribute *sd_disk_attrs[] = {
 	&dev_attr_app_tag_own.attr,
 	&dev_attr_thin_provisioning.attr,
 	&dev_attr_provisioning_mode.attr,
+	&dev_attr_ndob.attr,
 	&dev_attr_zeroing_mode.attr,
 	&dev_attr_max_write_same_blocks.attr,
 	&dev_attr_max_medium_access_timeouts.attr,
@@ -852,27 +862,38 @@ static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
 {
 	struct scsi_device *sdp = cmd->device;
 	struct request *rq = cmd->request;
+	struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
 	u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
 	u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
 	u32 data_len = sdp->sector_size;
 
-	rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
-	if (!rq->special_vec.bv_page)
-		return BLK_STS_RESOURCE;
-	clear_highpage(rq->special_vec.bv_page);
+	if (unmap && sdkp->ndob) {
+		rq->special_vec.bv_page = NULL;
+		rq->special_vec.bv_len = 0;
+	} else {
+		rq->special_vec.bv_page =
+			mempool_alloc(sd_page_pool, GFP_ATOMIC);
+		if (!rq->special_vec.bv_page)
+			return BLK_STS_RESOURCE;
+		clear_highpage(rq->special_vec.bv_page);
+		rq->special_vec.bv_len = data_len;
+	}
+
 	rq->special_vec.bv_offset = 0;
-	rq->special_vec.bv_len = data_len;
 	rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
 
 	cmd->cmd_len = 16;
 	cmd->cmnd[0] = WRITE_SAME_16;
-	if (unmap)
+	if (unmap) {
 		cmd->cmnd[1] = 0x8; /* UNMAP */
+		if (sdkp->ndob)
+			cmd->cmnd[1] |= 0x1; /* NDOB */
+	}
 	put_unaligned_be64(lba, &cmd->cmnd[2]);
 	put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
 
 	cmd->allowed = SD_MAX_RETRIES;
-	cmd->transfersize = data_len;
+	cmd->transfersize = rq->special_vec.bv_len;
 	rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT;
 
 	return scsi_init_io(cmd);
@@ -1297,7 +1318,7 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
 	struct request *rq = SCpnt->request;
 	u8 *cmnd;
 
-	if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
+	if (rq->rq_flags & RQF_SPECIAL_PAYLOAD && SCpnt->transfersize)
 		mempool_free(rq->special_vec.bv_page, sd_page_pool);
 
 	if (SCpnt->cmnd != scsi_req(rq)->cmd) {
@@ -2984,7 +3005,9 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp, unsigned char
  */
 static void sd_read_block_provisioning(struct scsi_disk *sdkp, unsigned char *buffer)
 {
-	const int vpd_len = 8;
+	struct scsi_device *sdev = sdkp->device;
+	const unsigned int vpd_len = 8;
+	const unsigned int rsoc_len = 20;
 
 	if (sdkp->lbpme == 0)
 		return;
@@ -2996,6 +3019,18 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp, unsigned char *bu
 	sdkp->lbpu	= (buffer[5] >> 7) & 1;	/* UNMAP */
 	sdkp->lbpws	= (buffer[5] >> 6) & 1;	/* WRITE SAME(16) with UNMAP */
 	sdkp->lbpws10	= (buffer[5] >> 5) & 1;	/* WRITE SAME(10) with UNMAP */
+
+	if (!sdkp->lbpws)
+		return;
+	/*
+	 * We assume that if a device supports the Block Provisioning
+	 * VPD page, it is smart enough to implement Report Supported
+	 * Operation Codes. We use that operation to determine whether
+	 * the NDOB bit is supported for WRITE SAME(16).
+	 */
+	if (scsi_report_opcode(sdev, buffer, rsoc_len, WRITE_SAME_16) == 1 &&
+	    get_unaligned_be16(&buffer[2]) >= 2)
+		sdkp->ndob = buffer[5] & 1;
 }
 
 static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 5796ace76225..fda6ad03e02d 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -111,6 +111,7 @@ struct scsi_disk {
 	unsigned	lbpvpd : 1;
 	unsigned	ws10 : 1;
 	unsigned	ws16 : 1;
+	unsigned	ndob : 1;
 	unsigned	rc_basis: 2;
 	unsigned	zoned: 2;
 	unsigned	urswrz : 1;
