Module Name: src
Committed By: jakllsch
Date: Thu Feb 27 17:17:00 UTC 2025
Modified Files:
src/sys/dev/scsipi: scsi_disk.h sd.c sdvar.h
Log Message:
sd(4): Translate discard to UNMAP (10) command
To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/scsipi/scsi_disk.h
cvs rdiff -u -r1.340 -r1.341 src/sys/dev/scsipi/sd.c
cvs rdiff -u -r1.41 -r1.42 src/sys/dev/scsipi/sdvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/scsipi/scsi_disk.h
diff -u src/sys/dev/scsipi/scsi_disk.h:1.37 src/sys/dev/scsipi/scsi_disk.h:1.38
--- src/sys/dev/scsipi/scsi_disk.h:1.37 Thu Feb 27 15:07:45 2025
+++ src/sys/dev/scsipi/scsi_disk.h Thu Feb 27 17:17:00 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: scsi_disk.h,v 1.37 2025/02/27 15:07:45 jakllsch Exp $ */
+/* $NetBSD: scsi_disk.h,v 1.38 2025/02/27 17:17:00 jakllsch Exp $ */
/*
* SCSI-specific interface description
@@ -394,4 +394,39 @@ union scsi_disk_pages {
} control_params;
};
+struct scsi_vpd_logical_block_provisioning {
+ struct {
+/*1*/ u_int8_t device;
+/*2*/ u_int8_t pagecode;
+/*3*/ u_int8_t length[2];
+ };
+/*4*/ u_int8_t threshold_exponent;
+/*5*/ u_int8_t flags;
+#define VPD_LBP_LBPU 0x80
+#define VPD_LBP_LBPWS 0x40
+#define VPD_LBP_LBPWS10 0x20
+/*6*/ u_int8_t reserved6[2];
+} __packed;
+
+#define UNMAP_10 0x42
+struct scsi_unmap_10 {
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t reserved3[4];
+ u_int8_t byte7;
+ u_int8_t length[2];
+ u_int8_t control;
+} __packed;
+
+struct scsi_unmap_10_data {
+ u_int8_t unmap_data_length[2];
+ u_int8_t unmap_block_descriptor_data_length[2];
+ u_int8_t reserved5[4];
+ struct {
+ u_int8_t addr[8];
+ u_int8_t len[4];
+ u_int8_t reserved13[4];
+ } unmap_block_descriptor[1];
+} __packed;
+
#endif /* _DEV_SCSIPI_SCSI_DISK_H_ */
Index: src/sys/dev/scsipi/sd.c
diff -u src/sys/dev/scsipi/sd.c:1.340 src/sys/dev/scsipi/sd.c:1.341
--- src/sys/dev/scsipi/sd.c:1.340 Thu Feb 27 17:03:46 2025
+++ src/sys/dev/scsipi/sd.c Thu Feb 27 17:17:00 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: sd.c,v 1.340 2025/02/27 17:03:46 jakllsch Exp $ */
+/* $NetBSD: sd.c,v 1.341 2025/02/27 17:17:00 jakllsch Exp $ */
/*-
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -47,7 +47,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.340 2025/02/27 17:03:46 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.341 2025/02/27 17:17:00 jakllsch Exp $");
#ifdef _KERNEL_OPT
#include "opt_scsi.h"
@@ -105,6 +105,7 @@ static void sd_iosize(device_t, int *);
static int sd_lastclose(device_t);
static int sd_firstopen(device_t, dev_t, int, int);
static void sd_label(device_t, struct disklabel *);
+static int sd_discard(device_t, off_t, off_t);
static int sd_mode_sense(struct sd_softc *, u_int8_t, void *, size_t, int,
int, int *);
@@ -158,6 +159,7 @@ static dev_type_ioctl(sdioctl);
static dev_type_strategy(sdstrategy);
static dev_type_dump(sddump);
static dev_type_size(sdsize);
+static dev_type_discard(sddiscard);
const struct bdevsw sd_bdevsw = {
.d_open = sdopen,
@@ -166,7 +168,7 @@ const struct bdevsw sd_bdevsw = {
.d_ioctl = sdioctl,
.d_dump = sddump,
.d_psize = sdsize,
- .d_discard = nodiscard,
+ .d_discard = sddiscard,
.d_cfdriver = &sd_cd,
.d_devtounit = disklabel_dev_unit,
.d_flag = D_DISK | D_MPSAFE
@@ -183,7 +185,7 @@ const struct cdevsw sd_cdevsw = {
.d_poll = nopoll,
.d_mmap = nommap,
.d_kqfilter = nokqfilter,
- .d_discard = nodiscard,
+ .d_discard = sddiscard,
.d_cfdriver = &sd_cd,
.d_devtounit = disklabel_dev_unit,
.d_flag = D_DISK | D_MPSAFE
@@ -200,6 +202,7 @@ static const struct dkdriver sddkdriver
.d_firstopen = sd_firstopen,
.d_lastclose = sd_lastclose,
.d_label = sd_label,
+ .d_discard = sd_discard,
};
static const struct scsipi_periphsw sd_switch = {
@@ -1047,6 +1050,51 @@ sd_label(device_t self, struct disklabel
lp->d_flags |= D_REMOVABLE;
}
+static int
+sd_unmap(struct sd_softc *sd, off_t pos, off_t len)
+{
+ struct scsi_unmap_10 cmd;
+ struct scsi_unmap_10_data data;
+ int flags = 0;
+ uint64_t bno;
+ uint32_t size;
+
+ /* round the start up and the end down */
+ bno = (pos + sd->params.blksize - 1) / sd->params.blksize;
+ size = ((pos + len) / sd->params.blksize) - bno;
+
+ if (size == 0)
+ return 0;
+
+ memset(&data, 0, sizeof(data));
+ _lto2b(sizeof(data) - 2, data.unmap_data_length);
+ _lto2b(sizeof(data) - 8, data.unmap_block_descriptor_data_length);
+ _lto8b(bno, data.unmap_block_descriptor[0].addr);
+ _lto4b(size, data.unmap_block_descriptor[0].len);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = UNMAP_10;
+ cmd.byte2 = 0;
+ _lto2b(sizeof(data), cmd.length);
+
+ scsipi_command(sd->sc_periph,
+ (void *)&cmd, sizeof(cmd), (void *)&data, sizeof(data),
+ SDRETRIES, 2000000, NULL,
+ flags | XS_CTL_DATA_OUT);
+
+ return 0;
+}
+
+static int
+sd_discard(device_t self, off_t pos, off_t len)
+{
+ struct sd_softc *sd = device_private(self);
+ if (sd->flags & SDF_LBPU) {
+ return sd_unmap(sd, pos, len);
+ }
+ return ENODEV;
+}
+
static bool
sd_shutdown(device_t self, int how)
{
@@ -1420,6 +1468,11 @@ sd_read_capacity(struct sd_softc *sd, in
rv = _8btol(datap->data16.addr) + 1;
sd->params.lbppbe = datap->data16.byte14 & SRC16D_LBPPB_EXPONENT;
sd->params.lalba = _2btol(datap->data16.lowest_aligned) & SRC16D_LALBA;
+ if (_2btol(datap->data16.lowest_aligned) & SRC16D_LBPME) {
+ sd->flags |= SDF_LBPME;
+ } else {
+ sd->flags &= ~SDF_LBPME;
+ }
out:
free(datap, M_TEMP);
@@ -1579,6 +1632,26 @@ printf("page 0 ok\n");
dp->blksize = blksize;
dp->disksize512 = (blocks * dp->blksize) / DEV_BSIZE;
+
+ if ((sd->flags & SDF_LBPME) == 0)
+ goto end;
+ struct scsipi_inquiry cmd;
+ struct scsi_vpd_logical_block_provisioning vpdbuf;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = INQUIRY;
+ cmd.length = sizeof(vpdbuf);
+ cmd.byte2 |= SINQ_EVPD;
+ cmd.pagecode = SINQ_VPD_LOGICAL_PROV;
+
+ sd->flags &= ~SDF_LBPU;
+ if (scsipi_command(sd->sc_periph, (void *)&cmd, sizeof(cmd), (void *)&vpdbuf, sizeof(vpdbuf),
+ SDRETRIES, 100000, NULL, flags | XS_CTL_DATA_IN | XS_CTL_IGNORE_ILLEGAL_REQUEST))
+ goto end;
+
+ if (vpdbuf.flags & VPD_LBP_LBPU)
+ sd->flags |= SDF_LBPU;
+
+end:
return (0);
}
@@ -1963,3 +2036,16 @@ sd_set_geometry(struct sd_softc *sd)
disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, sd->typename);
}
+
+static int
+sddiscard(dev_t dev, off_t pos, off_t len)
+{
+ struct sd_softc *sd;
+ int unit;
+
+ unit = SDUNIT(dev);
+ sd = device_lookup_private(&sd_cd, unit);
+
+ return dk_discard(&sd->sc_dksc, dev, pos, len);
+}
+
Index: src/sys/dev/scsipi/sdvar.h
diff -u src/sys/dev/scsipi/sdvar.h:1.41 src/sys/dev/scsipi/sdvar.h:1.42
--- src/sys/dev/scsipi/sdvar.h:1.41 Thu Feb 27 17:03:46 2025
+++ src/sys/dev/scsipi/sdvar.h Thu Feb 27 17:17:00 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: sdvar.h,v 1.41 2025/02/27 17:03:46 jakllsch Exp $ */
+/* $NetBSD: sdvar.h,v 1.42 2025/02/27 17:17:00 jakllsch Exp $ */
/*-
* Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
@@ -82,6 +82,8 @@ struct sd_softc {
#define SDF_ANCIENT 0x10 /* disk is ancient; for minphys */
#define SDF_DIRTY 0x20 /* disk is dirty; needs cache flush */
#define SDF_FLUSHING 0x40 /* flushing, for sddone() */
+#define SDF_LBPME 0x80 /* logical block provisioning management enabled */
+#define SDF_LBPU 0x100 /* logical block provisioning unmap */
struct scsipi_periph *sc_periph;/* contains our targ, lun, etc. */