From: James Bottomley <James.Bottomley@SteelEye.com>
To: "Stephen C. Tweedie" <sct@redhat.com>
Cc: Douglas Gilbert <dougg@torque.net>,
Jeremy Higdon <jeremy@classic.engr.sgi.com>,
Daniel Phillips <phillips@bonn-fries.net>,
James Bottomley <James.Bottomley@SteelEye.com>,
Chris Mason <mason@suse.com>,
linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org
Subject: Re: [PATCH] 2.4.x write barriers (updated for ext3)
Date: Mon, 11 Mar 2002 12:15:26 -0500 [thread overview]
Message-ID: <200203111715.g2BHFRB06909@localhost.localdomain> (raw)
In-Reply-To: Message from "Stephen C. Tweedie" <sct@redhat.com> of "Mon, 11 Mar 2002 11:34:46 GMT." <20020311113446.A10150@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 564 bytes --]
This patch (against 2.4.18) addresses our synchronisation problems with write
back caches only, not the ordering problem with tags.
It probes the cache type on attach and inserts synchronisation instructions on
release() (i.e. unmount) or if the reboot notifier is called.
How would you like the cache synchronize instruction plugged into the journal
writes? I can do it either by exposing an ioctl which the journal code can
use, or I can try to use the write barrier (however, the bio layer is going to
have to ensure the ordering if I do that).
James
[-- Attachment #2: sd-cache-2.4.18.diff --]
[-- Type: text/plain , Size: 7437 bytes --]
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.160 -> 1.162
# drivers/scsi/sd.h 1.1 -> 1.2
# drivers/scsi/sd.c 1.19 -> 1.21
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/08 jejb@mulgrave.(none) 1.161
# sd cache control changes
#
# - detect cache type on boot and store in extra fields in Scsi_Disk.
# - if cache is write back synchronize on device release.
# - if cache is write back also synchronize on shutdown notifier.
#
# --------------------------------------------
# 02/03/11 jejb@mulgrave.(none) 1.162
# sd cache control
#
# - bug fixes
# --------------------------------------------
#
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c Mon Mar 11 12:09:13 2002
+++ b/drivers/scsi/sd.c Mon Mar 11 12:09:13 2002
@@ -42,6 +42,7 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/reboot.h>
#include <linux/smp.h>
@@ -104,6 +105,10 @@
static int sd_detect(Scsi_Device *);
static void sd_detach(Scsi_Device *);
static int sd_init_command(Scsi_Cmnd *);
+static int sd_synchronize_cache(Scsi_Device *, int);
+static int sd_notifier(struct notifier_block *, unsigned long, void *);
+
+static struct notifier_block sd_notifier_block = {sd_notifier, NULL, 0};
static struct Scsi_Device_Template sd_template = {
name:"disk",
@@ -549,6 +554,11 @@
__MOD_DEC_USE_COUNT(SDev->host->hostt->module);
if (sd_template.module)
__MOD_DEC_USE_COUNT(sd_template.module);
+
+ /* check that we actually have a write back cache to synchronize */
+ if(rscsi_disks[target].WCE)
+ sd_synchronize_cache(SDev, 1);
+
return 0;
}
@@ -860,8 +870,6 @@
}
mode_retries = 2; /* make two attempts to change the cache type */
-
- retry_mode_select:
retries = 3;
do {
@@ -901,60 +909,20 @@
print_req_sense("sd", SRpnt);
else
printk("%s : sense not available. \n", nbuff);
+
+ printk("%s : assuming drive cache: write through\n", nbuff);
+ rscsi_disks[i].WCE = 0;
+ rscsi_disks[i].RCD = 0;
} else {
const char *types[] = { "write through", "none", "write back", "write back, no read (daft)" };
int ct = 0;
- ct = (buffer[6] & 0x01 /* RCD */) | ((buffer[6] & 0x04 /* WCE */) >> 1);
+ rscsi_disks[i].WCE = buffer[6] & 0x04;
+ rscsi_disks[i].RCD = buffer[6] & 0x01;
- printk("%s : checking drive cache: %s \n", nbuff, types[ct]);
- if(ct != 0x0 && mode_retries-- == 0) {
- printk("%s : FAILED to change cache to write back, continuing\n", nbuff);
- }
- else if(ct != 0x0) {
- retries = 3;
- buffer[6] &= (~0x05); /* clear RCD and WCE */
- do {
- memset((void *) &cmd[0], 0, 10);
- cmd[0] = MODE_SELECT;
- cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
- ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
- cmd[1] |= 0x10; /* PF */
- cmd[4] = 24; /* allocation length */
-
-
- SRpnt->sr_cmd_len = 0;
- SRpnt->sr_sense_buffer[0] = 0;
- SRpnt->sr_sense_buffer[2] = 0;
-
- SRpnt->sr_data_direction = SCSI_DATA_WRITE;
- scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
- 24, SD_TIMEOUT, MAX_RETRIES);
+ ct = rscsi_disks[i].RCD + 2*rscsi_disks[i].WCE;
- the_result = SRpnt->sr_result;
- retries--;
-
- } while (the_result && retries);
-
- if (the_result) {
- printk("%s : MODE SELECT failed.\n"
- "%s : status = %x, message = %02x, host = %d, driver = %02x \n",
- nbuff, nbuff,
- status_byte(the_result),
- msg_byte(the_result),
- host_byte(the_result),
- driver_byte(the_result)
- );
- if (driver_byte(the_result) & DRIVER_SENSE)
- print_req_sense("sd", SRpnt);
- else
- printk("%s : sense not available. \n", nbuff);
- } else {
- printk("%s : changing drive cache to write through\n", nbuff);
- }
- goto retry_mode_select;
- }
-
+ printk("%s : drive cache: %s\n", nbuff, types[ct]);
}
retries = 3;
@@ -1491,8 +1459,13 @@
static int __init init_sd(void)
{
+ int ret;
+
sd_template.module = THIS_MODULE;
- return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
+ ret = scsi_register_module(MODULE_SCSI_DEV, &sd_template);
+ if(ret == 0)
+ register_reboot_notifier(&sd_notifier_block);
+ return ret;
}
static void __exit exit_sd(void)
@@ -1521,6 +1494,92 @@
sd_template.dev_max = 0;
if (sd_gendisks != &sd_gendisk)
kfree(sd_gendisks);
+
+ unregister_reboot_notifier(&sd_notifier_block);
+}
+
+static int sd_notifier(struct notifier_block *nbt, unsigned long event, void *buf)
+{
+ Scsi_Disk *dpnt;
+ int i;
+
+ if (!(event == SYS_RESTART || event == SYS_HALT
+ || event == SYS_POWER_OFF))
+ return NOTIFY_DONE;
+ for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++) {
+ if (!dpnt->device)
+ continue;
+ if (dpnt->WCE)
+ sd_synchronize_cache(dpnt->device, 1);
+ }
+
+ return NOTIFY_OK;
+}
+
+/* send a SYNCHRONIZE CACHE instruction down to the device through the
+ * normal SCSI command structure. Wait for the command to complete (must
+ * have user context) */
+static int sd_synchronize_cache(Scsi_Device *SDpnt, int verbose)
+{
+ Scsi_Request *SRpnt;
+ int retries, the_result;
+
+ if(verbose) {
+ /* we actually want an sd name, so this awful lookup
+ * is only done if verbose is specified */
+ int i;
+ char buf[16];
+ Scsi_Disk *dpnt;
+
+ for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++) {
+ if (dpnt->device == SDpnt)
+ break;
+ }
+ /* no error checking ! */
+ sd_devname(i, buf);
+
+ printk("%s: synchronizing cache...", buf);
+ }
+
+ SRpnt = scsi_allocate_request(SDpnt);
+ if(!SRpnt) {
+ if(verbose)
+ printk("FAILED\n No memory for request\n");
+ return 0;
+ }
+
+
+ for(retries = 3; retries > 0; --retries) {
+ unsigned char cmd[10] = { 0 };
+
+ cmd[0] = SYNCHRONIZE_CACHE;
+ cmd[1] = SDpnt->scsi_level <= SCSI_2 ? (SDpnt->lun << 5) & 0xe0 : 0;
+ /* leave the rest of the command zero to indicate
+ * flush everything */
+ scsi_wait_req(SRpnt, (void *)cmd, NULL, 0,
+ SD_TIMEOUT, MAX_RETRIES);
+
+ if(SRpnt->sr_result == 0)
+ break;
+ }
+
+ the_result = SRpnt->sr_result;
+ scsi_release_request(SRpnt);
+ if(verbose) {
+ if(the_result == 0) {
+ printk("OK\n");
+ } else {
+ printk("FAILED\n status = %x, message = %02x, host = %d, driver = %02x\n ",
+ status_byte(the_result),
+ msg_byte(the_result),
+ host_byte(the_result),
+ driver_byte(the_result));
+ if (driver_byte(the_result) & DRIVER_SENSE)
+ print_req_sense("sd", SRpnt);
+
+ }
+ }
+ return (the_result == 0);
}
module_init(init_sd);
diff -Nru a/drivers/scsi/sd.h b/drivers/scsi/sd.h
--- a/drivers/scsi/sd.h Mon Mar 11 12:09:13 2002
+++ b/drivers/scsi/sd.h Mon Mar 11 12:09:13 2002
@@ -33,6 +33,8 @@
unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */
unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
unsigned has_part_table:1; /* has partition table */
+ unsigned WCE:1; /* state of disk WCE bit */
+ unsigned RCD:1; /* state of disk RCD bit */
} Scsi_Disk;
extern int revalidate_scsidisk(kdev_t dev, int maxusage);
next prev parent reply other threads:[~2002-03-11 17:17 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-02-22 15:57 James Bottomley
2002-02-22 16:10 ` Chris Mason
2002-02-22 16:13 ` Stephen C. Tweedie
2002-02-22 17:36 ` James Bottomley
2002-02-22 18:14 ` Chris Mason
2002-02-28 15:36 ` James Bottomley
2002-02-28 15:55 ` Chris Mason
2002-02-28 17:58 ` Mike Anderson
2002-02-28 18:12 ` Chris Mason
2002-03-01 2:08 ` James Bottomley
2002-03-03 22:11 ` Daniel Phillips
2002-03-04 4:21 ` Jeremy Higdon
2002-03-04 5:31 ` Daniel Phillips
2002-03-04 6:09 ` Jeremy Higdon
2002-03-04 7:57 ` Daniel Phillips
2002-03-05 7:09 ` Jeremy Higdon
2002-03-05 22:56 ` Daniel Phillips
2002-03-04 16:52 ` Stephen C. Tweedie
2002-03-04 18:15 ` Daniel Phillips
2002-03-05 7:40 ` Jens Axboe
2002-03-05 22:29 ` Daniel Phillips
2002-03-12 7:01 ` Jens Axboe
2002-03-10 5:24 ` Douglas Gilbert
2002-03-11 11:13 ` Kurt Garloff
2002-03-12 6:58 ` Jens Axboe
2002-03-13 22:37 ` Peter Osterlund
2002-03-11 11:34 ` Stephen C. Tweedie
2002-03-11 17:15 ` James Bottomley [this message]
2002-03-12 1:17 ` GOTO Masanori
2002-03-04 14:48 ` James Bottomley
2002-03-06 13:59 ` Daniel Phillips
2002-03-06 14:34 ` James Bottomley
2002-03-04 3:34 ` Chris Mason
2002-03-04 5:05 ` Daniel Phillips
2002-03-04 15:03 ` James Bottomley
2002-03-04 17:04 ` Stephen C. Tweedie
2002-03-04 17:35 ` James Bottomley
2002-03-04 17:48 ` Chris Mason
2002-03-04 18:11 ` James Bottomley
2002-03-04 18:41 ` Chris Mason
2002-03-04 21:34 ` Stephen C. Tweedie
2002-03-04 18:09 ` Stephen C. Tweedie
2002-03-04 17:16 ` Chris Mason
2002-03-04 18:05 ` Stephen C. Tweedie
2002-03-04 18:28 ` James Bottomley
2002-03-04 19:55 ` Stephen C. Tweedie
2002-03-04 19:48 ` Daniel Phillips
2002-03-04 19:57 ` Stephen C. Tweedie
2002-03-04 21:06 ` Daniel Phillips
2002-03-05 14:58 ` Stephen C. Tweedie
2002-03-05 7:48 ` Jens Axboe
2002-03-04 19:51 ` Daniel Phillips
2002-03-05 7:42 ` Jens Axboe
2002-03-04 8:19 ` Helge Hafting
2002-03-04 14:57 ` James Bottomley
2002-03-04 17:24 ` Chris Mason
2002-03-04 19:02 ` Daniel Phillips
2002-03-05 7:22 ` Jeremy Higdon
2002-03-05 23:01 ` Daniel Phillips
2002-02-25 10:57 ` Helge Hafting
2002-02-25 15:04 ` James Bottomley
-- strict thread matches above, loose matches on Subject: below --
2002-03-01 15:26 Dieter Nützel
2002-03-01 16:00 ` James Bottomley
2002-02-21 23:30 Chris Mason
2002-02-22 14:19 ` Stephen C. Tweedie
2002-02-22 15:26 ` Chris Mason
2002-01-10 9:55 [ANNOUNCE] FUSE: Filesystem in Userspace 0.95 Miklos Szeredi
2002-01-13 3:10 ` Pavel Machek
2002-01-21 10:18 ` Miklos Szeredi
2002-01-23 10:47 ` Pavel Machek
2002-01-22 19:07 ` Daniel Phillips
2002-01-23 2:33 ` [Avfs] " Justin Mason
2002-01-23 5:26 ` Daniel Phillips
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200203111715.g2BHFRB06909@localhost.localdomain \
--to=james.bottomley@steeleye.com \
--cc=dougg@torque.net \
--cc=jeremy@classic.engr.sgi.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=mason@suse.com \
--cc=phillips@bonn-fries.net \
--cc=sct@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®