The attach patch converts scsi_debug to use the virtual scsi bus. It was built against scsi-rc-fixes-2.6.
The interface has changed a little. Here is an example of adding and removing a single host:
cd /sys/bus/scsi_host/drivers/scsi_debug [EMAIL PROTECTED] scsi_debug]# ls add_host dev_size_mb every_nth module num_parts opts scsi_level delay dsense max_luns num_hosts num_tgts ptype [EMAIL PROTECTED] scsi_debug]# echo 1 > add_host [EMAIL PROTECTED] scsi_debug]# ls add_host dev_size_mb every_nth module num_parts opts scsi_level delay dsense max_luns num_hosts num_tgts ptype virt_host4 [EMAIL PROTECTED] scsi_debug]# cd virt_host4/ [EMAIL PROTECTED] virt_host4]# ls detach_state driver host4 power remove_host [EMAIL PROTECTED] virt_host4]# echo 1 > remove_host
Mike
--- scsi-rc-fixes-2.6.orig/drivers/scsi/scsi_debug.c 2005-02-04 22:11:25.000000000 -0800 +++ scsi-rc-fixes-2.6.work/drivers/scsi/scsi_debug.c 2005-02-11 00:54:13.000000000 -0800 @@ -44,6 +44,7 @@ #include <linux/blkdev.h> #include "scsi.h" #include <scsi/scsi_host.h> +#include <scsi/scsi_driver.h> #include <scsi/scsicam.h> #include <linux/stat.h> @@ -112,7 +113,7 @@ static const char * scsi_debug_version_d * or "peripheral device" addressing (value 0) */ #define SAM2_LUN_ADDRESS_METHOD 0 -static int scsi_debug_add_host = DEF_NUM_HOST; +static int scsi_debug_num_hosts; static int scsi_debug_delay = DEF_DELAY; static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; static int scsi_debug_every_nth = DEF_EVERY_NTH; @@ -161,13 +162,9 @@ struct sdebug_dev_info { struct sdebug_host_info { struct list_head host_list; struct Scsi_Host *shost; - struct device dev; struct list_head dev_info_list; }; -#define to_sdebug_host(d) \ - container_of(d, struct sdebug_host_info, dev) - static LIST_HEAD(sdebug_host_list); static DEFINE_SPINLOCK(sdebug_host_list_lock); @@ -218,21 +215,12 @@ static DEFINE_RWLOCK(atomic_rw); static char sdebug_proc_name[] = "scsi_debug"; -static int sdebug_driver_probe(struct device *); -static int sdebug_driver_remove(struct device *); -static struct bus_type pseudo_lld_bus; - -static struct device_driver sdebug_driverfs_driver = { - .name = sdebug_proc_name, - .bus = &pseudo_lld_bus, - .probe = sdebug_driver_probe, - .remove = sdebug_driver_remove, -}; - static const int check_condition_result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; /* function declarations */ +static int sdebug_driver_probe(struct scsi_virt_host *); +static int sdebug_driver_remove(struct scsi_virt_host *); static int resp_inquiry(struct scsi_cmnd * SCpnt, int target, struct sdebug_dev_info * devip); static int resp_requests(struct scsi_cmnd * SCpnt, @@ -266,17 +254,11 @@ static void stop_all_queued(void); static int stop_queued_cmnd(struct scsi_cmnd * cmnd); static int inquiry_evpd_83(unsigned char * arr, int dev_id_num, const char * dev_id_str, int dev_id_str_len); -static void do_create_driverfs_files(void); -static void do_remove_driverfs_files(void); -static int sdebug_add_adapter(void); -static void sdebug_remove_adapter(void); +static int sdebug_add_adapter(struct sdebug_host_info * sdbg_host); +static void sdebug_remove_adapter(struct sdebug_host_info * sdbg_host); static void sdebug_max_tgts_luns(void); -static struct device pseudo_primary; -static struct bus_type pseudo_lld_bus; - - static int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) { @@ -1054,7 +1036,7 @@ static struct sdebug_dev_info * devInfoR if (devip) return devip; - sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata; + sdbg_host = (struct sdebug_host_info *) sdev->host->hostdata; if(! sdbg_host) { printk(KERN_ERR "Host info NULL\n"); return NULL; @@ -1181,7 +1163,7 @@ static int scsi_debug_bus_reset(struct s printk(KERN_INFO "scsi_debug: bus_reset\n"); ++num_bus_resets; if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { - sdbg_host = *(struct sdebug_host_info **) hp->hostdata; + sdbg_host = (struct sdebug_host_info *) hp->hostdata; if (sdbg_host) { list_for_each_entry(dev_info, &sdbg_host->dev_info_list, @@ -1379,7 +1361,6 @@ static int schedule_resp(struct scsi_cmn * of sysfs parameters (which module_param doesn't yet support). * Sysfs parameters defined explicitly below. */ -module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */ module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */ module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0); module_param_named(dsense, scsi_debug_dsense, int, 0); @@ -1633,78 +1614,42 @@ static ssize_t sdebug_scsi_level_show(st } DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL); -static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_num_hosts_show(struct device_driver * ddp, char * buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_hosts); } +DRIVER_ATTR(num_hosts, S_IRUGO, sdebug_num_hosts_show, NULL); -static ssize_t sdebug_add_host_store(struct device_driver * ddp, - const char * buf, size_t count) -{ - int delta_hosts; - char work[20]; +static struct attribute *sdebug_attrs[] = { + &driver_attr_num_hosts.attr, + &driver_attr_delay.attr, + &driver_attr_dev_size_mb.attr, + &driver_attr_dsense.attr, + &driver_attr_every_nth.attr, + &driver_attr_max_luns.attr, + &driver_attr_num_tgts.attr, + &driver_attr_num_parts.attr, + &driver_attr_ptype.attr, + &driver_attr_opts.attr, + &driver_attr_scsi_level.attr, + NULL, +}; - if (1 != sscanf(buf, "%10s", work)) - return -EINVAL; - { /* temporary hack around sscanf() problem with -ve nums */ - int neg = 0; - - if ('-' == *work) - neg = 1; - if (1 != sscanf(work + neg, "%d", &delta_hosts)) - return -EINVAL; - if (neg) - delta_hosts = -delta_hosts; - } - if (delta_hosts > 0) { - do { - sdebug_add_adapter(); - } while (--delta_hosts); - } else if (delta_hosts < 0) { - do { - sdebug_remove_adapter(); - } while (++delta_hosts); - } - return count; -} -DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, - sdebug_add_host_store); +static struct attribute_group sdebug_attr_group = { + .attrs = sdebug_attrs, +}; -static void do_create_driverfs_files(void) -{ - driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); -} - -static void do_remove_driverfs_files(void) -{ - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ptype); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_parts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dsense); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); -} +static struct scsi_host_driver sdebug_driverfs_driver = { + .owner = THIS_MODULE, + .name = sdebug_proc_name, + .attrs = &sdebug_attr_group, + .probe = sdebug_driver_probe, + .remove = sdebug_driver_remove, +}; static int __init scsi_debug_init(void) { unsigned long sz; - int host_to_add; - int k; if (scsi_debug_dev_size_mb < 1) scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ @@ -1740,42 +1685,19 @@ static int __init scsi_debug_init(void) init_all_queued(); - device_register(&pseudo_primary); - bus_register(&pseudo_lld_bus); - driver_register(&sdebug_driverfs_driver); - do_create_driverfs_files(); - + scsi_register_host_driver(&sdebug_driverfs_driver); sdebug_driver_template.proc_name = (char *)sdebug_proc_name; - host_to_add = scsi_debug_add_host; - scsi_debug_add_host = 0; - - for (k = 0; k < host_to_add; k++) { - if (sdebug_add_adapter()) { - printk(KERN_ERR "scsi_debug_init: " - "sdebug_add_adapter failed k=%d\n", k); - break; - } - } - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { - printk(KERN_INFO "scsi_debug_init: built %d host(s)\n", - scsi_debug_add_host); + printk(KERN_INFO "scsi_debug driver\n"); } return 0; } static void __exit scsi_debug_exit(void) { - int k = scsi_debug_add_host; - stop_all_queued(); - for (; k; k--) - sdebug_remove_adapter(); - do_remove_driverfs_files(); - driver_unregister(&sdebug_driverfs_driver); - bus_unregister(&pseudo_lld_bus); - device_unregister(&pseudo_primary); + scsi_unregister_host_driver(&sdebug_driverfs_driver); vfree(fake_storep); } @@ -1783,52 +1705,13 @@ static void __exit scsi_debug_exit(void) device_initcall(scsi_debug_init); module_exit(scsi_debug_exit); -void pseudo_0_release(struct device * dev) -{ - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); -} - -static struct device pseudo_primary = { - .bus_id = "pseudo_0", - .release = pseudo_0_release, -}; - -static int pseudo_lld_bus_match(struct device *dev, - struct device_driver *dev_driver) -{ - return 1; -} - -static struct bus_type pseudo_lld_bus = { - .name = "pseudo", - .match = pseudo_lld_bus_match, -}; - -static void sdebug_release_adapter(struct device * dev) -{ - struct sdebug_host_info *sdbg_host; - - sdbg_host = to_sdebug_host(dev); - kfree(sdbg_host); -} - -static int sdebug_add_adapter(void) +static int sdebug_add_adapter(struct sdebug_host_info * sdbg_host) { int k, devs_per_host; int error = 0; - struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *sdbg_devinfo; struct list_head *lh, *lh_sf; - sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL); - - if (NULL == sdbg_host) { - printk(KERN_ERR "%s: out of memory at line %d\n", - __FUNCTION__, __LINE__); - return -ENOMEM; - } - memset(sdbg_host, 0, sizeof(*sdbg_host)); INIT_LIST_HEAD(&sdbg_host->dev_info_list); @@ -1851,17 +1734,7 @@ static int sdebug_add_adapter(void) list_add_tail(&sdbg_host->host_list, &sdebug_host_list); spin_unlock(&sdebug_host_list_lock); - sdbg_host->dev.bus = &pseudo_lld_bus; - sdbg_host->dev.parent = &pseudo_primary; - sdbg_host->dev.release = &sdebug_release_adapter; - sprintf(sdbg_host->dev.bus_id, "adapter%d", scsi_debug_add_host); - - error = device_register(&sdbg_host->dev); - - if (error) - goto clean; - - ++scsi_debug_add_host; + ++scsi_debug_num_hosts; return error; clean: @@ -1872,77 +1745,64 @@ clean: kfree(sdbg_devinfo); } - kfree(sdbg_host); return error; } -static void sdebug_remove_adapter(void) +static void sdebug_remove_adapter(struct sdebug_host_info * sdbg_host) { - struct sdebug_host_info * sdbg_host = NULL; - spin_lock(&sdebug_host_list_lock); - if (!list_empty(&sdebug_host_list)) { - sdbg_host = list_entry(sdebug_host_list.prev, - struct sdebug_host_info, host_list); - list_del(&sdbg_host->host_list); - } + list_del(&sdbg_host->host_list); spin_unlock(&sdebug_host_list_lock); - if (!sdbg_host) - return; - - device_unregister(&sdbg_host->dev); - --scsi_debug_add_host; + --scsi_debug_num_hosts; } -static int sdebug_driver_probe(struct device * dev) +static int sdebug_driver_probe(struct scsi_virt_host * vhost) { int error = 0; struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; - sdbg_host = to_sdebug_host(dev); - - hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); + hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(*sdbg_host)); if (NULL == hpnt) { printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__); error = -ENODEV; return error; } - sdbg_host->shost = hpnt; - *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; + sdbg_host = (struct sdebug_host_info *)hpnt->hostdata; + if (sdebug_add_adapter(sdbg_host)) + goto failed; + sdbg_host->shost = hpnt; + dev_set_drvdata(&vhost->dev, sdbg_host); + if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) hpnt->max_id = scsi_debug_num_tgts + 1; else hpnt->max_id = scsi_debug_num_tgts; hpnt->max_lun = scsi_debug_max_luns; - error = scsi_add_host(hpnt, &sdbg_host->dev); - if (error) { - printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); - error = -ENODEV; - scsi_host_put(hpnt); - } else - scsi_scan_host(hpnt); - + error = scsi_add_host(hpnt, &vhost->dev); + if (error) + goto failed; + scsi_scan_host(hpnt); return error; + + failed: + printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); + scsi_host_put(hpnt); + return -ENODEV; } -static int sdebug_driver_remove(struct device * dev) +static int sdebug_driver_remove(struct scsi_virt_host * vhost) { struct list_head *lh, *lh_sf; struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *sdbg_devinfo; - sdbg_host = to_sdebug_host(dev); - - if (!sdbg_host) { - printk(KERN_ERR "%s: Unable to locate host info\n", - __FUNCTION__); - return -ENODEV; - } + sdbg_host = dev_get_drvdata(&vhost->dev); + sdebug_remove_adapter(sdbg_host); scsi_remove_host(sdbg_host->shost);