From: Robert Love <robert.w.love@intel.com>
To: James.Bottomley@HansenPartnership.com, linux-scsi@vger.kernel.org
Cc: Chris Leech <christopher.leech@intel.com>,
Robert Love <robert.w.love@intel.com>
Subject: [PATCH 22/64] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling
Date: Tue, 25 Aug 2009 14:00:23 -0700 [thread overview]
Message-ID: <20090825210023.1553.47980.stgit@localhost.localdomain> (raw)
In-Reply-To: <20090825205826.1553.94414.stgit@localhost.localdomain>
From: Chris Leech <christopher.leech@intel.com>
Fixes reference counting on fcoe_instance and net_device, and adds
NETDEV_UNREGISTER notifier handling so that you can unload network drivers.
FCoE no longer increments the module use count for the network driver.
On an NETDEV_UNREGISTER event, destroying the FCoE instance is deferred to a
workqueue context to avoid RTNL deadlocks.
Based in part by an earlier patch from John Fastabend
John's patch description:
Currently, the netdev module ref count is not decremented with module_put()
when the module is unloaded while fcoe instances are present. To fix this
removed reference count on netdev module completely and added functionality to
netdev event handling for NETDEV_UNREGISTER events.
This allows fcoe to remove devices cleanly when the netdev module is unloaded
so we no longer need to hold a reference count for the netdev module.
Signed-off-by: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 186 ++++++++++++++++------------------------------
drivers/scsi/fcoe/fcoe.h | 2
2 files changed, 67 insertions(+), 121 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c9a0346..c0264a9 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -74,12 +74,13 @@ static int fcoe_link_ok(struct fc_lport *lp);
static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
static int fcoe_hostlist_add(const struct fc_lport *);
-static int fcoe_hostlist_remove(const struct fc_lport *);
static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
static int fcoe_device_notification(struct notifier_block *, ulong, void *);
static void fcoe_dev_setup(void);
static void fcoe_dev_cleanup(void);
+static struct fcoe_interface *
+ fcoe_hostlist_lookup_port(const struct net_device *dev);
/* notification function from net device */
static struct notifier_block fcoe_notifier = {
@@ -149,6 +150,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
* @netdev : ptr to the associated netdevice struct
*
* Returns : 0 for success
+ * Locking: must be called with the RTNL mutex held
*/
static int fcoe_interface_setup(struct fcoe_interface *fcoe,
struct net_device *netdev)
@@ -188,13 +190,11 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
* or enter promiscuous mode if not capable of listening
* for multiple unicast MACs.
*/
- rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_unicast_add(netdev, flogi_maddr);
if (fip->spma)
dev_unicast_add(netdev, fip->ctl_src_addr);
dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
- rtnl_unlock();
/*
* setup the receive function from ethernet driver
@@ -215,6 +215,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new);
+static void fcoe_destroy_work(struct work_struct *work);
/**
* fcoe_interface_create()
@@ -232,6 +233,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
return NULL;
}
+ dev_hold(netdev);
kref_init(&fcoe->kref);
/*
@@ -249,6 +251,8 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
/**
* fcoe_interface_cleanup() - clean up netdev configurations
* @fcoe:
+ *
+ * Caller must be holding the RTNL mutex
*/
void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
@@ -266,11 +270,7 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
__dev_remove_pack(&fcoe->fip_packet_type);
synchronize_net();
- /* tear-down the FCoE controller */
- fcoe_ctlr_destroy(&fcoe->ctlr);
-
/* Delete secondary MAC addresses */
- rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_unicast_delete(netdev, flogi_maddr);
if (!is_zero_ether_addr(fip->data_src_addr))
@@ -278,7 +278,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
if (fip->spma)
dev_unicast_delete(netdev, fip->ctl_src_addr);
dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
- rtnl_unlock();
}
/**
@@ -288,10 +287,14 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
static void fcoe_interface_release(struct kref *kref)
{
struct fcoe_interface *fcoe;
+ struct net_device *netdev;
fcoe = container_of(kref, struct fcoe_interface, kref);
- fcoe_interface_cleanup(fcoe);
+ netdev = fcoe->netdev;
+ /* tear-down the FCoE controller */
+ fcoe_ctlr_destroy(&fcoe->ctlr);
kfree(fcoe);
+ dev_put(netdev);
}
/**
@@ -642,8 +645,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Free memory used by statistical counters */
fc_lport_free_stats(lport);
- /* Release the net_device and Scsi_Host */
- dev_put(netdev);
+ /* Release the Scsi_Host */
scsi_host_put(lport->host);
}
@@ -718,7 +720,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
}
lport = shost_priv(shost);
port = lport_priv(lport);
+ port->lport = lport;
port->fcoe = fcoe;
+ INIT_WORK(&port->destroy_work, fcoe_destroy_work);
/* configure fc_lport, e.g., em */
rc = fcoe_lport_config(lport);
@@ -769,7 +773,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
goto out_lp_destroy;
}
- dev_hold(netdev);
fcoe_interface_get(fcoe);
return lport;
@@ -1530,19 +1533,19 @@ static int fcoe_device_notification(struct notifier_block *notifier,
struct fc_lport *lp = NULL;
struct net_device *netdev = ptr;
struct fcoe_interface *fcoe;
+ struct fcoe_port *port;
struct fcoe_dev_stats *stats;
u32 link_possible = 1;
u32 mfs;
int rc = NOTIFY_OK;
- read_lock(&fcoe_hostlist_lock);
+ write_lock(&fcoe_hostlist_lock);
list_for_each_entry(fcoe, &fcoe_hostlist, list) {
if (fcoe->netdev == netdev) {
lp = fcoe->ctlr.lp;
break;
}
}
- read_unlock(&fcoe_hostlist_lock);
if (lp == NULL) {
rc = NOTIFY_DONE;
goto out;
@@ -1564,6 +1567,13 @@ static int fcoe_device_notification(struct notifier_block *notifier,
break;
case NETDEV_REGISTER:
break;
+ case NETDEV_UNREGISTER:
+ list_del(&fcoe->list);
+ port = lport_priv(fcoe->ctlr.lp);
+ fcoe_interface_cleanup(fcoe);
+ schedule_work(&port->destroy_work);
+ goto out;
+ break;
default:
FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
"from netdev netlink\n", event);
@@ -1576,6 +1586,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
fcoe_clean_pending_queue(lp);
}
out:
+ write_unlock(&fcoe_hostlist_lock);
return rc;
}
@@ -1601,75 +1612,6 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
}
/**
- * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev
- * @netdev: the target netdev
- *
- * Returns: ptr to the struct module, NULL for failure
- */
-static struct module *
-fcoe_netdev_to_module_owner(const struct net_device *netdev)
-{
- struct device *dev;
-
- if (!netdev)
- return NULL;
-
- dev = netdev->dev.parent;
- if (!dev)
- return NULL;
-
- if (!dev->driver)
- return NULL;
-
- return dev->driver->owner;
-}
-
-/**
- * fcoe_ethdrv_get() - Hold the Ethernet driver
- * @netdev: the target netdev
- *
- * Holds the Ethernet driver module by try_module_get() for
- * the corresponding netdev.
- *
- * Returns: 0 for success
- */
-static int fcoe_ethdrv_get(const struct net_device *netdev)
-{
- struct module *owner;
-
- owner = fcoe_netdev_to_module_owner(netdev);
- if (owner) {
- FCOE_NETDEV_DBG(netdev, "Hold driver module %s\n",
- module_name(owner));
- return try_module_get(owner);
- }
- return -ENODEV;
-}
-
-/**
- * fcoe_ethdrv_put() - Release the Ethernet driver
- * @netdev: the target netdev
- *
- * Releases the Ethernet driver module by module_put for
- * the corresponding netdev.
- *
- * Returns: 0 for success
- */
-static int fcoe_ethdrv_put(const struct net_device *netdev)
-{
- struct module *owner;
-
- owner = fcoe_netdev_to_module_owner(netdev);
- if (owner) {
- FCOE_NETDEV_DBG(netdev, "Release driver module %s\n",
- module_name(owner));
- module_put(owner);
- return 0;
- }
- return -ENODEV;
-}
-
-/**
* fcoe_destroy() - handles the destroy from sysfs
* @buffer: expected to be an eth if name
* @kp: associated kernel param
@@ -1678,10 +1620,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
*/
static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
{
- struct net_device *netdev;
struct fcoe_interface *fcoe;
- struct fcoe_port *port;
- struct fc_lport *lport;
+ struct net_device *netdev;
int rc;
mutex_lock(&fcoe_config_mutex);
@@ -1702,19 +1642,20 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
rc = -ENODEV;
goto out_nodev;
}
- /* look for existing lport */
- lport = fcoe_hostlist_lookup(netdev);
- if (!lport) {
+
+ write_lock(&fcoe_hostlist_lock);
+ fcoe = fcoe_hostlist_lookup_port(netdev);
+ if (!fcoe) {
+ write_unlock(&fcoe_hostlist_lock);
rc = -ENODEV;
goto out_putdev;
}
- /* Remove the instance from fcoe's list */
- fcoe_hostlist_remove(lport);
- port = lport_priv(lport);
- fcoe = port->fcoe;
- fcoe_if_destroy(lport);
- fcoe_ethdrv_put(netdev);
- rc = 0;
+ list_del(&fcoe->list);
+ write_unlock(&fcoe_hostlist_lock);
+ rtnl_lock();
+ fcoe_interface_cleanup(fcoe);
+ rtnl_unlock();
+ fcoe_if_destroy(fcoe->ctlr.lp);
out_putdev:
dev_put(netdev);
out_nodev:
@@ -1722,6 +1663,16 @@ out_nodev:
return rc;
}
+static void fcoe_destroy_work(struct work_struct *work)
+{
+ struct fcoe_port *port;
+
+ port = container_of(work, struct fcoe_port, destroy_work);
+ mutex_lock(&fcoe_config_mutex);
+ fcoe_if_destroy(port->lport);
+ mutex_unlock(&fcoe_config_mutex);
+}
+
/**
* fcoe_create() - Handles the create call from sysfs
* @buffer: expected to be an eth if name
@@ -1749,17 +1700,18 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
}
#endif
+ rtnl_lock();
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
rc = -ENODEV;
goto out_nodev;
}
+
/* look for existing lport */
if (fcoe_hostlist_lookup(netdev)) {
rc = -EEXIST;
goto out_putdev;
}
- fcoe_ethdrv_get(netdev);
fcoe = fcoe_interface_create(netdev);
if (!fcoe) {
@@ -1771,8 +1723,8 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
if (IS_ERR(lport)) {
printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
netdev->name);
- fcoe_ethdrv_put(netdev);
rc = -EIO;
+ fcoe_interface_cleanup(fcoe);
goto out_free;
}
@@ -1798,6 +1750,7 @@ out_free:
out_putdev:
dev_put(netdev);
out_nodev:
+ rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
return rc;
}
@@ -1973,25 +1926,6 @@ int fcoe_hostlist_add(const struct fc_lport *lport)
}
/**
- * fcoe_hostlist_remove() - remove a lport from lports list
- * @lp: ptr to the fc_lport to be removed
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_remove(const struct fc_lport *lport)
-{
- struct fcoe_interface *fcoe;
-
- write_lock_bh(&fcoe_hostlist_lock);
- fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
- BUG_ON(!fcoe);
- list_del(&fcoe->list);
- write_unlock_bh(&fcoe_hostlist_lock);
-
- return 0;
-}
-
-/**
* fcoe_init() - fcoe module loading initialization
*
* Returns 0 on success, negative on failure
@@ -2046,6 +1980,7 @@ static void __exit fcoe_exit(void)
unsigned int cpu;
struct fcoe_interface *fcoe, *tmp;
LIST_HEAD(local_list);
+ struct fcoe_port *port;
mutex_lock(&fcoe_config_mutex);
@@ -2058,7 +1993,11 @@ static void __exit fcoe_exit(void)
list_for_each_entry_safe(fcoe, tmp, &local_list, list) {
list_del(&fcoe->list);
- fcoe_if_destroy(fcoe->ctlr.lp);
+ port = lport_priv(fcoe->ctlr.lp);
+ rtnl_lock();
+ fcoe_interface_cleanup(fcoe);
+ rtnl_unlock();
+ schedule_work(&port->destroy_work);
}
unregister_hotcpu_notifier(&fcoe_cpu_notifier);
@@ -2066,9 +2005,14 @@ static void __exit fcoe_exit(void)
for_each_online_cpu(cpu)
fcoe_percpu_thread_destroy(cpu);
- /* detach from scsi transport */
- fcoe_if_exit();
-
mutex_unlock(&fcoe_config_mutex);
+
+ /* flush any asyncronous interface destroys,
+ * this should happen after the netdev notifier is unregistered */
+ flush_scheduled_work();
+
+ /* detach from scsi transport
+ * must happen after all destroys are done, therefor after the flush */
+ fcoe_if_exit();
}
module_exit(fcoe_exit);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index ff22928..ce7f60f 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -93,9 +93,11 @@ struct fcoe_interface {
*/
struct fcoe_port {
struct fcoe_interface *fcoe;
+ struct fc_lport *lport;
struct sk_buff_head fcoe_pending_queue;
u8 fcoe_pending_queue_active;
struct timer_list timer; /* queue timer */
+ struct work_struct destroy_work; /* to prevent rtnl deadlocks */
};
#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)
next prev parent reply other threads:[~2009-08-25 21:00 UTC|newest]
Thread overview: 69+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-25 20:58 [PATCH 00/64] libfc, libfcoe and fcoe updates for scsi-misc Robert Love
2009-08-25 20:58 ` [PATCH 01/64] fcoe: Add format spacing to FCOE_NETDEV_DBG debug macro Robert Love
2009-08-25 20:58 ` [PATCH 02/64] libfc: Fix misleading debug statement Robert Love
2009-08-25 20:58 ` [PATCH 03/64] fcoe: libfcoe: extra semicolon in CHECK_LOGGING macros causes compile error Robert Love
2009-08-25 20:58 ` [PATCH 04/64] fcoe, libfc: adds per cpu exch pool within exchange manager(EM) Robert Love
2009-08-25 20:58 ` [PATCH 05/64] fcoe, libfc: fully makes use of per cpu exch pool and then removes em_lock Robert Love
2009-08-25 20:58 ` [PATCH 06/64] libfc: Export FC headers Robert Love
2009-08-27 10:27 ` Christof Schmitt
2009-08-27 17:42 ` Robert Love
2009-08-28 8:32 ` Swen Schillig
2009-08-28 16:58 ` Robert Love
2009-08-25 20:59 ` [PATCH 07/64] fcoe: Add sysfs parameter to fcoe for minimum DDP read I/O size Robert Love
2009-08-25 20:59 ` [PATCH 08/64] libfcoe: fcoe_ctlr_destroy use cancel_work_sync instead of flush_work Robert Love
2009-08-25 20:59 ` [PATCH 09/64] fcoe: fix missing error check in call to fcoe_if_init Robert Love
2009-08-25 20:59 ` [PATCH 10/64] fcoe: remove unnecessary list and lock initializations Robert Love
2009-08-25 20:59 ` [PATCH 11/64] fcoe: interface changes to fcoe_if_create and fcoe_if_destroy Robert Love
2009-08-25 20:59 ` [PATCH 12/64] fcoe: Introduce and allocate fcoe_interface structure, 1:1 with net_device Robert Love
2009-08-25 20:59 ` [PATCH 13/64] fcoe: move netdev to fcoe_interface Robert Love
2009-08-25 20:59 ` [PATCH 14/64] fcoe: move packet handlers from fcoe_port " Robert Love
2009-08-25 20:59 ` [PATCH 15/64] fcoe: move FIP controller " Robert Love
2009-08-25 20:59 ` [PATCH 16/64] fcoe: move offload exchange manager pointer " Robert Love
2009-08-25 20:59 ` [PATCH 17/64] fcoe: remove fcoe_interface->priv pointer Robert Love
2009-08-25 21:00 ` [PATCH 18/64] fcoe: fcoe_interface create, destroy and refcounting Robert Love
2009-08-25 21:00 ` [PATCH 19/64] fcoe: split out per interface setup Robert Love
2009-08-25 21:00 ` [PATCH 20/64] fcoe: add mutex to protect create and destroy Robert Love
2009-08-25 21:00 ` [PATCH 21/64] fcoe: move the host-list add/remove to keep out VN_Ports Robert Love
2009-08-25 21:00 ` Robert Love [this message]
2009-08-25 21:00 ` [PATCH 23/64] fcoe: use rtnl mutex in place of hostlist lock Robert Love
2009-08-25 21:00 ` [PATCH 24/64] libfc: prepare to split off struct fc_rport_priv from fc_rport_libfc_priv Robert Love
2009-08-25 21:00 ` [PATCH 25/64] libfc: change interface for rport_create Robert Love
2009-08-25 21:00 ` [PATCH 26/64] libfc: fix RPORT_TO_PRIV and PRIV_TO_RPORT() macros Robert Love
2009-08-25 21:00 ` [PATCH 27/64] libfc: make fc_rport_priv the primary rport interface Robert Love
2009-08-25 21:00 ` [PATCH 28/64] libfc: change elsct to use FC_ID instead of rdata Robert Love
2009-08-25 21:01 ` [PATCH 29/64] libfc: make rport structure optional Robert Love
2009-08-25 21:01 ` [PATCH 30/64] libfc: rearrange code in fc_rport_work Robert Love
2009-08-25 21:01 ` [PATCH 31/64] libfc: rename rport event CREATED to READY Robert Love
2009-08-25 21:01 ` [PATCH 32/64] libfc: don't create dummy (rogue) remote ports Robert Love
2009-08-25 21:01 ` [PATCH 33/64] libfc: fix rport event race between READY and LOGO Robert Love
2009-08-25 21:01 ` [PATCH 34/64] libfc: eliminate disc->event Robert Love
2009-08-25 21:01 ` [PATCH 35/64] libfc: remove unused disc->delay element Robert Love
2009-08-25 21:01 ` [PATCH 36/64] libfc: rport debug messages were printing pointer values Robert Love
2009-08-25 21:01 ` [PATCH 37/64] libfc: simplify fc_lport_rport_callback Robert Love
2009-08-25 21:01 ` [PATCH 38/64] libfc: make rport module maintain the rport list Robert Love
2009-08-25 21:01 ` [PATCH 39/64] libfc: have rport_create do a lookup for pre-existing rports first Robert Love
2009-08-25 21:02 ` [PATCH 40/64] libfc: change to make remote port callback optional Robert Love
2009-08-25 21:02 ` [PATCH 41/64] libfc: move rport_lookup into fc_rport.c Robert Love
2009-08-25 21:02 ` [PATCH 42/64] libfc: do not log off rports before or after discovery Robert Love
2009-08-25 21:02 ` [PATCH 43/64] libfc: discovery restart sequence error fix Robert Love
2009-08-25 21:02 ` [PATCH 44/64] libfc: rearrange code in fc_disc_gpn_ft_resp() Robert Love
2009-08-25 21:02 ` [PATCH 45/64] libfc: handle discovery failure more correctly Robert Love
2009-08-25 21:02 ` [PATCH 46/64] libfc: fix: empty zone causes endless discovery retries Robert Love
2009-08-25 21:02 ` [PATCH 47/64] libfc: discovery retry should clear pending first Robert Love
2009-08-25 21:02 ` [PATCH 48/64] libfc: discovery gpn_ft parse bug Robert Love
2009-08-25 21:02 ` [PATCH 49/64] libfc: clean up point-to-point discovery code Robert Love
2009-08-25 21:02 ` [PATCH 50/64] libfc: don't do discovery before callback is set Robert Love
2009-08-25 21:02 ` [PATCH 51/64] libfc: Initialize fc_rport_identifiers inside fc_rport_create Robert Love
2009-08-25 21:03 ` [PATCH 52/64] libfc: Always reset remote port roles when receiving PRLI Robert Love
2009-08-25 21:03 ` [PATCH 53/64] libfc: move remote port lookup for ELS requests into fc_rport.c Robert Love
2009-08-25 21:03 ` [PATCH 54/64] libfc: fix: rport_recv_req needs disc_mutex when calling rport_lookup Robert Love
2009-08-25 21:03 ` [PATCH 55/64] libfc: improve debug messages for ELS response handlers Robert Love
2009-08-25 21:03 ` [PATCH 56/64] libfc: correctly handle incoming PLOGI request Robert Love
2009-08-25 21:03 ` [PATCH 57/64] libfc: fix rport error handling for login-required and invalid ops Robert Love
2009-08-25 21:03 ` [PATCH 58/64] libfc: re-login to remote ports that send us LOGO Robert Love
2009-08-25 21:03 ` [PATCH 59/64] libfc: LOGO response code had extraeous enter_rtv Robert Love
2009-08-25 21:03 ` [PATCH 60/64] libfc: use ADISC to verify rport login state Robert Love
2009-08-25 21:03 ` [PATCH 61/64] libfc: fix handling of incoming Discover Address (ADISC) requests Robert Love
2009-08-25 21:03 ` [PATCH 62/64] libfc: send GPN_ID in reaction to single-port RSCNs Robert Love
2009-08-25 21:04 ` [PATCH 63/64] libfc: don't swap OX_ID and RX_ID when sending BA_RJT Robert Love
2009-08-25 21:04 ` [PATCH 64/64] fcoe: flush per-cpu thread work when destroying interface Robert Love
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090825210023.1553.47980.stgit@localhost.localdomain \
--to=robert.w.love@intel.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=christopher.leech@intel.com \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.