summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2009-01-08 17:26:51 +0000
committertrasz <trasz@FreeBSD.org>2009-01-08 17:26:51 +0000
commit3e67abb702a0af9dbd399509e984c3a2ba1bdc3e (patch)
tree3951873ee916b9e11809e8b5a927c3a218dd30e0 /sys/cam
parent98ad45c3d3f257c3649d4e198723267231203184 (diff)
downloadFreeBSD-src-3e67abb702a0af9dbd399509e984c3a2ba1bdc3e.zip
FreeBSD-src-3e67abb702a0af9dbd399509e984c3a2ba1bdc3e.tar.gz
Make "kldunload atapicam" return EBUSY instead of deadlocking when a device
created by atapicam is being kept opened or mounted. This is probably just a temporary solution until we invent something better. Reviewed by: scottl Approved by: rwatson (mentor) Sponsored by: FreeBSD Foundation Reported by: Jaakko Heinonen
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam_xpt.c35
-rw-r--r--sys/cam/cam_xpt_sim.h1
2 files changed, 35 insertions, 1 deletions
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 77fb62a..753a877 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2642,6 +2642,39 @@ xptbustraverse(struct cam_eb *start_bus, xpt_busfunc_t *tr_func, void *arg)
return(retval);
}
+int
+xpt_sim_opened(struct cam_sim *sim)
+{
+ struct cam_eb *bus;
+ struct cam_et *target;
+ struct cam_ed *device;
+ struct cam_periph *periph;
+
+ KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+ mtx_assert(sim->mtx, MA_OWNED);
+
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ TAILQ_FOREACH(bus, &xsoftc.xpt_busses, links) {
+ if (bus->sim != sim)
+ continue;
+
+ TAILQ_FOREACH(target, &bus->et_entries, links) {
+ TAILQ_FOREACH(device, &target->ed_entries, links) {
+ SLIST_FOREACH(periph, &device->periphs,
+ periph_links) {
+ if (periph->refcount > 0) {
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+ return (1);
+ }
+ }
+ }
+ }
+ }
+
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+ return (0);
+}
+
static int
xpttargettraverse(struct cam_eb *bus, struct cam_et *start_target,
xpt_targetfunc_t *tr_func, void *arg)
@@ -4277,7 +4310,7 @@ xpt_release_ccb(union ccb *free_ccb)
* for this new bus and places it in the array of busses and assigns
* it a path_id. The path_id may be influenced by "hard wiring"
* information specified by the user. Once interrupt services are
- * availible, the bus will be probed.
+ * available, the bus will be probed.
*/
int32_t
xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
diff --git a/sys/cam/cam_xpt_sim.h b/sys/cam/cam_xpt_sim.h
index d824093..e64c67c 100644
--- a/sys/cam/cam_xpt_sim.h
+++ b/sys/cam/cam_xpt_sim.h
@@ -45,6 +45,7 @@ void xpt_release_simq(struct cam_sim *sim, int run_queue);
u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
void xpt_release_devq(struct cam_path *path, u_int count,
int run_queue);
+int xpt_sim_opened(struct cam_sim *sim);
void xpt_done(union ccb *done_ccb);
#endif
OpenPOWER on IntegriCloud