Date: Mon, 29 Sep 2008 06:14:59 -0700 (PDT) From: Jeremy Chadwick <koitsu@FreeBSD.org> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/127717: ata(4) - support write cache toggling per device Message-ID: <20080929131459.9B581C9438@icarus.home.lan> Resent-Message-ID: <200809291320.m8TDK0vU056229@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 127717 >Category: kern >Synopsis: ata(4) - support write cache toggling per device >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Sep 29 13:20:00 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Jeremy Chadwick >Release: FreeBSD 7.1-PRERELEASE amd64 >Organization: >Environment: System: FreeBSD icarus.home.lan 7.1-PRERELEASE FreeBSD 7.1-PRERELEASE #0: Wed Sep 24 19:35:59 PDT 2008 root@icarus.home.lan:/usr/obj/usr/src/sys/PDSMI_PLUS_amd64 amd64 >Description: At present, there is no way to disable/enable write caching on a disk, on a per-disk basis. There is the tunable hw.ata.wc which you can set to 0, but that disables WC on all disks. Some users may want to disable WC on specific disks, or if using hw.ata.wc=0, enable WC on specific disks. The below patch addresses this limitation. It does the following: 1) Adds an ATA ioctl called IOCATASETWC, which allows one to disable/enable write caching on a specific device. Devices which do not support toggling the capability (e.g. CD/DVD drives) will return ENODEV, causing ioctl() to return -1. 2) Extends atacontrol(8) to support toggling of write caching, 3) Updates the atacontrol(8) man page to reflect things. Ultimately this should be useful to administrators who use gjournal(8) with the async mount option (where disabling disk write caching is sometimes advised). This patch is against HEAD, but has been fully tested on RELENG_7 i386 and amd64, and can be MFC'd safely. >How-To-Repeat: n/a, but here's confirmation that it does in fact work and is not just a cosmetic thing: testbox# atacontrol wc ad0 on testbox# dd if=/dev/urandom of=/usr/testfile bs=64k count=10000 10000+0 records in 10000+0 records out 655360000 bytes transferred in 19.294844 secs (33965551 bytes/sec) testbox# rm /usr/testfile testbox# sync testbox# sync testbox# atacontrol wc ad0 off testbox# dd if=/dev/urandom of=/usr/testfile bs=64k count=10000 10000+0 records in 10000+0 records out 655360000 bytes transferred in 95.172770 secs (6886003 bytes/sec) >Fix: Apply below patch. Index: sbin/atacontrol/atacontrol.8 =================================================================== RCS file: /home/ncvs/src/sbin/atacontrol/atacontrol.8,v retrieving revision 1.31 diff -u -r1.31 atacontrol.8 --- sbin/atacontrol/atacontrol.8 25 Jun 2008 18:11:22 -0000 1.31 +++ sbin/atacontrol/atacontrol.8 29 Sep 2008 12:56:55 -0000 @@ -74,6 +74,10 @@ .Ar device .Op Ar seconds .Nm +.Ic wc +.Ar device +.Op Ar on|off +.Nm .Ic list .Sh DESCRIPTION The @@ -202,6 +206,9 @@ setting the timeout. To disable spindown, set the timeout to zero. No further actions are needed in this case. +.It Ic wc +Enable or disable write caching on the specific +.Ar device . .It Ic info Show info about the attached devices on the .Ar channel . @@ -354,6 +361,18 @@ .Pa / or syslog logging on it as the disk will be worn out spinning down and up all the time. +.Pp +To disable write caching on a specific disk, run +.Pp +.Dl "atacontrol wc ad6 off" +.Pp +Write cache toggling may be useful to individuals using +.Xr gjournal 8 +with the +.Pa async +.Xr mount 8 +option on a filesystem. +.Pp .Sh SEE ALSO .Xr ata 4 .Sh HISTORY Index: sbin/atacontrol/atacontrol.c =================================================================== RCS file: /home/ncvs/src/sbin/atacontrol/atacontrol.c,v retrieving revision 1.49 diff -u -r1.49 atacontrol.c --- sbin/atacontrol/atacontrol.c 6 Aug 2008 18:08:02 -0000 1.49 +++ sbin/atacontrol/atacontrol.c 29 Sep 2008 12:56:55 -0000 @@ -104,6 +104,7 @@ " atacontrol mode device [mode]\n" " atacontrol cap device\n" " atacontrol spindown device [seconds]\n" + " atacontrol wc device [on|off]\n" ); exit(EX_USAGE); } @@ -374,6 +375,24 @@ } exit(EX_OK); } + + if (!strcmp(argv[1], "wc") && argc == 4) { + fd = open_dev(argv[2], O_RDONLY); + if (!strcmp(argv[3], "on")) { + mode = 1; + } + else if (!strcmp(argv[3], "off")) { + mode = 0; + } + else { + usage(); + exit(EX_USAGE); + } + if (ioctl(fd, IOCATASETWC, &mode) < 0) + err(1, "ioctl(IOCATASETWC)"); + exit(EX_OK); + } + if (!strcmp(argv[1], "cap") && argc == 3) { fd = open_dev(argv[2], O_RDONLY); ata_cap_print(fd); Index: sys/dev/ata/ata-all.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v retrieving revision 1.290 diff -u -r1.290 ata-all.c --- sys/dev/ata/ata-all.c 15 Aug 2008 10:55:11 -0000 1.290 +++ sys/dev/ata/ata-all.c 29 Sep 2008 12:56:55 -0000 @@ -532,6 +532,22 @@ case IOCATAGSPINDOWN: *mode = atadev->spindown; return 0; + case IOCATASETWC: + ATA_SETMODE(device_get_parent(dev), dev); + + /* enable write caching if supported and configured */ + if (atadev->param.support.command1 & ATA_SUPPORT_WRITECACHE) { + if (*mode == 1) { + ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_WCACHE, 0, 0); + } + else { + ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_DIS_WCACHE, 0, 0); + } + } + else { + return ENODEV; + } + return 0; default: return ENOTTY; } Index: sys/sys/ata.h =================================================================== RCS file: /home/ncvs/src/sys/sys/ata.h,v retrieving revision 1.40 diff -u -r1.40 ata.h --- sys/sys/ata.h 10 Apr 2008 13:01:17 -0000 1.40 +++ sys/sys/ata.h 29 Sep 2008 12:56:55 -0000 @@ -438,6 +438,8 @@ #define IOCATAGSPINDOWN _IOR('a', 104, int) #define IOCATASSPINDOWN _IOW('a', 105, int) +#define IOCATASETWC _IOW('a', 106, int) + struct ata_ioc_raid_config { int lun; >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080929131459.9B581C9438>