LKML Archive on lore.kernel.org help / color / mirror / Atom feed
From: Takao Indoh <indou.takao@soft.fujitsu.com> To: linux-kernel@vger.kernel.org Subject: [2/4] [PATCH]Diskdump - yet another crash dump function Date: Thu, 27 May 2004 21:37:30 +0900 [thread overview] Message-ID: <1EC443E7602106indou.takao@soft.fujitsu.com> (raw) In-Reply-To: <1CC443CDA50AF2indou.takao@soft.fujitsu.com> Hi, This is a patch for scsi common layer. Best Regards, Takao Indoh diff -Nur linux-2.6.6.org/drivers/scsi/Kconfig linux-2.6.6/drivers/scsi/Kconfig --- linux-2.6.6.org/drivers/scsi/Kconfig 2004-05-20 08:58:48.000000000 +0900 +++ linux-2.6.6/drivers/scsi/Kconfig 2004-05-27 09:24:46.000000000 +0900 @@ -55,6 +55,12 @@ In this case, do not compile the driver for your SCSI host adapter (below) as a module either. +config SCSI_DUMP + tristate "SCSI dump support" + depends on DISKDUMP && SCSI + help + SCSI dump support + config CHR_DEV_ST tristate "SCSI tape support" depends on SCSI diff -Nur linux-2.6.6.org/drivers/scsi/Makefile linux-2.6.6/drivers/scsi/Makefile --- linux-2.6.6.org/drivers/scsi/Makefile 2004-05-20 08:58:48.000000000 +0900 +++ linux-2.6.6/drivers/scsi/Makefile 2004-05-27 09:24:46.000000000 +0900 @@ -133,6 +133,8 @@ obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o obj-$(CONFIG_CHR_DEV_SG) += sg.o +obj-$(CONFIG_SCSI_DUMP) += scsi_dump.o + scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_syms.o scsi_sysfs.o \ diff -Nur linux-2.6.6.org/drivers/scsi/scsi.c linux-2.6.6/drivers/scsi/scsi.c --- linux-2.6.6.org/drivers/scsi/scsi.c 2004-05-20 08:58:48.000000000 +0900 +++ linux-2.6.6/drivers/scsi/scsi.c 2004-05-27 09:24:46.000000000 +0900 @@ -691,6 +691,10 @@ { unsigned long flags; +#if defined(CONFIG_SCSI_DUMP) || defined(CONFIG_SCSI_DUMP_MODULE) + if (crashdump_mode()) + return; +#endif /* * We don't have to worry about this one timing out any more. * If we are unable to remove the timer, then the command diff -Nur linux-2.6.6.org/drivers/scsi/scsi_dump.c linux-2.6.6/drivers/scsi/scsi_dump.c --- linux-2.6.6.org/drivers/scsi/scsi_dump.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.6/drivers/scsi/scsi_dump.c 2004-05-27 09:38:53.000000000 +0900 @@ -0,0 +1,565 @@ +/* + * linux/drivers/scsi/scsi_dump.c + * + * Copyright (C) 2004 FUJITSU LIMITED + * Written by Nobuhiro Tachino (ntachino@jp.fujitsu.com) + * + * Some codes are derived from drivers/scsi/sd.c + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/config.h> +#include <linux/module.h> + +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/sched.h> + +#include <linux/blkdev.h> +#include <linux/blkpg.h> +#include "scsi.h" +#include "scsi_priv.h" +#include "hosts.h" +#include "scsi_dump.h" +#include <scsi/scsi_ioctl.h> + +#include <linux/genhd.h> +#include <linux/utsname.h> +#include <linux/crc32.h> +#include <linux/diskdump.h> +#include <linux/diskdumplib.h> +#include <linux/delay.h> + +#define MAX_RETRIES 5 +#define SD_TIMEOUT (60 * HZ) + +#define DEBUG 0 +#if DEBUG +# define Dbg(x, ...) printk(KERN_INFO "scsi_dump:" x "\n", ## __VA_ARGS__) +#else +# define Dbg(x...) +#endif + +#define Err(x, ...) printk(KERN_ERR "scsi_dump: " x "\n", ## __VA_ARGS__); +#define Warn(x, ...) printk(KERN_WARNING "scsi_dump: " x "\n", ## __VA_ARGS__) +#define Info(x, ...) printk(x "\n", ## __VA_ARGS__) + +/* blocks to 512byte sectors */ +#define BLOCK_SECTOR(s) ((s) << (DUMP_BLOCK_SHIFT - 9)) + +static int quiesce_ok = 0; +static Scsi_Cmnd scsi_dump_cmnd; +static struct request scsi_dump_req; +static uint32_t module_crc; + +static void rw_intr(Scsi_Cmnd * scmd) +{ + scmd->done = NULL; +} + +/* + * Common code to make Scsi_Cmnd + */ +static void init_scsi_command(Scsi_Device *sdev, Scsi_Cmnd *scmd, void *buf, int len, unsigned char direction, int set_lun) +{ + scmd->request = &scsi_dump_req; + scmd->sc_magic = SCSI_CMND_MAGIC; + scmd->owner = SCSI_OWNER_MIDLEVEL; + scmd->device = sdev; + scmd->buffer = scmd->request_buffer = buf; + scmd->bufflen = scmd->request_bufflen = len; + + + scmd->sc_data_direction = direction; + + memcpy(scmd->data_cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); + scmd->old_cmd_len = scmd->cmd_len; + + + if (set_lun) + scmd->cmnd[1] |= (sdev->scsi_level <= SCSI_2) ? + ((sdev->lun << 5) & 0xe0) : 0; + + scmd->transfersize = sdev->sector_size; + if (direction == SCSI_DATA_WRITE) + scmd->underflow = len; + + scmd->allowed = MAX_RETRIES; + scmd->timeout_per_command = SD_TIMEOUT; + + /* + * This is the completion routine we use. This is matched in terms + * of capability to this function. + */ + scmd->done = rw_intr; +} + +static void init_mode_sense_command(Scsi_Device *sdev, Scsi_Cmnd *scmd, void *buf) +{ + memset(scmd, 0, sizeof(*scmd)); + scmd->cmnd[0] = MODE_SENSE; + scmd->cmnd[1] = 0x00; /* DBD=0 */ + scmd->cmnd[2] = 0x08; /* PCF=0 Page 8(Cache) */ + scmd->cmnd[4] = 255; + + init_scsi_command(sdev, scmd, buf, 256, SCSI_DATA_READ, 1); +} + +static void init_mode_select_command(Scsi_Device *sdev, Scsi_Cmnd *scmd, void *buf, int len) +{ + memset(scmd, 0, sizeof(*scmd)); + scmd->cmnd[0] = MODE_SELECT; + scmd->cmnd[1] = 0x10; /* PF=1 SP=0 */ + scmd->cmnd[4] = len; + + init_scsi_command(sdev, scmd, buf, len, SCSI_DATA_WRITE, 1); +} + +static void init_sync_command(Scsi_Device *sdev, Scsi_Cmnd * scmd) +{ + memset(scmd, 0, sizeof(*scmd)); + scmd->cmnd[0] = SYNCHRONIZE_CACHE; + + init_scsi_command(sdev, scmd, NULL, 0, SCSI_DATA_NONE, 0); +} + +static void init_sense_command(Scsi_Device *sdev, Scsi_Cmnd *scmd, void *buf) +{ + memset(scmd, 0, sizeof(*scmd)); + scmd->cmnd[0] = REQUEST_SENSE; + scmd->cmnd[4] = 255; + + init_scsi_command(sdev, scmd, buf, 256, SCSI_DATA_READ, 1); +} + +static int init_rw_command(struct disk_dump_partition *dump_part, Scsi_Device *sdev, Scsi_Cmnd * scmd, int rw, int block, void *buf, unsigned int len) +{ + int this_count = len >> 9; + + memset(scmd, 0, sizeof(*scmd)); + + if (block + this_count > dump_part->nr_sects) { + Err("block number %d is larger than %lu", + block + this_count, dump_part->nr_sects); + return -EFBIG; + } + + block += dump_part->start_sect; + + /* + * If we have a 1K hardware sectorsize, prevent access to single + * 512 byte sectors. In theory we could handle this - in fact + * the scsi cdrom driver must be able to handle this because + * we typically use 1K blocksizes, and cdroms typically have + * 2K hardware sectorsizes. Of course, things are simpler + * with the cdrom, since it is read-only. For performance + * reasons, the filesystems should be able to handle this + * and not force the scsi disk driver to use bounce buffers + * for this. + */ + if (sdev->sector_size == 1024) { + block = block >> 1; + this_count = this_count >> 1; + } + if (sdev->sector_size == 2048) { + block = block >> 2; + this_count = this_count >> 2; + } + if (sdev->sector_size == 4096) { + block = block >> 3; + this_count = this_count >> 3; + } + switch (rw) { + case WRITE: + if (!sdev->writeable) { + Err("writable media"); + return 0; + } + scmd->cmnd[0] = WRITE_10; + break; + case READ: + scmd->cmnd[0] = READ_10; + break; + default: + Err("Unknown command %d", rw); + return -EINVAL; + } + + if (this_count > 0xffff) + this_count = 0xffff; + + scmd->cmnd[2] = (unsigned char) (block >> 24) & 0xff; + scmd->cmnd[3] = (unsigned char) (block >> 16) & 0xff; + scmd->cmnd[4] = (unsigned char) (block >> 8) & 0xff; + scmd->cmnd[5] = (unsigned char) block & 0xff; + scmd->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; + scmd->cmnd[8] = (unsigned char) this_count & 0xff; + + init_scsi_command(sdev, scmd, buf, len, + (rw == WRITE ? SCSI_DATA_WRITE : SCSI_DATA_READ), 1); + return 0; +} + +/* + * Check the status of scsi command and determine whether it is + * success, fail, or retriable. + * + * Return code + * > 0: should retry + * = 0: success + * < 0: fail + */ +static int cmd_result(Scsi_Cmnd *scmd) +{ + int status; + + status = status_byte(scmd->result); + + switch (scsi_decide_disposition(scmd)) { + case FAILED: + break; + case NEEDS_RETRY: + case ADD_TO_MLQUEUE: + return 1 /* retry */; + case SUCCESS: + if (host_byte(scmd->result) != DID_OK) + break; + + if (status == GOOD || status == INTERMEDIATE_GOOD + || status == INTERMEDIATE_C_GOOD) + return 0; + if (status == CHECK_CONDITION && scmd->sense_buffer[2] == RECOVERED_ERROR) + return 0; + break; + default: + Err("bad disposition: %d", scmd->result); + return -EIO; + } + + Err("command %x failed with 0x%x", scmd->cmnd[0], scmd->result); + return -EIO; +} + +static int send_command(Scsi_Cmnd *scmd) +{ + struct Scsi_Host *host = scmd->device->host; + Scsi_Device *sdev = scmd->device; + int ret; + + do { + if (!scsi_device_online(sdev)) { + Err("Scsi disk is not online"); + return -EIO; + } + if (sdev->changed) { + Err("SCSI disk has been changed. Prohibiting further I/O"); + return -EIO; + } + + spin_lock(host->host_lock); + host->hostt->queuecommand(scmd, rw_intr); + spin_unlock(host->host_lock); + + while (scmd->done != NULL) { + host->hostt->dump_ops->poll(scmd->device); + udelay(100); + diskdump_update(); + } + scmd->done = rw_intr; + } while ((ret = cmd_result(scmd)) > 0); + + return ret; +} + +/* + * If Write Cache Enable of disk device is not set, write I/O takes + * long long time. So enable WCE temporary and issue SYNCHRONIZE CACHE + * after all write I/Os are done, Following system reboot will reset + * WCE bit to original value. + */ +static void +enable_write_cache(Scsi_Device *sdev) +{ + char buf[256]; + int ret; + int data_len; + + Dbg("enable write cache"); + memset(buf, 0, 256); + + init_mode_sense_command(sdev, &scsi_dump_cmnd, buf); + if ((ret = send_command(&scsi_dump_cmnd)) < 0) { + Warn(KERN_WARNING "MODE SENSE failed"); + return; + } + + if (buf[14] & 0x04) /* WCE is already set */ + return; + + data_len = buf[0] + 1; /* Data length in mode parameter header */ + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[12] &= 0x7f; /* clear PS */ + buf[14] |= 0x04; /* set WCE */ + + init_mode_select_command(sdev, &scsi_dump_cmnd, buf, data_len); + if ((ret = send_command(&scsi_dump_cmnd)) < 0) { + Warn("MODE SELECT failed"); + + init_sense_command(sdev, &scsi_dump_cmnd, buf); + if ((ret = send_command(&scsi_dump_cmnd)) < 0) { + Err("sense failed"); + } + } +} + +/* + * Check whether the dump device is sane enough to handle I/O. + * + * Return value: + * 0: the device is ok + * < 0: the device is not ok + * > 0: Cannot determine + */ +static int +scsi_dump_sanity_check(struct disk_dump_device *dump_device) +{ + Scsi_Device *sdev = dump_device->device; + struct Scsi_Host *host = sdev->host; + int adapter_sanity = 0; + int sanity = 0; + + if (!check_crc_module()) { + Err("checksum error. scsi dump module may be compromised."); + return -EINVAL; + } + /* + * If host's spinlock is already taken, assume it's part + * of crash and skip it. + */ + if (!scsi_device_online(sdev)) { + Warn("device not online: host %d channel %d id %d lun %d", + host->host_no, sdev->channel, sdev->id, sdev->lun); + return -EIO; + } + if (sdev->changed) { + Err("SCSI disk has been changed. Prohibiting further I/O: host %d channel %d id %d lun %d", + host->host_no, sdev->channel, sdev->id, sdev->lun); + return -EIO; + } + + if (host->hostt->dump_ops->sanity_check) { + adapter_sanity = host->hostt->dump_ops->sanity_check(sdev); + if (adapter_sanity < 0) { + Warn("adapter status is not sane"); + return adapter_sanity; + } + } + + if (!spin_is_locked(host->host_lock)) { + sanity = 0; + } else { + Warn("host_lock is held: host %d channel %d id %d lun %d", + host->host_no, sdev->channel, sdev->id, sdev->lun); + if (host->host_lock == &host->default_lock) + sanity = 1; + else + return -EIO; + } + return sanity + adapter_sanity; +} + +/* + * Try to reset the host adapter. If the adapter does not have its host reset + * handler, try to use its bus device reset handler. + */ +static int scsi_dump_reset(Scsi_Device *sdev) +{ + struct Scsi_Host *host = sdev->host; + Scsi_Host_Template *hostt = host->hostt; + char buf[256]; + int ret, i; + + init_sense_command(sdev, &scsi_dump_cmnd, buf); + + if (hostt->eh_host_reset_handler) { + spin_lock(host->host_lock); + ret = hostt->eh_host_reset_handler(&scsi_dump_cmnd); + } else if (hostt->eh_bus_reset_handler) { + spin_lock(host->host_lock); + ret = hostt->eh_bus_reset_handler(&scsi_dump_cmnd); + } else + return 0; + spin_unlock(host->host_lock); + + if (ret != SUCCESS) { + Err("adapter reset failed"); + return -EIO; + } + + /* bus reset settle time. 5sec for old disk devices */ + for (i = 0; i < 5000; i++) { + diskdump_update(); + mdelay(1); + } + + Dbg("request sense"); + if ((ret = send_command(&scsi_dump_cmnd)) < 0) { + Err("sense failed"); + return -EIO; + } + return 0; +} + +static int +scsi_dump_quiesce(struct disk_dump_device *dump_device) +{ + Scsi_Device *sdev = dump_device->device; + struct Scsi_Host *host = sdev->host; + int ret; + + if (host->hostt->dump_ops->quiesce) { + ret = host->hostt->dump_ops->quiesce(sdev); + if (ret < 0) + return ret; + } + + Dbg("do bus reset"); + if ((ret = scsi_dump_reset(sdev)) < 0) + return ret; + + if (sdev->scsi_level >= SCSI_2) + enable_write_cache(sdev); + + quiesce_ok = 1; + return 0; +} + +static int scsi_dump_rw_block(struct disk_dump_partition *dump_part, int rw, unsigned long dump_block_nr, void *buf, int len) +{ + struct disk_dump_device *dump_device = dump_part->device; + Scsi_Device *sdev = dump_device->device; + int block_nr = BLOCK_SECTOR(dump_block_nr); + int ret; + + if (!quiesce_ok) { + Err("quiesce not called"); + return -EIO; + } + + ret = init_rw_command(dump_part, sdev, &scsi_dump_cmnd, rw, + block_nr, buf, DUMP_BLOCK_SIZE * len); + if (ret < 0) { + Err("init_rw_command failed"); + return ret; + } + return send_command(&scsi_dump_cmnd); +} + +static int +scsi_dump_shutdown(struct disk_dump_device *dump_device) +{ + Scsi_Device *sdev = dump_device->device; + struct Scsi_Host *host = sdev->host; + + if (sdev->scsi_level >= SCSI_2) { + init_sync_command(sdev, &scsi_dump_cmnd); + send_command(&scsi_dump_cmnd); + } + + if (host->hostt->dump_ops->shutdown) + return host->hostt->dump_ops->shutdown(sdev); + + return 0; +} + +static void *scsi_dump_probe(dev_t dev) +{ + Scsi_Device *sdev; + + sdev = sd_find_scsi_device(dev); + if (sdev == NULL) + return NULL; + if (!sdev->host->hostt->dump_ops) + return NULL; + + return sdev; +} + + +struct disk_dump_device_ops scsi_dump_device_ops = { + .sanity_check = scsi_dump_sanity_check, + .rw_block = scsi_dump_rw_block, + .quiesce = scsi_dump_quiesce, + .shutdown = scsi_dump_shutdown, +}; + +static int scsi_dump_add_device(struct disk_dump_device *dump_device) +{ + Scsi_Device *sdev; + + sdev = dump_device->device; + if (!sdev->host->hostt->dump_ops) + return -ENOTSUPP; + + scsi_device_get(sdev); /* retval ignored ? */ + + memcpy(&dump_device->ops, &scsi_dump_device_ops, sizeof(scsi_dump_device_ops)); + if (sdev->host->max_sectors) { + dump_device->max_blocks = (sdev->sector_size * sdev->host->max_sectors) >> DUMP_BLOCK_SHIFT; + } + return 0; +} + +static void scsi_dump_remove_device(struct disk_dump_device *dump_device) +{ + Scsi_Device *sdev = dump_device->device; + + scsi_device_put(sdev); +} + +static struct disk_dump_type scsi_dump_type = { + .probe = scsi_dump_probe, + .add_device = scsi_dump_add_device, + .remove_device = scsi_dump_remove_device, + .owner = THIS_MODULE, +}; + +static int init_scsi_dump(void) +{ + int ret; + + if ((ret = register_disk_dump_type(&scsi_dump_type)) < 0) { + Err("register failed"); + return ret; + } + set_crc_modules(); + return ret; +} + +static void cleanup_scsi_dump(void) +{ + if (unregister_disk_dump_type(&scsi_dump_type) < 0) + Err("register failed"); +} + +module_init(init_scsi_dump); +module_exit(cleanup_scsi_dump); +MODULE_LICENSE("GPL"); diff -Nur linux-2.6.6.org/drivers/scsi/scsi_dump.h linux-2.6.6/drivers/scsi/scsi_dump.h --- linux-2.6.6.org/drivers/scsi/scsi_dump.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.6/drivers/scsi/scsi_dump.h 2004-05-27 09:31:07.000000000 +0900 @@ -0,0 +1,38 @@ +#ifndef _SCSI_DUMP_H +#define _SCSI_DUMP_H + +/* + * linux/drivers/scsi/scsi_dump.h + * + * Copyright (C) 2004 FUJITSU LIMITED + * Written by Nobuhiro Tachino (ntachino@jp.fujitsu.com) + * + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +struct scsi_dump_ops { + int (*sanity_check)(Scsi_Device *); + int (*quiesce)(Scsi_Device *); + int (*shutdown)(Scsi_Device *); + void (*poll)(Scsi_Device *); +}; + +/* sd.c function */ +extern Scsi_Device *sd_find_scsi_device(dev_t); + +#endif /* _SCSI_DUMP_H */ diff -Nur linux-2.6.6.org/drivers/scsi/scsi_error.c linux-2.6.6/drivers/scsi/scsi_error.c --- linux-2.6.6.org/drivers/scsi/scsi_error.c 2004-05-20 08:58:48.000000000 +0900 +++ linux-2.6.6/drivers/scsi/scsi_error.c 2004-05-27 09:24:46.000000000 +0900 @@ -402,6 +402,10 @@ **/ static void scsi_eh_done(struct scsi_cmnd *scmd) { +#if defined(CONFIG_SCSI_DUMP) || defined(CONFIG_SCSI_DUMP_MODULE) + if (crashdump_mode()) + return; +#endif /* * if the timeout handler is already running, then just set the * flag which says we finished late, and return. we have no diff -Nur linux-2.6.6.org/drivers/scsi/scsi_syms.c linux-2.6.6/drivers/scsi/scsi_syms.c --- linux-2.6.6.org/drivers/scsi/scsi_syms.c 2004-05-20 08:58:48.000000000 +0900 +++ linux-2.6.6/drivers/scsi/scsi_syms.c 2004-05-27 09:24:46.000000000 +0900 @@ -25,6 +25,7 @@ #include "scsi.h" #include "scsi_logging.h" +#include "scsi_priv.h" /* @@ -107,3 +108,5 @@ */ EXPORT_SYMBOL(scsi_add_timer); EXPORT_SYMBOL(scsi_delete_timer); + +EXPORT_SYMBOL(scsi_decide_disposition); diff -Nur linux-2.6.6.org/drivers/scsi/sd.c linux-2.6.6/drivers/scsi/sd.c --- linux-2.6.6.org/drivers/scsi/sd.c 2004-05-20 08:58:48.000000000 +0900 +++ linux-2.6.6/drivers/scsi/sd.c 2004-05-27 09:24:46.000000000 +0900 @@ -192,6 +192,21 @@ up(&sd_ref_sem); } +#if defined(CONFIG_DISKDUMP) || defined(CONFIG_DISKDUMP_MODULE) +Scsi_Device *sd_find_scsi_device(dev_t dev) +{ + struct gendisk *disk; + int part; + disk = get_gendisk(dev, &part); + if(disk && disk->private_data) + return scsi_disk(disk)->device; + else + return NULL; +} + +EXPORT_SYMBOL(sd_find_scsi_device); +#endif + /** * sd_init_command - build a scsi (read or write) command from * information in the request structure. diff -Nur linux-2.6.6.org/include/scsi/scsi_host.h linux-2.6.6/include/scsi/scsi_host.h --- linux-2.6.6.org/include/scsi/scsi_host.h 2004-05-20 08:59:07.000000000 +0900 +++ linux-2.6.6/include/scsi/scsi_host.h 2004-05-27 09:28:49.000000000 +0900 @@ -345,6 +345,11 @@ * module_init/module_exit. */ struct list_head legacy_hosts; + + /* + * operations for dump + */ + struct scsi_dump_ops *dump_ops; }; /*
next prev parent reply other threads:[~2004-05-27 12:38 UTC|newest] Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top 2004-05-27 9:33 [PATCH]Diskdump - yet another crash dump function Takao Indoh 2004-05-27 12:36 ` [1/4] " Takao Indoh 2004-05-27 12:37 ` Takao Indoh [this message] 2004-05-27 13:48 ` [2/4] " Christoph Hellwig 2004-05-28 2:13 ` Takao Indoh 2004-05-27 12:39 ` [3/4] " Takao Indoh 2004-05-27 13:51 ` Christoph Hellwig 2004-05-27 21:04 ` Ingo Molnar 2004-06-17 11:34 ` Takao Indoh 2004-06-17 12:00 ` Christoph Hellwig 2004-06-17 12:45 ` Takao Indoh 2004-06-17 12:13 ` Ingo Molnar 2004-06-17 12:18 ` Christoph Hellwig 2004-06-17 12:32 ` Ingo Molnar 2004-06-17 14:56 ` Jeff Moyer 2004-06-17 15:45 ` Nobuhiro Tachino 2004-06-17 13:04 ` Takao Indoh 2004-06-17 13:10 ` Ingo Molnar 2004-06-17 13:11 ` Ingo Molnar 2004-06-17 13:15 ` Ingo Molnar 2004-06-17 14:00 ` Takao Indoh 2004-06-17 14:45 ` Nobuhiro Tachino 2004-06-17 14:53 ` Takao Indoh 2004-06-18 12:02 ` Takao Indoh 2004-06-21 20:40 ` Nobuhiro Tachino 2004-06-22 10:19 ` Ingo Molnar 2004-06-23 12:11 ` Takao Indoh 2004-06-23 13:00 ` Takao Indoh 2004-06-21 5:46 ` Keith Owens 2004-06-21 6:25 ` Takao Indoh 2004-06-22 4:21 ` Rob Landley 2004-06-22 7:56 ` Ingo Molnar 2004-05-28 9:38 ` Takao Indoh 2004-05-27 12:40 ` [4/4] " Takao Indoh 2004-05-27 13:34 ` [Document][PATCH]Diskdump " Takao Indoh 2004-06-03 13:10 ` [PATCH]Diskdump " Pavel Machek 2004-06-04 0:44 ` Takao Indoh 2004-06-04 9:33 ` Pavel Machek
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=1EC443E7602106indou.takao@soft.fujitsu.com \ --to=indou.takao@soft.fujitsu.com \ --cc=linux-kernel@vger.kernel.org \ /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: linkBe 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; as well as URLs for NNTP newsgroup(s).