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:
Alexander Kabaev 2009-10-20 02:35:12 +00:00
parent d5e9eabead
commit 363b8ed74f
4 changed files with 40 additions and 21 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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
}
/*

View File

@ -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