Subject: Re: Explicit enabling of disk caches
To: None <tech-kern@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: tech-kern
Date: 09/05/2001 09:38:49
--jL2BoiuKMElzg3CS
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Sun, Sep 02, 2001 at 10:31:04AM -0700, Jason R Thorpe wrote:
> I've been thinking of ways we can improve I/O performance, and one
> obvious way is to provide a mechanism to explicitly manipulate the
> read and write caches on disks.
I've done a little more work on this in my spare time, and have fleshed
the DKCACHE bits out a bit more.
I know of at least one person who is quite happy with these changes (because
his RAID performance improved roughly 4x), and can live with write-back
mode because he trusts his UPS :-)
Later this week I will probably look into gluing the disk cache knowledge
into the file system code.
--
-- Jason R. Thorpe <thorpej@wasabisystems.com>
--jL2BoiuKMElzg3CS
Content-Type: text/plain; charset=us-ascii
Content-Description: dkcache.diffs
Content-Disposition: attachment; filename=foo
Index: sys/dkio.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/dkio.h,v
retrieving revision 1.5
diff -c -r1.5 dkio.h
*** sys/dkio.h 2001/01/07 17:55:41 1.5
--- sys/dkio.h 2001/09/05 16:40:53
***************
*** 75,78 ****
--- 75,91 ----
#define ODIOCGDEFLABEL _IOR('d', 114, struct olddisklabel)
#endif
+ /* disk cache enable/disable */
+ #define DIOCGCACHE _IOR('d', 116, int) /* get cache enables */
+ #define DIOCSCACHE _IOW('d', 117, int) /* set cache enables */
+
+ #define DKCACHE_READ 0x000001 /* read cache enabled */
+ #define DKCACHE_WRITE 0x000002 /* write(back) cache enabled */
+ #define DKCACHE_RCHANGE 0x000100 /* read enable is changeable */
+ #define DKCACHE_WCHANGE 0x000200 /* write enable is changeable */
+ #define DKCACHE_SAVE 0x010000 /* cache parameters are savable/save them */
+
+ /* sync disk cache */
+ #define DIOCCACHESYNC _IOW('d', 118, int) /* sync cache (force?) */
+
#endif /* _SYS_DKIO_H_ */
Index: dev/scsipi/sd.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/scsipi/sd.c,v
retrieving revision 1.178
diff -c -r1.178 sd.c
*** dev/scsipi/sd.c 2001/07/18 18:21:05 1.178
--- dev/scsipi/sd.c 2001/09/05 16:40:54
***************
*** 912,917 ****
--- 912,919 ----
case DIOCLOCK:
case DIOCEJECT:
case ODIOCEJECT:
+ case DIOCGCACHE:
+ case DIOCSCACHE:
case SCIOCIDENTIFY:
case OSCIOCIDENTIFY:
case SCIOCCOMMAND:
***************
*** 1047,1052 ****
--- 1049,1089 ----
memcpy(addr, &newlabel, sizeof (struct olddisklabel));
return (0);
#endif
+
+ case DIOCGCACHE:
+ if (sd->sc_ops->sdo_getcache != NULL)
+ return ((*sd->sc_ops->sdo_getcache)(sd, (int *) addr));
+
+ /* Not supported on this device. */
+ *(int *) addr = 0;
+ return (0);
+
+ case DIOCSCACHE:
+ if ((flag & FWRITE) == 0)
+ return (EBADF);
+ if (sd->sc_ops->sdo_setcache != NULL)
+ return ((*sd->sc_ops->sdo_setcache)(sd, *(int *) addr));
+
+ /* Not supported on this device. */
+ return (EOPNOTSUPP);
+
+ case DIOCCACHESYNC:
+ /*
+ * XXX Do we really need to care about having a writeable
+ * file descriptor here?
+ */
+ if ((flag & FWRITE) == 0)
+ return (EBADF);
+ if (((sd->flags & SDF_DIRTY) != 0 || *(int *)addr != 0) &&
+ sd->sc_ops->sdo_flush != NULL) {
+ error = (*sd->sc_ops->sdo_flush)(sd, 0);
+ if (error)
+ sd->flags &= ~SDF_FLUSHING;
+ else
+ sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
+ } else
+ error = 0;
+ return (error);
default:
if (part != RAW_PART)
Index: dev/scsipi/sd_scsi.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/scsipi/sd_scsi.c,v
retrieving revision 1.19
diff -c -r1.19 sd_scsi.c
*** dev/scsipi/sd_scsi.c 2001/08/31 07:09:42 1.19
--- dev/scsipi/sd_scsi.c 2001/09/05 16:40:54
***************
*** 62,67 ****
--- 62,68 ----
#include <sys/errno.h>
#include <sys/device.h>
#include <sys/disk.h>
+ #include <sys/dkio.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsi_all.h>
***************
*** 102,111 ****
--- 103,116 ----
static int sd_scsibus_get_optparms __P((struct sd_softc *,
struct disk_parms *, int));
static int sd_scsibus_flush __P((struct sd_softc *, int));
+ static int sd_scsibus_getcache __P((struct sd_softc *, int *));
+ static int sd_scsibus_setcache __P((struct sd_softc *, int));
const struct sd_ops sd_scsibus_ops = {
sd_scsibus_get_parms,
sd_scsibus_flush,
+ sd_scsibus_getcache,
+ sd_scsibus_setcache,
};
int
***************
*** 369,372 ****
--- 374,475 ----
flags|XS_CTL_IGNORE_ILLEGAL_REQUEST));
} else
return(0);
+ }
+
+ int
+ sd_scsibus_getcache(sd, bitsp)
+ struct sd_softc *sd;
+ int *bitsp;
+ {
+ struct scsipi_periph *periph = sd->sc_periph;
+ struct sd_scsibus_mode_sense_data scsipi_sense;
+ int error, bits = 0;
+
+ if (periph->periph_version < 2)
+ return (EOPNOTSUPP);
+
+ error = sd_scsibus_mode_sense(sd, &scsipi_sense, 8, 0);
+ if (error)
+ return (error);
+
+ if ((scsipi_sense.pages.caching_params.flags & CACHING_RCD) == 0)
+ bits |= DKCACHE_READ;
+ if (scsipi_sense.pages.caching_params.flags & CACHING_WCE)
+ bits |= DKCACHE_WRITE;
+ if (scsipi_sense.pages.caching_params.pg_code & PGCODE_PS)
+ bits |= DKCACHE_SAVE;
+
+ error = sd_scsibus_mode_sense(sd, &scsipi_sense,
+ SMS_PAGE_CTRL_CHANGEABLE|8, 0);
+ if (error == 0) {
+ if (scsipi_sense.pages.caching_params.flags & CACHING_RCD)
+ bits |= DKCACHE_RCHANGE;
+ if (scsipi_sense.pages.caching_params.flags & CACHING_WCE)
+ bits |= DKCACHE_WCHANGE;
+ }
+
+ *bitsp = bits;
+
+ return (0);
+ }
+
+ int
+ sd_scsibus_setcache(sd, bits)
+ struct sd_softc *sd;
+ int bits;
+ {
+ struct scsipi_periph *periph = sd->sc_periph;
+ struct sd_scsibus_mode_sense_data scsipi_sense;
+ int error, size;
+ uint8_t oflags, byte2 = 0;
+
+ if (periph->periph_version < 2)
+ return (EOPNOTSUPP);
+
+ error = sd_scsibus_mode_sense(sd, &scsipi_sense, 8, 0);
+ if (error)
+ return (error);
+
+ oflags = scsipi_sense.pages.caching_params.flags;
+
+ if (bits & DKCACHE_READ)
+ scsipi_sense.pages.caching_params.flags &= ~CACHING_RCD;
+ else
+ scsipi_sense.pages.caching_params.flags |= CACHING_RCD;
+
+ if (bits & DKCACHE_WRITE)
+ scsipi_sense.pages.caching_params.flags |= CACHING_WCE;
+ else
+ scsipi_sense.pages.caching_params.flags &= ~CACHING_WCE;
+
+ if (oflags == scsipi_sense.pages.caching_params.flags)
+ return (0);
+
+ scsipi_sense.pages.caching_params.pg_code &= PGCODE_MASK;
+
+ if (bits & DKCACHE_SAVE)
+ byte2 |= SMS_SP;
+
+ size = sizeof(scsipi_sense.header) + sizeof(scsipi_sense.blk_desc) +
+ sizeof(struct scsipi_mode_page_header) +
+ scsipi_sense.pages.caching_params.pg_length;
+
+ if ((sd->sc_periph->periph_quirks & PQUIRK_ONLYBIG) &&
+ !(sd->sc_periph->periph_quirks & PQUIRK_NOBIGMODESENSE)) {
+ scsipi_sense.header.data_length = 0;
+ /* 2nd length byte in BIG header */
+ scsipi_sense.header.medium_type = 0;
+ error = scsipi_mode_select_big(sd->sc_periph, SMS_PF,
+ (struct scsipi_mode_header_big*)&scsipi_sense.header,
+ size, /* XS_CTL_SILENT | */ XS_CTL_DATA_ONSTACK,
+ SDRETRIES, 10000);
+ } else {
+ scsipi_sense.header.data_length = 0;
+ error = scsipi_mode_select(sd->sc_periph, SMS_PF,
+ &scsipi_sense.header, size,
+ /* XS_CTL_SILENT | */ XS_CTL_DATA_ONSTACK,
+ SDRETRIES, 10000);
+ }
+
+ return (error);
}
Index: dev/scsipi/sdvar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/scsipi/sdvar.h,v
retrieving revision 1.15
diff -c -r1.15 sdvar.h
*** dev/scsipi/sdvar.h 2001/05/23 02:16:19 1.15
--- dev/scsipi/sdvar.h 2001/09/05 16:40:54
***************
*** 109,114 ****
--- 109,116 ----
int (*sdo_get_parms) __P((struct sd_softc *, struct disk_parms *,
int));
int (*sdo_flush) __P((struct sd_softc *, int));
+ int (*sdo_getcache) __P((struct sd_softc *, int *));
+ int (*sdo_setcache) __P((struct sd_softc *, int));
};
#define SDGP_RESULT_OK 0 /* paramters obtained */
#define SDGP_RESULT_OFFLINE 1 /* no media, or otherwise losing */
--jL2BoiuKMElzg3CS--