提交 8526cb11 编写于 作者: M Mike Christie 提交者: James Bottomley

[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: NZhao Hongjiang <zhaohongjiang@huawei.com>
Signed-off-by: NMike Christie <michaelc@cs.wisc.edu>
Acked-by: NVikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
上级 aa9f8328
...@@ -5605,6 +5605,7 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, ...@@ -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, ...@@ -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, ...@@ -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 @@ static int flashnode_match_index(struct device *dev, void *data) ...@@ -1019,8 +1019,7 @@ static int flashnode_match_index(struct device *dev, void *data)
/** /**
* 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 @@ static int flashnode_match_index(struct device *dev, void *data) ...@@ -1029,13 +1028,13 @@ static int flashnode_match_index(struct device *dev, void *data)
* %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 * ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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); ...@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册