mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 07:12:09 +00:00
[SCSI] libsas: introduce sas_work to fix sas_drain_work vs sas_queue_work
When requeuing work to a draining workqueue the last work instance may not be idle, so sas_queue_work() must not touch work->entry. Introduce sas_work with a drain_node list_head to have a private list for collecting work deferred due to drain collision. Fixes reports like: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff810410d4>] process_one_work+0x2e/0x338 Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
f8fc75dc57
commit
22b9153faa
7 changed files with 83 additions and 62 deletions
|
@ -217,11 +217,29 @@ struct domain_device {
|
|||
struct kref kref;
|
||||
};
|
||||
|
||||
struct sas_discovery_event {
|
||||
struct sas_work {
|
||||
struct list_head drain_node;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *))
|
||||
{
|
||||
INIT_WORK(&sw->work, fn);
|
||||
INIT_LIST_HEAD(&sw->drain_node);
|
||||
}
|
||||
|
||||
struct sas_discovery_event {
|
||||
struct sas_work work;
|
||||
struct asd_sas_port *port;
|
||||
};
|
||||
|
||||
static inline struct sas_discovery_event *to_sas_discovery_event(struct work_struct *work)
|
||||
{
|
||||
struct sas_discovery_event *ev = container_of(work, typeof(*ev), work.work);
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
struct sas_discovery {
|
||||
struct sas_discovery_event disc_work[DISC_NUM_EVENTS];
|
||||
unsigned long pending;
|
||||
|
@ -244,7 +262,7 @@ struct asd_sas_port {
|
|||
struct list_head destroy_list;
|
||||
enum sas_linkrate linkrate;
|
||||
|
||||
struct work_struct work;
|
||||
struct sas_work work;
|
||||
|
||||
/* public: */
|
||||
int id;
|
||||
|
@ -270,10 +288,17 @@ struct asd_sas_port {
|
|||
};
|
||||
|
||||
struct asd_sas_event {
|
||||
struct work_struct work;
|
||||
struct sas_work work;
|
||||
struct asd_sas_phy *phy;
|
||||
};
|
||||
|
||||
static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work)
|
||||
{
|
||||
struct asd_sas_event *ev = container_of(work, typeof(*ev), work.work);
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
/* The phy pretty much is controlled by the LLDD.
|
||||
* The class only reads those fields.
|
||||
*/
|
||||
|
@ -333,10 +358,17 @@ struct scsi_core {
|
|||
};
|
||||
|
||||
struct sas_ha_event {
|
||||
struct work_struct work;
|
||||
struct sas_work work;
|
||||
struct sas_ha_struct *ha;
|
||||
};
|
||||
|
||||
static inline struct sas_ha_event *to_sas_ha_event(struct work_struct *work)
|
||||
{
|
||||
struct sas_ha_event *ev = container_of(work, typeof(*ev), work.work);
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
enum sas_ha_state {
|
||||
SAS_HA_REGISTERED,
|
||||
SAS_HA_DRAINING,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue