mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-14 17:40:41 +09:00
vhost-scsi: Take configfs group dependency during VHOST_SCSI_SET_ENDPOINT
commit ab8edab132 upstream.
This patch addresses a bug where individual vhost-scsi configfs endpoint
groups can be removed from below while active exports to QEMU userspace
still exist, resulting in an OOPs.
It adds a configfs_depend_item() in vhost_scsi_set_endpoint() to obtain
an explicit dependency on se_tpg->tpg_group in order to prevent individual
vhost-scsi WWPN endpoints from being released via normal configfs methods
while an QEMU ioctl reference still exists.
Also, add matching configfs_undepend_item() in vhost_scsi_clear_endpoint()
to release the dependency, once QEMU's reference to the individual group
at /sys/kernel/config/target/vhost/$WWPN/$TPGT is released.
(Fix up vhost_scsi_clear_endpoint() error path - DanC)
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f2da3c240d
commit
3ce3a8612d
@@ -1150,6 +1150,7 @@ static int vhost_scsi_set_endpoint(
|
||||
struct vhost_scsi *vs,
|
||||
struct vhost_scsi_target *t)
|
||||
{
|
||||
struct se_portal_group *se_tpg;
|
||||
struct tcm_vhost_tport *tv_tport;
|
||||
struct tcm_vhost_tpg *tv_tpg;
|
||||
struct tcm_vhost_tpg **vs_tpg;
|
||||
@@ -1197,6 +1198,21 @@ static int vhost_scsi_set_endpoint(
|
||||
ret = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* In order to ensure individual vhost-scsi configfs
|
||||
* groups cannot be removed while in use by vhost ioctl,
|
||||
* go ahead and take an explicit se_tpg->tpg_group.cg_item
|
||||
* dependency now.
|
||||
*/
|
||||
se_tpg = &tv_tpg->se_tpg;
|
||||
ret = configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
|
||||
&se_tpg->tpg_group.cg_item);
|
||||
if (ret) {
|
||||
pr_warn("configfs_depend_item() failed: %d\n", ret);
|
||||
kfree(vs_tpg);
|
||||
mutex_unlock(&tv_tpg->tv_tpg_mutex);
|
||||
goto out;
|
||||
}
|
||||
tv_tpg->tv_tpg_vhost_count++;
|
||||
tv_tpg->vhost_scsi = vs;
|
||||
vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
|
||||
@@ -1240,6 +1256,7 @@ static int vhost_scsi_clear_endpoint(
|
||||
struct vhost_scsi *vs,
|
||||
struct vhost_scsi_target *t)
|
||||
{
|
||||
struct se_portal_group *se_tpg;
|
||||
struct tcm_vhost_tport *tv_tport;
|
||||
struct tcm_vhost_tpg *tv_tpg;
|
||||
struct vhost_virtqueue *vq;
|
||||
@@ -1288,6 +1305,13 @@ static int vhost_scsi_clear_endpoint(
|
||||
vs->vs_tpg[target] = NULL;
|
||||
match = true;
|
||||
mutex_unlock(&tv_tpg->tv_tpg_mutex);
|
||||
/*
|
||||
* Release se_tpg->tpg_group.cg_item configfs dependency now
|
||||
* to allow vhost-scsi WWPN se_tpg->tpg_group shutdown to occur.
|
||||
*/
|
||||
se_tpg = &tv_tpg->se_tpg;
|
||||
configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
|
||||
&se_tpg->tpg_group.cg_item);
|
||||
}
|
||||
if (match) {
|
||||
for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
|
||||
|
||||
Reference in New Issue
Block a user