提交 6c10db72 编写于 作者: C Chandra Seetharaman 提交者: James Bottomley

[SCSI] scsi_dh: Reference count scsi_dh_attach

Problem reported: http://marc.info/?l=dm-devel&m=124585978305866&w=2

scsi_dh does not do a refernce count for attach/detach, and this affects
the way it is supposed to work with multipath when a device is not
in the dev_list of the hardware handler.

This patch adds a reference count that counts each attach.
Signed-off-by: NChandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: NJames Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: NJames Bottomley <James.Bottomley@suse.de>
上级 b4567ca6
...@@ -153,12 +153,24 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev, ...@@ -153,12 +153,24 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev,
if (sdev->scsi_dh_data) { if (sdev->scsi_dh_data) {
if (sdev->scsi_dh_data->scsi_dh != scsi_dh) if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
err = -EBUSY; err = -EBUSY;
} else if (scsi_dh->attach) else
kref_get(&sdev->scsi_dh_data->kref);
} else if (scsi_dh->attach) {
err = scsi_dh->attach(sdev); err = scsi_dh->attach(sdev);
if (!err) {
kref_init(&sdev->scsi_dh_data->kref);
sdev->scsi_dh_data->sdev = sdev;
}
}
return err; return err;
} }
static void __detach_handler (struct kref *kref)
{
struct scsi_dh_data *scsi_dh_data = container_of(kref, struct scsi_dh_data, kref);
scsi_dh_data->scsi_dh->detach(scsi_dh_data->sdev);
}
/* /*
* scsi_dh_handler_detach - Detach a device handler from a device * scsi_dh_handler_detach - Detach a device handler from a device
* @sdev - SCSI device the device handler should be detached from * @sdev - SCSI device the device handler should be detached from
...@@ -180,7 +192,7 @@ static void scsi_dh_handler_detach(struct scsi_device *sdev, ...@@ -180,7 +192,7 @@ static void scsi_dh_handler_detach(struct scsi_device *sdev,
scsi_dh = sdev->scsi_dh_data->scsi_dh; scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (scsi_dh && scsi_dh->detach) if (scsi_dh && scsi_dh->detach)
scsi_dh->detach(sdev); kref_put(&sdev->scsi_dh_data->kref, __detach_handler);
} }
/* /*
...@@ -474,7 +486,6 @@ int scsi_dh_attach(struct request_queue *q, const char *name) ...@@ -474,7 +486,6 @@ int scsi_dh_attach(struct request_queue *q, const char *name)
if (!err) { if (!err) {
err = scsi_dh_handler_attach(sdev, scsi_dh); err = scsi_dh_handler_attach(sdev, scsi_dh);
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
} }
return err; return err;
...@@ -505,10 +516,8 @@ void scsi_dh_detach(struct request_queue *q) ...@@ -505,10 +516,8 @@ void scsi_dh_detach(struct request_queue *q)
return; return;
if (sdev->scsi_dh_data) { if (sdev->scsi_dh_data) {
/* if sdev is not on internal list, detach */
scsi_dh = sdev->scsi_dh_data->scsi_dh; scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (!device_handler_match(scsi_dh, sdev)) scsi_dh_handler_detach(sdev, scsi_dh);
scsi_dh_handler_detach(sdev, scsi_dh);
} }
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
} }
......
...@@ -191,6 +191,8 @@ struct scsi_device_handler { ...@@ -191,6 +191,8 @@ struct scsi_device_handler {
struct scsi_dh_data { struct scsi_dh_data {
struct scsi_device_handler *scsi_dh; struct scsi_device_handler *scsi_dh;
struct scsi_device *sdev;
struct kref kref;
char buf[0]; char buf[0];
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册