[SCSI] iscsi class, qla4xxx: fix sess/conn refcounting when find fns are used
This fixes a bug where the iscsi class/driver did not do a put_device when a sess/conn device was found. This also simplifies the interface by not having to pass in some arguments that were duplicated and did not need to be exported. Reported-by: Zhao Hongjiang <zhaohongjiang@huawei.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Acked-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
aa9f8328fc
commit
8526cb114f
|
@ -5605,6 +5605,7 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,
|
||||||
ql4_printk(KERN_ERR, ha,
|
ql4_printk(KERN_ERR, ha,
|
||||||
"%s: A non-persistent entry %s found\n",
|
"%s: A non-persistent entry %s found\n",
|
||||||
__func__, dev->kobj.name);
|
__func__, dev->kobj.name);
|
||||||
|
put_device(dev);
|
||||||
goto exit_ddb_add;
|
goto exit_ddb_add;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6112,8 +6113,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
|
||||||
int parent_type, parent_index = 0xffff;
|
int parent_type, parent_index = 0xffff;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
|
dev = iscsi_find_flashnode_conn(fnode_sess);
|
||||||
iscsi_is_flashnode_conn_dev);
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
@ -6347,6 +6347,8 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
|
||||||
rc = -ENOSYS;
|
rc = -ENOSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
put_device(dev);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1019,8 +1019,7 @@ exit_match_index:
|
||||||
/**
|
/**
|
||||||
* iscsi_get_flashnode_by_index -finds flashnode session entry by index
|
* iscsi_get_flashnode_by_index -finds flashnode session entry by index
|
||||||
* @shost: pointer to host data
|
* @shost: pointer to host data
|
||||||
* @data: pointer to data containing value to use for comparison
|
* @idx: index to match
|
||||||
* @fn: function pointer that does actual comparison
|
|
||||||
*
|
*
|
||||||
* Finds the flashnode session object for the passed index
|
* Finds the flashnode session object for the passed index
|
||||||
*
|
*
|
||||||
|
@ -1029,13 +1028,13 @@ exit_match_index:
|
||||||
* %NULL on failure
|
* %NULL on failure
|
||||||
*/
|
*/
|
||||||
static struct iscsi_bus_flash_session *
|
static struct iscsi_bus_flash_session *
|
||||||
iscsi_get_flashnode_by_index(struct Scsi_Host *shost, void *data,
|
iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
|
||||||
int (*fn)(struct device *dev, void *data))
|
|
||||||
{
|
{
|
||||||
struct iscsi_bus_flash_session *fnode_sess = NULL;
|
struct iscsi_bus_flash_session *fnode_sess = NULL;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
dev = device_find_child(&shost->shost_gendev, data, fn);
|
dev = device_find_child(&shost->shost_gendev, &idx,
|
||||||
|
flashnode_match_index);
|
||||||
if (dev)
|
if (dev)
|
||||||
fnode_sess = iscsi_dev_to_flash_session(dev);
|
fnode_sess = iscsi_dev_to_flash_session(dev);
|
||||||
|
|
||||||
|
@ -1059,18 +1058,13 @@ struct device *
|
||||||
iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
|
iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
|
||||||
int (*fn)(struct device *dev, void *data))
|
int (*fn)(struct device *dev, void *data))
|
||||||
{
|
{
|
||||||
struct device *dev;
|
return device_find_child(&shost->shost_gendev, data, fn);
|
||||||
|
|
||||||
dev = device_find_child(&shost->shost_gendev, data, fn);
|
|
||||||
return dev;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
|
EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iscsi_find_flashnode_conn - finds flashnode connection entry
|
* iscsi_find_flashnode_conn - finds flashnode connection entry
|
||||||
* @fnode_sess: pointer to parent flashnode session entry
|
* @fnode_sess: pointer to parent flashnode session entry
|
||||||
* @data: pointer to data containing value to use for comparison
|
|
||||||
* @fn: function pointer that does actual comparison
|
|
||||||
*
|
*
|
||||||
* Finds the flashnode connection object comparing the data passed using logic
|
* Finds the flashnode connection object comparing the data passed using logic
|
||||||
* defined in passed function pointer
|
* defined in passed function pointer
|
||||||
|
@ -1080,14 +1074,10 @@ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
|
||||||
* %NULL on failure
|
* %NULL on failure
|
||||||
*/
|
*/
|
||||||
struct device *
|
struct device *
|
||||||
iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
|
iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
|
||||||
void *data,
|
|
||||||
int (*fn)(struct device *dev, void *data))
|
|
||||||
{
|
{
|
||||||
struct device *dev;
|
return device_find_child(&fnode_sess->dev, NULL,
|
||||||
|
iscsi_is_flashnode_conn_dev);
|
||||||
dev = device_find_child(&fnode_sess->dev, data, fn);
|
|
||||||
return dev;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
|
EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
|
||||||
|
|
||||||
|
@ -2808,7 +2798,7 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
|
||||||
struct iscsi_bus_flash_session *fnode_sess;
|
struct iscsi_bus_flash_session *fnode_sess;
|
||||||
struct iscsi_bus_flash_conn *fnode_conn;
|
struct iscsi_bus_flash_conn *fnode_conn;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
uint32_t *idx;
|
uint32_t idx;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!transport->set_flashnode_param) {
|
if (!transport->set_flashnode_param) {
|
||||||
|
@ -2824,25 +2814,27 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = &ev->u.set_flashnode.flashnode_idx;
|
idx = ev->u.set_flashnode.flashnode_idx;
|
||||||
fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
|
fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
|
||||||
flashnode_match_index);
|
|
||||||
if (!fnode_sess) {
|
if (!fnode_sess) {
|
||||||
pr_err("%s could not find flashnode %u for host no %u\n",
|
pr_err("%s could not find flashnode %u for host no %u\n",
|
||||||
__func__, *idx, ev->u.set_flashnode.host_no);
|
__func__, idx, ev->u.set_flashnode.host_no);
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
|
dev = iscsi_find_flashnode_conn(fnode_sess);
|
||||||
iscsi_is_flashnode_conn_dev);
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_sess;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnode_conn = iscsi_dev_to_flash_conn(dev);
|
fnode_conn = iscsi_dev_to_flash_conn(dev);
|
||||||
err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
|
err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
|
||||||
|
put_device(dev);
|
||||||
|
|
||||||
|
put_sess:
|
||||||
|
put_device(&fnode_sess->dev);
|
||||||
|
|
||||||
put_host:
|
put_host:
|
||||||
scsi_host_put(shost);
|
scsi_host_put(shost);
|
||||||
|
@ -2891,7 +2883,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
|
||||||
{
|
{
|
||||||
struct Scsi_Host *shost;
|
struct Scsi_Host *shost;
|
||||||
struct iscsi_bus_flash_session *fnode_sess;
|
struct iscsi_bus_flash_session *fnode_sess;
|
||||||
uint32_t *idx;
|
uint32_t idx;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!transport->del_flashnode) {
|
if (!transport->del_flashnode) {
|
||||||
|
@ -2907,17 +2899,17 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = &ev->u.del_flashnode.flashnode_idx;
|
idx = ev->u.del_flashnode.flashnode_idx;
|
||||||
fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
|
fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
|
||||||
flashnode_match_index);
|
|
||||||
if (!fnode_sess) {
|
if (!fnode_sess) {
|
||||||
pr_err("%s could not find flashnode %u for host no %u\n",
|
pr_err("%s could not find flashnode %u for host no %u\n",
|
||||||
__func__, *idx, ev->u.del_flashnode.host_no);
|
__func__, idx, ev->u.del_flashnode.host_no);
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = transport->del_flashnode(fnode_sess);
|
err = transport->del_flashnode(fnode_sess);
|
||||||
|
put_device(&fnode_sess->dev);
|
||||||
|
|
||||||
put_host:
|
put_host:
|
||||||
scsi_host_put(shost);
|
scsi_host_put(shost);
|
||||||
|
@ -2933,7 +2925,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
|
||||||
struct iscsi_bus_flash_session *fnode_sess;
|
struct iscsi_bus_flash_session *fnode_sess;
|
||||||
struct iscsi_bus_flash_conn *fnode_conn;
|
struct iscsi_bus_flash_conn *fnode_conn;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
uint32_t *idx;
|
uint32_t idx;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!transport->login_flashnode) {
|
if (!transport->login_flashnode) {
|
||||||
|
@ -2949,25 +2941,27 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = &ev->u.login_flashnode.flashnode_idx;
|
idx = ev->u.login_flashnode.flashnode_idx;
|
||||||
fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
|
fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
|
||||||
flashnode_match_index);
|
|
||||||
if (!fnode_sess) {
|
if (!fnode_sess) {
|
||||||
pr_err("%s could not find flashnode %u for host no %u\n",
|
pr_err("%s could not find flashnode %u for host no %u\n",
|
||||||
__func__, *idx, ev->u.login_flashnode.host_no);
|
__func__, idx, ev->u.login_flashnode.host_no);
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
|
dev = iscsi_find_flashnode_conn(fnode_sess);
|
||||||
iscsi_is_flashnode_conn_dev);
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_sess;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnode_conn = iscsi_dev_to_flash_conn(dev);
|
fnode_conn = iscsi_dev_to_flash_conn(dev);
|
||||||
err = transport->login_flashnode(fnode_sess, fnode_conn);
|
err = transport->login_flashnode(fnode_sess, fnode_conn);
|
||||||
|
put_device(dev);
|
||||||
|
|
||||||
|
put_sess:
|
||||||
|
put_device(&fnode_sess->dev);
|
||||||
|
|
||||||
put_host:
|
put_host:
|
||||||
scsi_host_put(shost);
|
scsi_host_put(shost);
|
||||||
|
@ -2983,7 +2977,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
|
||||||
struct iscsi_bus_flash_session *fnode_sess;
|
struct iscsi_bus_flash_session *fnode_sess;
|
||||||
struct iscsi_bus_flash_conn *fnode_conn;
|
struct iscsi_bus_flash_conn *fnode_conn;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
uint32_t *idx;
|
uint32_t idx;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!transport->logout_flashnode) {
|
if (!transport->logout_flashnode) {
|
||||||
|
@ -2999,26 +2993,28 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = &ev->u.logout_flashnode.flashnode_idx;
|
idx = ev->u.logout_flashnode.flashnode_idx;
|
||||||
fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
|
fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
|
||||||
flashnode_match_index);
|
|
||||||
if (!fnode_sess) {
|
if (!fnode_sess) {
|
||||||
pr_err("%s could not find flashnode %u for host no %u\n",
|
pr_err("%s could not find flashnode %u for host no %u\n",
|
||||||
__func__, *idx, ev->u.logout_flashnode.host_no);
|
__func__, idx, ev->u.logout_flashnode.host_no);
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
|
dev = iscsi_find_flashnode_conn(fnode_sess);
|
||||||
iscsi_is_flashnode_conn_dev);
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto put_host;
|
goto put_sess;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnode_conn = iscsi_dev_to_flash_conn(dev);
|
fnode_conn = iscsi_dev_to_flash_conn(dev);
|
||||||
|
|
||||||
err = transport->logout_flashnode(fnode_sess, fnode_conn);
|
err = transport->logout_flashnode(fnode_sess, fnode_conn);
|
||||||
|
put_device(dev);
|
||||||
|
|
||||||
|
put_sess:
|
||||||
|
put_device(&fnode_sess->dev);
|
||||||
|
|
||||||
put_host:
|
put_host:
|
||||||
scsi_host_put(shost);
|
scsi_host_put(shost);
|
||||||
|
|
|
@ -471,14 +471,10 @@ iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess);
|
||||||
extern void iscsi_destroy_all_flashnode(struct Scsi_Host *shost);
|
extern void iscsi_destroy_all_flashnode(struct Scsi_Host *shost);
|
||||||
extern int iscsi_flashnode_bus_match(struct device *dev,
|
extern int iscsi_flashnode_bus_match(struct device *dev,
|
||||||
struct device_driver *drv);
|
struct device_driver *drv);
|
||||||
extern int iscsi_is_flashnode_conn_dev(struct device *dev, void *data);
|
|
||||||
|
|
||||||
extern struct device *
|
extern struct device *
|
||||||
iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
|
iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
|
||||||
int (*fn)(struct device *dev, void *data));
|
int (*fn)(struct device *dev, void *data));
|
||||||
|
|
||||||
extern struct device *
|
extern struct device *
|
||||||
iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
|
iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess);
|
||||||
void *data,
|
|
||||||
int (*fn)(struct device *dev, void *data));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue