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. */