diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/scsi/impl/scsi_watch.c | 35 | ||||
-rw-r--r-- | usr/src/uts/common/io/scsi/targets/sd.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/sys/scsi/scsi_watch.h | 3 |
3 files changed, 50 insertions, 8 deletions
diff --git a/usr/src/uts/common/io/scsi/impl/scsi_watch.c b/usr/src/uts/common/io/scsi/impl/scsi_watch.c index 9c3be4e6bc..b747dc45b5 100644 --- a/usr/src/uts/common/io/scsi/impl/scsi_watch.c +++ b/usr/src/uts/common/io/scsi/impl/scsi_watch.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * generic scsi device watch */ @@ -962,3 +960,36 @@ done: } mutex_exit(&cpr_mutex); } + +/* + * scsi_watch_get_ref_count + * called by clients to query the reference count for a given token. + * return the number of reference count or 0 if the given token is + * not found. + */ +int +scsi_watch_get_ref_count(opaque_t token) +{ + struct scsi_watch_request *swr = + (struct scsi_watch_request *)token; + struct scsi_watch_request *sswr; + int rval = 0; + + SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG, + "scsi_watch_get_ref_count: Entering(0x%p) ...\n", + (void *)swr); + mutex_enter(&sw.sw_mutex); + + sswr = sw.sw_head; + while (sswr) { + if (sswr == swr) { + rval = swr->swr_ref; + mutex_exit(&sw.sw_mutex); + return (rval); + } + sswr = sswr->swr_next; + } + + mutex_exit(&sw.sw_mutex); + return (rval); +} diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c index 0f5d759839..72dd7318ca 100644 --- a/usr/src/uts/common/io/scsi/targets/sd.c +++ b/usr/src/uts/common/io/scsi/targets/sd.c @@ -22569,11 +22569,18 @@ sd_check_media(dev_t dev, enum dkio_state state) opaque_t token = NULL; int rval = 0; sd_ssc_t *ssc; + dev_t sub_dev; if ((un = ddi_get_soft_state(sd_state, SDUNIT(dev))) == NULL) { return (ENXIO); } + /* + * sub_dev is used when submitting request to scsi watch. + * All submissions are unified to use same device number. + */ + sub_dev = sd_make_device(SD_DEVINFO(un)); + SD_TRACE(SD_LOG_COMMON, un, "sd_check_media: entry\n"); ssc = sd_ssc_init(un); @@ -22607,7 +22614,7 @@ sd_check_media(dev_t dev, enum dkio_state state) token = scsi_watch_request_submit(SD_SCSI_DEVP(un), sd_check_media_time, SENSE_LENGTH, sd_media_watch_cb, - (caddr_t)dev); + (caddr_t)sub_dev); sd_pm_exit(un); @@ -22737,17 +22744,22 @@ sd_check_media(dev_t dev, enum dkio_state state) done: sd_ssc_fini(ssc); un->un_f_watcht_stopped = FALSE; + if (token != NULL && un->un_swr_token != NULL) { /* * Use of this local token and the mutex ensures that we avoid * some race conditions associated with terminating the * scsi watch. */ - if (token) { - un->un_swr_token = (opaque_t)NULL; + token = un->un_swr_token; mutex_exit(SD_MUTEX(un)); (void) scsi_watch_request_terminate(token, SCSI_WATCH_TERMINATE_WAIT); - mutex_enter(SD_MUTEX(un)); + if (scsi_watch_get_ref_count(token) == 0) { + mutex_enter(SD_MUTEX(un)); + un->un_swr_token = (opaque_t)NULL; + } else { + mutex_enter(SD_MUTEX(un)); + } } /* diff --git a/usr/src/uts/common/sys/scsi/scsi_watch.h b/usr/src/uts/common/sys/scsi/scsi_watch.h index 7bdd224253..a5dd6feae6 100644 --- a/usr/src/uts/common/sys/scsi/scsi_watch.h +++ b/usr/src/uts/common/sys/scsi/scsi_watch.h @@ -26,8 +26,6 @@ #ifndef _SYS_SCSI_SCSI_WATCH_H #define _SYS_SCSI_SCSI_WATCH_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -60,6 +58,7 @@ opaque_t scsi_watch_request_submit(struct scsi_device *devp, int interval, int sense_length, int (*callback)(), caddr_t cb_arg); int scsi_watch_request_terminate(opaque_t token, int flags); +int scsi_watch_get_ref_count(opaque_t token); void scsi_watch_resume(opaque_t token); void scsi_watch_suspend(opaque_t token); |