Use callout_init_mtx on FreeBSD versions recent enough. This closes
the race where interrupt thread can complete the request for which timeout has fired and while mpt_timeout has blocked on mpt_lock. Do a best effort to keep 4.x ang Giant-locked configurartions compiling still. Reported by: ups Reviewed by: scottl
This commit is contained in:
parent
d5e9eabead
commit
363b8ed74f
@ -1238,7 +1238,6 @@ retry:
|
||||
req->state = REQ_STATE_ALLOCATED;
|
||||
req->chain = NULL;
|
||||
mpt_assign_serno(mpt, req);
|
||||
mpt_callout_init(&req->callout);
|
||||
} else if (sleep_ok != 0) {
|
||||
mpt->getreqwaiter = 1;
|
||||
mpt_sleep(mpt, &mpt->request_free_list, PUSER, "mptgreq", 0);
|
||||
@ -2251,6 +2250,7 @@ mpt_core_attach(struct mpt_softc *mpt)
|
||||
for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
|
||||
request_t *req = &mpt->request_pool[val];
|
||||
req->state = REQ_STATE_ALLOCATED;
|
||||
mpt_callout_init(mpt, &req->callout);
|
||||
mpt_free_request(mpt, req);
|
||||
}
|
||||
MPT_UNLOCK(mpt);
|
||||
@ -2334,10 +2334,18 @@ mpt_core_shutdown(struct mpt_softc *mpt)
|
||||
void
|
||||
mpt_core_detach(struct mpt_softc *mpt)
|
||||
{
|
||||
int val;
|
||||
|
||||
/*
|
||||
* XXX: FREE MEMORY
|
||||
*/
|
||||
mpt_disable_ints(mpt);
|
||||
|
||||
/* Make sure no request has pending timeouts. */
|
||||
for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
|
||||
request_t *req = &mpt->request_pool[val];
|
||||
mpt_callout_drain(mpt, &req->callout);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -296,13 +296,6 @@ void mpt_map_rquest(void *, bus_dma_segment_t *, int, int);
|
||||
kthread_exit(status)
|
||||
#endif
|
||||
|
||||
/****************************** Timer Facilities ******************************/
|
||||
#if __FreeBSD_version > 500000
|
||||
#define mpt_callout_init(c) callout_init(c, /*mpsafe*/1);
|
||||
#else
|
||||
#define mpt_callout_init(c) callout_init(c);
|
||||
#endif
|
||||
|
||||
/********************************** Endianess *********************************/
|
||||
#define MPT_2_HOST64(ptr, tag) ptr->tag = le64toh(ptr->tag)
|
||||
#define MPT_2_HOST32(ptr, tag) ptr->tag = le32toh(ptr->tag)
|
||||
@ -889,6 +882,10 @@ mpt_sleep(struct mpt_softc *mpt, void *ident, int priority,
|
||||
callout_reset(&(req)->callout, (ticks), (func), (arg));
|
||||
#define mpt_req_untimeout(req, func, arg) \
|
||||
callout_stop(&(req)->callout)
|
||||
#define mpt_callout_init(mpt, c) \
|
||||
callout_init(c)
|
||||
#define mpt_callout_drain(mpt, c) \
|
||||
callout_stop(c)
|
||||
|
||||
#else
|
||||
#if 1
|
||||
@ -911,9 +908,13 @@ mpt_sleep(struct mpt_softc *mpt, void *ident, int priority,
|
||||
#define mpt_sleep(mpt, ident, priority, wmesg, timo) \
|
||||
msleep(ident, &(mpt)->mpt_lock, priority, wmesg, timo)
|
||||
#define mpt_req_timeout(req, ticks, func, arg) \
|
||||
callout_reset(&(req)->callout, (ticks), (func), (arg));
|
||||
callout_reset(&(req)->callout, (ticks), (func), (arg))
|
||||
#define mpt_req_untimeout(req, func, arg) \
|
||||
callout_stop(&(req)->callout)
|
||||
#define mpt_callout_init(mpt, c) \
|
||||
callout_init_mtx(c, &(mpt)->mpt_lock, 0)
|
||||
#define mpt_callout_drain(mpt, c) \
|
||||
callout_drain(c)
|
||||
|
||||
#else
|
||||
|
||||
@ -926,18 +927,18 @@ mpt_sleep(struct mpt_softc *mpt, void *ident, int priority,
|
||||
#define MPTLOCK_2_CAMLOCK(mpt)
|
||||
#define CAMLOCK_2_MPTLOCK(mpt)
|
||||
|
||||
#define mpt_req_timeout(req, ticks, func, arg) \
|
||||
callout_reset(&(req)->callout, (ticks), (func), (arg))
|
||||
#define mpt_req_untimeout(req, func, arg) \
|
||||
callout_stop(&(req)->callout)
|
||||
#define mpt_callout_init(mpt, c) \
|
||||
callout_init(c, 0)
|
||||
#define mpt_callout_drain(mpt, c) \
|
||||
callout_drain(c)
|
||||
|
||||
static __inline int
|
||||
mpt_sleep(struct mpt_softc *, void *, int, const char *, int);
|
||||
|
||||
#define mpt_ccb_timeout(ccb, ticks, func, arg) \
|
||||
do { \
|
||||
(ccb)->ccb_h.timeout_ch = timeout((func), (arg), (ticks)); \
|
||||
} while (0)
|
||||
#define mpt_ccb_untimeout(ccb, func, arg) \
|
||||
untimeout((func), (arg), (ccb)->ccb_h.timeout_ch)
|
||||
#define mpt_ccb_timeout_init(ccb) \
|
||||
callout_handle_init(&(ccb)->ccb_h.timeout_ch)
|
||||
|
||||
static __inline int
|
||||
mpt_sleep(struct mpt_softc *mpt, void *i, int p, const char *w, int t)
|
||||
{
|
||||
|
@ -1245,7 +1245,10 @@ mpt_timeout(void *arg)
|
||||
ccb = (union ccb *)arg;
|
||||
mpt = ccb->ccb_h.ccb_mpt_ptr;
|
||||
|
||||
#if __FreeBSD_version < 500000
|
||||
MPT_LOCK(mpt);
|
||||
#endif
|
||||
MPT_LOCK_ASSERT(mpt);
|
||||
req = ccb->ccb_h.ccb_req_ptr;
|
||||
mpt_prt(mpt, "request %p:%u timed out for ccb %p (req->ccb %p)\n", req,
|
||||
req->serno, ccb, req->ccb);
|
||||
@ -1256,7 +1259,9 @@ mpt_timeout(void *arg)
|
||||
req->state |= REQ_STATE_TIMEDOUT;
|
||||
mpt_wakeup_recovery_thread(mpt);
|
||||
}
|
||||
#if __FreeBSD_version < 500000
|
||||
MPT_UNLOCK(mpt);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -271,7 +271,7 @@ mpt_raid_attach(struct mpt_softc *mpt)
|
||||
mpt_handler_t handler;
|
||||
int error;
|
||||
|
||||
mpt_callout_init(&mpt->raid_timer);
|
||||
mpt_callout_init(mpt, &mpt->raid_timer);
|
||||
|
||||
error = mpt_spawn_raid_thread(mpt);
|
||||
if (error != 0) {
|
||||
@ -320,10 +320,10 @@ mpt_raid_detach(struct mpt_softc *mpt)
|
||||
struct ccb_setasync csa;
|
||||
mpt_handler_t handler;
|
||||
|
||||
callout_stop(&mpt->raid_timer);
|
||||
mpt_callout_drain(mpt, &mpt->raid_timer);
|
||||
|
||||
MPT_LOCK(mpt);
|
||||
mpt_terminate_raid_thread(mpt);
|
||||
|
||||
handler.reply_handler = mpt_raid_reply_handler;
|
||||
mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
|
||||
raid_handler_id);
|
||||
@ -1570,9 +1570,14 @@ mpt_raid_timer(void *arg)
|
||||
struct mpt_softc *mpt;
|
||||
|
||||
mpt = (struct mpt_softc *)arg;
|
||||
#if __FreeBSD_version < 500000
|
||||
MPT_LOCK(mpt);
|
||||
#endif
|
||||
MPT_LOCK_ASSERT(mpt);
|
||||
mpt_raid_wakeup(mpt);
|
||||
#if __FreeBSD_version < 500000
|
||||
MPT_UNLOCK(mpt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
x
Reference in New Issue
Block a user