Commit ccefd23e authored by Robert Love's avatar Robert Love Committed by James Bottomley

[SCSI] fcoe: Do not switch context in vport_delete callback

Currently all port deletion is routed though the FCoE
workqueue (fcoe_wq). When fc_remove_host is called on
an N_Port (for example, from fcoe_destroy) the vports
are queued into a FC Transport workqueue. fc_remove_host
flushes that queue and each vport is passed to fcoe's
fcoe_vport_destroy, which simply queues the associated
fcoe_ports for later deletion. This queue cannot be
flushed within the N_Ports destroy path because of
circular locking issues. The result is that the NPIV
ports are destroyed after the N_Port, which is reverse
of how they are created.

This quirk causes fcoe to keep references on the
fcoe_interface shared by each of these ports (N_Port
and NPIV). Changing the ordering such that NPIV ports
are destroyed before the N_Port will allow us to remove
reference counting on the fcoe_interface instances.

This patch simply allows fcoe_vport_destory to destroy
NPIV ports without deferring them to a workqueue context.
This ensures that when fc_remove_host is called the
NPIV ports will be destroyed first before the N_Port and
allows reference counting on the fcoe's fcoe_interface
to be remove in a later patch.
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Tested-by: default avatarRoss Brattain <ross.b.brattain@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6f68794c
...@@ -2107,19 +2107,13 @@ static void fcoe_destroy_work(struct work_struct *work) ...@@ -2107,19 +2107,13 @@ static void fcoe_destroy_work(struct work_struct *work)
{ {
struct fcoe_port *port; struct fcoe_port *port;
struct fcoe_interface *fcoe; struct fcoe_interface *fcoe;
int npiv = 0;
port = container_of(work, struct fcoe_port, destroy_work); port = container_of(work, struct fcoe_port, destroy_work);
mutex_lock(&fcoe_config_mutex); mutex_lock(&fcoe_config_mutex);
/* set if this is an NPIV port */
npiv = port->lport->vport ? 1 : 0;
fcoe = port->priv; fcoe = port->priv;
fcoe_if_destroy(port->lport); fcoe_if_destroy(port->lport);
/* Do not tear down the fcoe interface for NPIV port */
if (!npiv)
fcoe_interface_cleanup(fcoe); fcoe_interface_cleanup(fcoe);
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
...@@ -2691,12 +2685,15 @@ static int fcoe_vport_destroy(struct fc_vport *vport) ...@@ -2691,12 +2685,15 @@ static int fcoe_vport_destroy(struct fc_vport *vport)
struct Scsi_Host *shost = vport_to_shost(vport); struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost); struct fc_lport *n_port = shost_priv(shost);
struct fc_lport *vn_port = vport->dd_data; struct fc_lport *vn_port = vport->dd_data;
struct fcoe_port *port = lport_priv(vn_port);
mutex_lock(&n_port->lp_mutex); mutex_lock(&n_port->lp_mutex);
list_del(&vn_port->list); list_del(&vn_port->list);
mutex_unlock(&n_port->lp_mutex); mutex_unlock(&n_port->lp_mutex);
queue_work(fcoe_wq, &port->destroy_work);
mutex_lock(&fcoe_config_mutex);
fcoe_if_destroy(vn_port);
mutex_unlock(&fcoe_config_mutex);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment