summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2020-03-21 15:18:57 +0000
committermartin <martin@NetBSD.org>2020-03-21 15:18:57 +0000
commitd24078dceaf8eeb614ba55475a210d5595579e15 (patch)
treef6f81ab1987a4d70527d71d0d744aeadf6ecfd63 /sys/dev
parent3345497b79948f6e5da5a04c13f34981c7d6ca10 (diff)
Pull up following revision(s) (requested by riastradh in ticket #788):
sys/sys/dkio.h: revision 1.26 sys/dev/dkwedge/dk.c: revision 1.100 sys/sys/disk.h: revision 1.75 external/cddl/osnet/dist/uts/common/fs/zfs/vdev_disk.c: revision 1.14 external/cddl/osnet/dist/uts/common/fs/zfs/vdev_disk.c: revision 1.15 sys/dev/cgd.c: revision 1.121 sys/dev/ata/wdvar.h: revision 1.50 sys/kern/subr_disk_open.c: revision 1.15 sys/dev/ata/wd.c: revision 1.459 New ioctl DIOCGSECTORALIGN returns sector alignment parameters. struct disk_sectoralign { /* First aligned sector number. */ uint32_t dsa_firstaligned; /* Number of sectors per aligned unit. */ uint32_t dsa_alignment; }; - Teach wd(4) to get it from ATA. - Teach cgd(4) to pass it through from the underlying disk. - Teach dk(4) to pass it through with adjustments. - Teach zpool (zfs) to take advantage of it. => XXX zpool doesn't seem to understand when the vdev's starting sector is misaligned. Missing: - ccd(4) and raidframe(4) support -- these should support _using_ DIOCGSECTORALIGN to decide where to start putting ccd or raid stripes on disk, and these should perhaps _implement_ DIOCGSECTORALIGN by reporting the stripe/interleave factor. - sd(4) support -- I don't know any obvious way to get it from SCSI, but if any SCSI wizards know better than I, please feel free to teach sd(4) about it! - any ld(4) attachments -- might be worth teaching the ld drivers for nvme and various raid controllers to get the aligned sector size There's some duplicate logic here for now. I'm doing it this way, rather than gathering the logic into a new disklabel_sectoralign function or something, so that this change is limited to adding a new ioctl, without any new kernel symbols, in order to make it easy to pull up to netbsd-9 without worrying about the module ABI. Make getdiskinfo() compatible with a DIOCGWEDGEINFO. dkw_parent is defined to hold the disk name as used by disk_find(), not a partition (i.e. no partition letter appended). Use utility functions to handle disk geometry.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/wd.c51
-rw-r--r--sys/dev/ata/wdvar.h3
-rw-r--r--sys/dev/cgd.c31
-rw-r--r--sys/dev/dkwedge/dk.c21
4 files changed, 98 insertions, 8 deletions
diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c
index 039fd844c0d..aa52d8a7425 100644
--- a/sys/dev/ata/wd.c
+++ b/sys/dev/ata/wd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.452 2019/06/06 20:55:43 mlelstv Exp $ */
+/* $NetBSD: wd.c,v 1.452.2.1 2020/03/21 15:18:57 martin Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452 2019/06/06 20:55:43 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452.2.1 2020/03/21 15:18:57 martin Exp $");
#include "opt_ata.h"
#include "opt_wd.h"
@@ -430,16 +430,40 @@ wdattach(device_t parent, device_t self, void *aux)
} else {
wd->sc_blksize = 512;
}
+ wd->sc_sectoralign.dsa_firstaligned = 0;
+ wd->sc_sectoralign.dsa_alignment = 1;
+ if ((wd->sc_params.atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID
+ && ((wd->sc_params.atap_secsz & ATA_SECSZ_LPS) != 0)) {
+ wd->sc_sectoralign.dsa_alignment = 1 <<
+ (wd->sc_params.atap_secsz & ATA_SECSZ_LPS_SZMSK);
+ if ((wd->sc_params.atap_logical_align & ATA_LA_VALID_MASK) ==
+ ATA_LA_VALID) {
+ wd->sc_sectoralign.dsa_firstaligned =
+ (wd->sc_sectoralign.dsa_alignment -
+ (wd->sc_params.atap_logical_align &
+ ATA_LA_MASK));
+ }
+ }
wd->sc_capacity512 = (wd->sc_capacity * wd->sc_blksize) / DEV_BSIZE;
format_bytes(pbuf, sizeof(pbuf), wd->sc_capacity * wd->sc_blksize);
aprint_normal_dev(self, "%s, %d cyl, %d head, %d sec, "
- "%d bytes/sect x %llu sectors\n",
+ "%d bytes/sect x %llu sectors",
pbuf,
(wd->sc_flags & WDF_LBA) ? (int)(wd->sc_capacity /
(wd->sc_params.atap_heads * wd->sc_params.atap_sectors)) :
wd->sc_params.atap_cylinders,
wd->sc_params.atap_heads, wd->sc_params.atap_sectors,
wd->sc_blksize, (unsigned long long)wd->sc_capacity);
+ if (wd->sc_sectoralign.dsa_alignment != 1) {
+ aprint_normal(" (%d bytes/physsect",
+ wd->sc_sectoralign.dsa_alignment & wd->sc_blksize);
+ if (wd->sc_sectoralign.dsa_firstaligned != 0) {
+ aprint_normal("; first aligned sector: %jd",
+ (intmax_t)wd->sc_sectoralign.dsa_firstaligned);
+ }
+ aprint_normal(")");
+ }
+ aprint_normal("\n");
ATADEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
device_xname(self), wd->sc_params.atap_dmatiming_mimi,
@@ -1409,6 +1433,27 @@ wdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
return(error1);
}
+ case DIOCGSECTORALIGN: {
+ struct disk_sectoralign *dsa = addr;
+ int part = WDPART(dev);
+
+ *dsa = wd->sc_sectoralign;
+ if (part != RAW_PART) {
+ struct disklabel *lp = dksc->sc_dkdev.dk_label;
+ daddr_t offset = lp->d_partitions[part].p_offset;
+ uint32_t r = offset % dsa->dsa_alignment;
+
+ if (r < dsa->dsa_firstaligned)
+ dsa->dsa_firstaligned = dsa->dsa_firstaligned
+ - r;
+ else
+ dsa->dsa_firstaligned = (dsa->dsa_firstaligned
+ + dsa->dsa_alignment) - r;
+ }
+
+ return 0;
+ }
+
default:
return dk_ioctl(dksc, dev, cmd, addr, flag, l);
}
diff --git a/sys/dev/ata/wdvar.h b/sys/dev/ata/wdvar.h
index 2f13ded15e3..3c754ca103e 100644
--- a/sys/dev/ata/wdvar.h
+++ b/sys/dev/ata/wdvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: wdvar.h,v 1.49 2019/04/05 18:23:45 bouyer Exp $ */
+/* $NetBSD: wdvar.h,v 1.49.4.1 2020/03/21 15:18:57 martin Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -59,6 +59,7 @@ struct wd_softc {
uint64_t sc_capacity512; /* ... in DEV_BSIZE blocks */
uint32_t sc_capacity28; /* capacity accessible with LBA28 commands */
uint32_t sc_blksize; /* logical block size, in bytes */
+ struct disk_sectoralign sc_sectoralign; /* sector alignment */
#ifdef WD_SOFTBADSECT
SLIST_HEAD(, disk_badsectors) sc_bslist;
diff --git a/sys/dev/cgd.c b/sys/dev/cgd.c
index 4c7348c364d..c73a364908c 100644
--- a/sys/dev/cgd.c
+++ b/sys/dev/cgd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cgd.c,v 1.116 2018/01/23 22:42:29 pgoyette Exp $ */
+/* $NetBSD: cgd.c,v 1.116.10.1 2020/03/21 15:18:57 martin Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.116 2018/01/23 22:42:29 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.116.10.1 2020/03/21 15:18:57 martin Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -722,6 +722,33 @@ cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
* We pass this call down to the underlying disk.
*/
return VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
+ case DIOCGSECTORALIGN: {
+ struct disk_sectoralign *dsa = data;
+ int error;
+
+ if (!DK_ATTACHED(dksc))
+ return ENOENT;
+
+ /* Get the underlying disk's sector alignment. */
+ error = VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
+ if (error)
+ return error;
+
+ /* Adjust for the disklabel partition if necessary. */
+ if (part != RAW_PART) {
+ struct disklabel *lp = dksc->sc_dkdev.dk_label;
+ daddr_t offset = lp->d_partitions[part].p_offset;
+ uint32_t r = offset % dsa->dsa_alignment;
+
+ if (r < dsa->dsa_firstaligned)
+ dsa->dsa_firstaligned = dsa->dsa_firstaligned
+ - r;
+ else
+ dsa->dsa_firstaligned = (dsa->dsa_firstaligned
+ + dsa->dsa_alignment) - r;
+ }
+ return 0;
+ }
case DIOCGSTRATEGY:
case DIOCSSTRATEGY:
if (!DK_ATTACHED(dksc))
diff --git a/sys/dev/dkwedge/dk.c b/sys/dev/dkwedge/dk.c
index 30fc333d0b4..733151bfda8 100644
--- a/sys/dev/dkwedge/dk.c
+++ b/sys/dev/dkwedge/dk.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dk.c,v 1.97 2018/05/12 10:33:06 mlelstv Exp $ */
+/* $NetBSD: dk.c,v 1.97.8.1 2020/03/21 15:18:57 martin Exp $ */
/*-
* Copyright (c) 2004, 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.97 2018/05/12 10:33:06 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.97.8.1 2020/03/21 15:18:57 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_dkwedge.h"
@@ -1501,7 +1501,24 @@ dkioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
break;
}
+ case DIOCGSECTORALIGN:
+ {
+ struct disk_sectoralign *dsa = data;
+ uint32_t r;
+
+ error = VOP_IOCTL(sc->sc_parent->dk_rawvp, cmd, dsa, flag,
+ l != NULL ? l->l_cred : NOCRED);
+ if (error)
+ break;
+ r = sc->sc_offset % dsa->dsa_alignment;
+ if (r < dsa->dsa_firstaligned)
+ dsa->dsa_firstaligned = dsa->dsa_firstaligned - r;
+ else
+ dsa->dsa_firstaligned = (dsa->dsa_firstaligned +
+ dsa->dsa_alignment) - r;
+ break;
+ }
default:
error = ENOTTY;
}