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

Reply via email to