Currently implemented for wd and sd.
Initially ported from netbsd by pedro@
ok deraadt@
-/* $OpenBSD: wd.c,v 1.121 2017/05/04 22:47:27 deraadt Exp $ */
+/* $OpenBSD: wd.c,v 1.122 2017/05/29 14:05:31 sf Exp $ */
/* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer 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
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 */
}
#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;
}
}
-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);
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
-/* $OpenBSD: sd.c,v 1.271 2017/05/29 07:47:13 krw Exp $ */
+/* $OpenBSD: sd.c,v 1.272 2017/05/29 14:05:31 sf Exp $ */
/* $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
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);
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;
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
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;
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);
}
-/* $OpenBSD: dkio.h,v 1.9 2011/06/05 18:40:33 matthew Exp $ */
+/* $OpenBSD: dkio.h,v 1.10 2017/05/29 14:05:31 sf Exp $ */
/* $NetBSD: dkio.h,v 1.1 1996/01/30 18:21:48 thorpej Exp $ */
/*
#define DIOCMAP _IOWR('d', 119, struct dk_diskmap)
+#define DIOCCACHESYNC _IOW('d', 120, int) /* sync cache (force?) */
+
#endif /* _SYS_DKIO_H_ */