diff options
Diffstat (limited to 'usr/src/uts/common/io/blkdev/blkdev.c')
| -rw-r--r-- | usr/src/uts/common/io/blkdev/blkdev.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/usr/src/uts/common/io/blkdev/blkdev.c b/usr/src/uts/common/io/blkdev/blkdev.c index 2b185dff2b..07fa32da1d 100644 --- a/usr/src/uts/common/io/blkdev/blkdev.c +++ b/usr/src/uts/common/io/blkdev/blkdev.c @@ -122,9 +122,10 @@ * There are 4 instance global locks d_ocmutex, d_ksmutex, d_errmutex and * d_statemutex. As well a q_iomutex per waitq/runq pair. * - * Currently, there is no lock hierarchy. Nowhere do we ever own more than - * one lock, any change needs to be documented here with a defined - * hierarchy. + * Lock Hierarchy + * -------------- + * The only two locks which may be held simultaneously are q_iomutex and + * d_ksmutex. In all cases q_iomutex must be acquired before d_ksmutex. */ #define BD_MAXPART 64 @@ -1668,6 +1669,10 @@ bd_sched(bd_t *bd, bd_queue_t *bq) while ((bq->q_qactive < bq->q_qsize) && ((xi = list_remove_head(&bq->q_waitq)) != NULL)) { + mutex_enter(&bd->d_ksmutex); + kstat_waitq_to_runq(bd->d_kiop); + mutex_exit(&bd->d_ksmutex); + bq->q_qactive++; list_insert_tail(&bq->q_runq, xi); @@ -1679,10 +1684,6 @@ bd_sched(bd_t *bd, bd_queue_t *bq) mutex_exit(&bq->q_iomutex); - mutex_enter(&bd->d_ksmutex); - kstat_waitq_to_runq(bd->d_kiop); - mutex_exit(&bd->d_ksmutex); - rv = xi->i_func(bd->d_private, &xi->i_public); if (rv != 0) { bp = xi->i_bp; @@ -1690,11 +1691,13 @@ bd_sched(bd_t *bd, bd_queue_t *bq) biodone(bp); atomic_inc_32(&bd->d_kerr->bd_transerrs.value.ui32); + + mutex_enter(&bq->q_iomutex); + mutex_enter(&bd->d_ksmutex); kstat_runq_exit(bd->d_kiop); mutex_exit(&bd->d_ksmutex); - mutex_enter(&bq->q_iomutex); bq->q_qactive--; list_remove(&bq->q_runq, xi); bd_xfer_free(xi); @@ -1717,13 +1720,15 @@ bd_submit(bd_t *bd, bd_xfer_impl_t *xi) xi->i_qnum = q; mutex_enter(&bq->q_iomutex); + list_insert_tail(&bq->q_waitq, xi); - mutex_exit(&bq->q_iomutex); mutex_enter(&bd->d_ksmutex); kstat_waitq_enter(bd->d_kiop); mutex_exit(&bd->d_ksmutex); + mutex_exit(&bq->q_iomutex); + bd_sched(bd, bq); } @@ -1736,13 +1741,14 @@ bd_runq_exit(bd_xfer_impl_t *xi, int err) mutex_enter(&bq->q_iomutex); bq->q_qactive--; - list_remove(&bq->q_runq, xi); - mutex_exit(&bq->q_iomutex); mutex_enter(&bd->d_ksmutex); kstat_runq_exit(bd->d_kiop); mutex_exit(&bd->d_ksmutex); + list_remove(&bq->q_runq, xi); + mutex_exit(&bq->q_iomutex); + if (err == 0) { if (bp->b_flags & B_READ) { atomic_inc_uint(&bd->d_kiop->reads); |
