> On 31 Oct 2016, at 09:18, Stefan Fritsch <s...@sfritsch.de> wrote: > > On Sun, 30 Oct 2016, Stefan Fritsch wrote: >> I agree with all your comments (and should have reviewed the initial patch >> better). Here is an updated diff. > > The FWRITE check was missing in wdioctl(). Next try:
the diff looks fine to me. whats the use of the ioctl though? why do we need extra sync cache things? dlg > > diff --git sys/dev/ata/wd.c sys/dev/ata/wd.c > index 5e2461f..ca5ac90 100644 > --- sys/dev/ata/wd.c > +++ sys/dev/ata/wd.c > @@ -26,7 +26,7 @@ > */ > > /*- > - * Copyright (c) 1998 The NetBSD Foundation, Inc. > + * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. > * All rights reserved. > * > * This code is derived from software contributed to The NetBSD Foundation > @@ -138,7 +138,7 @@ void wdstart(void *); > void __wdstart(struct wd_softc*, struct buf *); > void wdrestart(void *); > int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *); > -void wd_flushcache(struct wd_softc *, int); > +int wd_flushcache(struct wd_softc *, int); > void wd_standby(struct wd_softc *, int); > > /* XXX: these should go elsewhere */ > @@ -848,6 +848,14 @@ wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, > struct proc *p) > } > #endif > > + case DIOCCACHESYNC: > + if ((flag & FWRITE) == 0) { > + error = EBADF; > + goto exit; > + } > + error = wd_flushcache(wd, AT_WAIT); > + goto exit; > + > default: > error = wdc_ioctl(wd->drvp, xfer, addr, flag, p); > goto exit; > @@ -1067,13 +1075,13 @@ wd_get_params(struct wd_softc *wd, u_int8_t flags, > struct ataparams *params) > } > } > > -void > +int > wd_flushcache(struct wd_softc *wd, int flags) > { > struct wdc_command wdc_c; > > if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */ > - return; > + return EIO; > bzero(&wdc_c, sizeof(struct wdc_command)); > wdc_c.r_command = (wd->sc_flags & WDF_LBA48 ? WDCC_FLUSHCACHE_EXT : > WDCC_FLUSHCACHE); > @@ -1088,20 +1096,28 @@ wd_flushcache(struct wd_softc *wd, int flags) > if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { > printf("%s: flush cache command didn't complete\n", > wd->sc_dev.dv_xname); > + return EIO; > } > + if (wdc_c.flags & ERR_NODEV) > + return ENODEV; > if (wdc_c.flags & AT_TIMEOU) { > printf("%s: flush cache command timeout\n", > wd->sc_dev.dv_xname); > + return EIO; > + } > + if (wdc_c.flags & AT_ERROR) { > + if (wdc_c.r_error == WDCE_ABRT) /* command not supported */ > + return ENODEV; > + printf("%s: flush cache command: error 0x%x\n", > + wd->sc_dev.dv_xname, wdc_c.r_error); > + return EIO; > } > if (wdc_c.flags & AT_DF) { > printf("%s: flush cache command: drive fault\n", > wd->sc_dev.dv_xname); > + return EIO; > } > - /* > - * Ignore error register, it shouldn't report anything else > - * than COMMAND ABORTED, which means the device doesn't support > - * flush cache > - */ > + return 0; > } > > void > diff --git sys/scsi/sd.c sys/scsi/sd.c > index 30fb36b..e5a0139 100644 > --- sys/scsi/sd.c > +++ sys/scsi/sd.c > @@ -2,7 +2,7 @@ > /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ > > /*- > - * Copyright (c) 1998 The NetBSD Foundation, Inc. > + * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. > * All rights reserved. > * > * This code is derived from software contributed to The NetBSD Foundation > @@ -96,7 +96,7 @@ int sd_vpd_block_limits(struct sd_softc *, int); > int sd_vpd_thin(struct sd_softc *, int); > int sd_thin_params(struct sd_softc *, int); > int sd_get_parms(struct sd_softc *, struct disk_parms *, int); > -void sd_flush(struct sd_softc *, int); > +int sd_flush(struct sd_softc *, int); > > void viscpy(u_char *, u_char *, int); > > @@ -999,6 +999,15 @@ sdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, > struct proc *p) > error = sd_ioctl_cache(sc, cmd, (struct dk_cache *)addr); > goto exit; > > + case DIOCCACHESYNC: > + if (!ISSET(flag, FWRITE)) { > + error = EBADF; > + goto exit; > + } > + if ((sc->flags & SDF_DIRTY) != 0 || *(int *)addr != 0) > + error = sd_flush(sc, 0); > + goto exit; > + > default: > if (part != RAW_PART) { > error = ENOTTY; > @@ -1876,19 +1885,20 @@ die: > return (SDGP_RESULT_OFFLINE); > } > > -void > +int > sd_flush(struct sd_softc *sc, int flags) > { > struct scsi_link *link; > struct scsi_xfer *xs; > struct scsi_synchronize_cache *cmd; > + int error; > > if (sc->flags & SDF_DYING) > - return; > + return (ENXIO); > link = sc->sc_link; > > if (link->quirks & SDEV_NOSYNCCACHE) > - return; > + return (0); > > /* > * Issue a SYNCHRONIZE CACHE. Address 0, length 0 means "all remaining > @@ -1899,7 +1909,7 @@ sd_flush(struct sd_softc *sc, int flags) > xs = scsi_xs_get(link, flags); > if (xs == NULL) { > SC_DEBUG(link, SDEV_DB1, ("cache sync failed to get xs\n")); > - return; > + return (EIO); > } > > cmd = (struct scsi_synchronize_cache *)xs->cmd; > @@ -1909,10 +1919,14 @@ sd_flush(struct sd_softc *sc, int flags) > xs->timeout = 100000; > xs->flags |= SCSI_IGNORE_ILLEGAL_REQUEST; > > - if (scsi_xs_sync(xs) == 0) > - sc->flags &= ~SDF_DIRTY; > - else > - SC_DEBUG(link, SDEV_DB1, ("cache sync failed\n")); > + error = scsi_xs_sync(xs); > > scsi_xs_put(xs); > + > + if (error) > + SC_DEBUG(link, SDEV_DB1, ("cache sync failed\n")); > + else > + sc->flags &= ~SDF_DIRTY; > + > + return (error); > } > diff --git sys/sys/dkio.h sys/sys/dkio.h > index c774e19..0a373af 100644 > --- sys/sys/dkio.h > +++ sys/sys/dkio.h > @@ -83,4 +83,6 @@ struct dk_diskmap { > > #define DIOCMAP _IOWR('d', 119, struct dk_diskmap) > > +#define DIOCCACHESYNC _IOW('d', 120, int) /* sync cache (force?) > */ > + > #endif /* _SYS_DKIO_H_ */ >