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

Commit 8526cb11 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley
Browse files

[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: default avatarZhao Hongjiang <zhaohongjiang@huawei.com>
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Acked-by: default avatarVikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent aa9f8328
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -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;
}
}


+43 −47
Original line number Original line Diff line number Diff line
@@ -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);
+2 −6
Original line number Original line Diff line number Diff line
@@ -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