Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 086b91d0 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley
Browse files

scsi_dh: integrate into the core SCSI code



Stop building scsi_dh as a separate module and integrate it fully into the
core SCSI code with explicit callouts at bus scan time.  For now the
callouts are placed at the same point as the old bus notifiers were called,
but in the future we will be able to look at ALUA INQUIRY data earlier on.

Note that this also means that the device handler modules need to be loaded
by the time we scan the bus.  The next patches will add support for
autoloading device handlers at bus scan time to make sure they are always
loaded if they are enabled in the kernel config.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Acked-by: default avatarMike Snitzer <snitzer@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent daaa858b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -172,6 +172,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
scsi_mod-y			+= scsi_trace.o scsi_logging.o
scsi_mod-y			+= scsi_trace.o scsi_logging.o
scsi_mod-$(CONFIG_PM)		+= scsi_pm.o
scsi_mod-$(CONFIG_PM)		+= scsi_pm.o
scsi_mod-$(CONFIG_SCSI_DH)	+= scsi_dh.o


hv_storvsc-y			:= storvsc_drv.o
hv_storvsc-y			:= storvsc_drv.o


+1 −1
Original line number Original line Diff line number Diff line
@@ -3,7 +3,7 @@
#
#


menuconfig SCSI_DH
menuconfig SCSI_DH
	tristate "SCSI Device Handlers"
	bool "SCSI Device Handlers"
	depends on SCSI
	depends on SCSI
	default n
	default n
	help
	help
+0 −1
Original line number Original line Diff line number Diff line
#
#
# SCSI Device Handler
# SCSI Device Handler
#
#
obj-$(CONFIG_SCSI_DH)		+= scsi_dh.o
obj-$(CONFIG_SCSI_DH_RDAC)	+= scsi_dh_rdac.o
obj-$(CONFIG_SCSI_DH_RDAC)	+= scsi_dh_rdac.o
obj-$(CONFIG_SCSI_DH_HP_SW)	+= scsi_dh_hp_sw.o
obj-$(CONFIG_SCSI_DH_HP_SW)	+= scsi_dh_hp_sw.o
obj-$(CONFIG_SCSI_DH_EMC)	+= scsi_dh_emc.o
obj-$(CONFIG_SCSI_DH_EMC)	+= scsi_dh_emc.o
+12 −171
Original line number Original line Diff line number Diff line
@@ -57,15 +57,8 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name)
	return dh;
	return dh;
}
}


/*
 * device_handler_match_function - Match a device handler to a device
 * @sdev - SCSI device to be tested
 *
 * Tests @sdev against the match function of all registered device_handler.
 * Returns the found device handler or NULL if not found.
 */
static struct scsi_device_handler *
static struct scsi_device_handler *
device_handler_match_function(struct scsi_device *sdev)
device_handler_match(struct scsi_device *sdev)
{
{
	struct scsi_device_handler *tmp_dh, *found_dh = NULL;
	struct scsi_device_handler *tmp_dh, *found_dh = NULL;


@@ -80,29 +73,6 @@ device_handler_match_function(struct scsi_device *sdev)
	return found_dh;
	return found_dh;
}
}


/*
 * device_handler_match - Attach a device handler to a device
 * @scsi_dh - The device handler to match against or NULL
 * @sdev - SCSI device to be tested against @scsi_dh
 *
 * Tests @sdev against the device handler @scsi_dh or against
 * all registered device_handler if @scsi_dh == NULL.
 * Returns the found device handler or NULL if not found.
 */
static struct scsi_device_handler *
device_handler_match(struct scsi_device_handler *scsi_dh,
		     struct scsi_device *sdev)
{
	struct scsi_device_handler *found_dh;

	found_dh = device_handler_match_function(sdev);

	if (scsi_dh && found_dh != scsi_dh)
		found_dh = NULL;

	return found_dh;
}

/*
/*
 * scsi_dh_handler_attach - Attach a device handler to a device
 * scsi_dh_handler_attach - Attach a device handler to a device
 * @sdev - SCSI device the device handler should attach to
 * @sdev - SCSI device the device handler should attach to
@@ -212,119 +182,26 @@ static struct device_attribute scsi_dh_state_attr =
	__ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
	__ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
	       store_dh_state);
	       store_dh_state);


/*
int scsi_dh_add_device(struct scsi_device *sdev)
 * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh
 */
static int scsi_dh_sysfs_attr_add(struct device *dev, void *data)
{
{
	struct scsi_device *sdev;
	struct scsi_device_handler *devinfo;
	int err;
	int err;


	if (!scsi_is_sdev_device(dev))
	err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
		return 0;
	if (err)

		return err;
	sdev = to_scsi_device(dev);

	err = device_create_file(&sdev->sdev_gendev,
				 &scsi_dh_state_attr);

	return 0;
}

/*
 * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh
 */
static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data)
{
	struct scsi_device *sdev;

	if (!scsi_is_sdev_device(dev))
		return 0;

	sdev = to_scsi_device(dev);

	device_remove_file(&sdev->sdev_gendev,
			   &scsi_dh_state_attr);

	return 0;
}

/*
 * scsi_dh_notifier - notifier chain callback
 */
static int scsi_dh_notifier(struct notifier_block *nb,
			    unsigned long action, void *data)
{
	struct device *dev = data;
	struct scsi_device *sdev;
	int err = 0;
	struct scsi_device_handler *devinfo = NULL;

	if (!scsi_is_sdev_device(dev))
		return 0;

	sdev = to_scsi_device(dev);


	if (action == BUS_NOTIFY_ADD_DEVICE) {
	devinfo = device_handler_match(sdev);
		err = device_create_file(dev, &scsi_dh_state_attr);
		/* don't care about err */
		devinfo = device_handler_match(NULL, sdev);
	if (devinfo)
	if (devinfo)
		err = scsi_dh_handler_attach(sdev, devinfo);
		err = scsi_dh_handler_attach(sdev, devinfo);
	} else if (action == BUS_NOTIFY_DEL_DEVICE) {
		device_remove_file(dev, &scsi_dh_state_attr);
		if (sdev->scsi_dh_data)
			scsi_dh_handler_detach(sdev);
	}
	return err;
	return err;
}
}


/*
void scsi_dh_remove_device(struct scsi_device *sdev)
 * scsi_dh_notifier_add - Callback for scsi_register_device_handler
 */
static int scsi_dh_notifier_add(struct device *dev, void *data)
{
{
	struct scsi_device_handler *scsi_dh = data;
	if (sdev->scsi_dh_data)
	struct scsi_device *sdev;

	if (!scsi_is_sdev_device(dev))
		return 0;

	if (!get_device(dev))
		return 0;

	sdev = to_scsi_device(dev);

	if (device_handler_match(scsi_dh, sdev))
		scsi_dh_handler_attach(sdev, scsi_dh);

	put_device(dev);

	return 0;
}

/*
 * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
 */
static int scsi_dh_notifier_remove(struct device *dev, void *data)
{
	struct scsi_device_handler *scsi_dh = data;
	struct scsi_device *sdev;

	if (!scsi_is_sdev_device(dev))
		return 0;

	if (!get_device(dev))
		return 0;

	sdev = to_scsi_device(dev);

	if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh == scsi_dh)
		scsi_dh_handler_detach(sdev);
		scsi_dh_handler_detach(sdev);

	device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
	put_device(dev);

	return 0;
}
}


/*
/*
@@ -346,7 +223,6 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
	list_add(&scsi_dh->list, &scsi_dh_list);
	list_add(&scsi_dh->list, &scsi_dh_list);
	spin_unlock(&list_lock);
	spin_unlock(&list_lock);


	bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
	printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
	printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);


	return SCSI_DH_OK;
	return SCSI_DH_OK;
@@ -362,13 +238,9 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler);
 */
 */
int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
{
{

	if (!__scsi_dh_lookup(scsi_dh->name))
	if (!__scsi_dh_lookup(scsi_dh->name))
		return -ENODEV;
		return -ENODEV;


	bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
			 scsi_dh_notifier_remove);

	spin_lock(&list_lock);
	spin_lock(&list_lock);
	list_del(&scsi_dh->list);
	list_del(&scsi_dh->list);
	spin_unlock(&list_lock);
	spin_unlock(&list_lock);
@@ -538,34 +410,3 @@ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
	return handler_name;
	return handler_name;
}
}
EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name);
EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name);

static struct notifier_block scsi_dh_nb = {
	.notifier_call = scsi_dh_notifier
};

static int __init scsi_dh_init(void)
{
	int r;

	r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);

	if (!r)
		bus_for_each_dev(&scsi_bus_type, NULL, NULL,
				 scsi_dh_sysfs_attr_add);

	return r;
}

static void __exit scsi_dh_exit(void)
{
	bus_for_each_dev(&scsi_bus_type, NULL, NULL,
			 scsi_dh_sysfs_attr_remove);
	bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
}

module_init(scsi_dh_init);
module_exit(scsi_dh_exit);

MODULE_DESCRIPTION("SCSI device handler");
MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
MODULE_LICENSE("GPL");
+9 −0
Original line number Original line Diff line number Diff line
@@ -170,6 +170,15 @@ static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
extern struct async_domain scsi_sd_pm_domain;
extern struct async_domain scsi_sd_pm_domain;
extern struct async_domain scsi_sd_probe_domain;
extern struct async_domain scsi_sd_probe_domain;


/* scsi_dh.c */
#ifdef CONFIG_SCSI_DH
int scsi_dh_add_device(struct scsi_device *sdev);
void scsi_dh_remove_device(struct scsi_device *sdev);
#else
static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; }
static inline void scsi_dh_remove_device(struct scsi_device *sdev) { }
#endif

/* 
/* 
 * internal scsi timeout functions: for use by mid-layer and transport
 * internal scsi timeout functions: for use by mid-layer and transport
 * classes.
 * classes.
Loading