svn commit: r236800 - stable/8/sys/cam
Alexander Motin
mav at FreeBSD.org
Sat Jun 9 08:51:26 UTC 2012
Author: mav
Date: Sat Jun 9 08:51:25 2012
New Revision: 236800
URL: http://svn.freebsd.org/changeset/base/236800
Log:
MFC r224806i (by mjacob):
Fixes for sure bus reference miscounting and potential device and
target reference miscounts. It also adds a helper function to get
the current reference counts for components of cam_path for debug
aid. One minor style(9) change.
Modified:
stable/8/sys/cam/cam_xpt.c
stable/8/sys/cam/cam_xpt.h
Directory Properties:
stable/8/sys/ (props changed)
Modified: stable/8/sys/cam/cam_xpt.c
==============================================================================
--- stable/8/sys/cam/cam_xpt.c Sat Jun 9 08:41:30 2012 (r236799)
+++ stable/8/sys/cam/cam_xpt.c Sat Jun 9 08:51:25 2012 (r236800)
@@ -3396,8 +3396,10 @@ xpt_create_path_unlocked(struct cam_path
}
}
status = xpt_compile_path(path, periph, path_id, target_id, lun_id);
- if (need_unlock)
+ if (need_unlock) {
CAM_SIM_UNLOCK(bus->sim);
+ xpt_release_bus(bus);
+ }
if (status != CAM_REQ_CMP) {
free(path, M_CAMXPT);
path = NULL;
@@ -3505,6 +3507,38 @@ xpt_free_path(struct cam_path *path)
free(path, M_CAMXPT);
}
+void
+xpt_path_counts(struct cam_path *path, uint32_t *bus_ref,
+ uint32_t *periph_ref, uint32_t *target_ref, uint32_t *device_ref)
+{
+
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ if (bus_ref) {
+ if (path->bus)
+ *bus_ref = path->bus->refcount;
+ else
+ *bus_ref = 0;
+ }
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+ if (periph_ref) {
+ if (path->periph)
+ *periph_ref = path->periph->refcount;
+ else
+ *periph_ref = 0;
+ }
+ if (target_ref) {
+ if (path->target)
+ *target_ref = path->target->refcount;
+ else
+ *target_ref = 0;
+ }
+ if (device_ref) {
+ if (path->device)
+ *device_ref = path->device->refcount;
+ else
+ *device_ref = 0;
+ }
+}
/*
* Return -1 for failure, 0 for exact match, 1 for match with wildcards
@@ -4350,15 +4384,17 @@ static void
xpt_release_bus(struct cam_eb *bus)
{
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ KASSERT(bus->refcount >= 1, ("bus->refcount >= 1"));
if ((--bus->refcount == 0)
&& (TAILQ_FIRST(&bus->et_entries) == NULL)) {
- mtx_lock(&xsoftc.xpt_topo_lock);
TAILQ_REMOVE(&xsoftc.xpt_busses, bus, links);
xsoftc.bus_generation++;
mtx_unlock(&xsoftc.xpt_topo_lock);
cam_sim_release(bus->sim);
free(bus, M_CAMXPT);
- }
+ } else
+ mtx_unlock(&xsoftc.xpt_topo_lock);
}
static struct cam_et *
@@ -4381,7 +4417,9 @@ xpt_alloc_target(struct cam_eb *bus, tar
* Hold a reference to our parent bus so it
* will not go away before we do.
*/
+ mtx_lock(&xsoftc.xpt_topo_lock);
bus->refcount++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
/* Insertion sort into our bus's target list */
cur_target = TAILQ_FIRST(&bus->et_entries);
@@ -4402,15 +4440,17 @@ static void
xpt_release_target(struct cam_et *target)
{
- if ((--target->refcount == 0)
- && (TAILQ_FIRST(&target->ed_entries) == NULL)) {
- TAILQ_REMOVE(&target->bus->et_entries, target, links);
- target->bus->generation++;
- xpt_release_bus(target->bus);
- if (target->luns)
- free(target->luns, M_CAMXPT);
- free(target, M_CAMXPT);
- }
+ if (target->refcount == 1) {
+ if (TAILQ_FIRST(&target->ed_entries) == NULL) {
+ TAILQ_REMOVE(&target->bus->et_entries, target, links);
+ target->bus->generation++;
+ xpt_release_bus(target->bus);
+ if (target->luns)
+ free(target->luns, M_CAMXPT);
+ free(target, M_CAMXPT);
+ }
+ } else
+ target->refcount--;
}
static struct cam_ed *
@@ -4507,7 +4547,7 @@ void
xpt_release_device(struct cam_ed *device)
{
- if (--device->refcount == 0) {
+ if (device->refcount == 1) {
struct cam_devq *devq;
if (device->alloc_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX
@@ -4515,7 +4555,7 @@ xpt_release_device(struct cam_ed *device
panic("Removing device while still queued for ccbs");
if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0)
- callout_stop(&device->callout);
+ callout_stop(&device->callout);
TAILQ_REMOVE(&device->target->ed_entries, device,links);
device->target->generation++;
@@ -4527,7 +4567,8 @@ xpt_release_device(struct cam_ed *device
cam_ccbq_fini(&device->ccbq);
xpt_release_target(device->target);
free(device, M_CAMXPT);
- }
+ } else
+ device->refcount--;
}
u_int32_t
Modified: stable/8/sys/cam/cam_xpt.h
==============================================================================
--- stable/8/sys/cam/cam_xpt.h Sat Jun 9 08:41:30 2012 (r236799)
+++ stable/8/sys/cam/cam_xpt.h Sat Jun 9 08:51:25 2012 (r236800)
@@ -104,6 +104,9 @@ cam_status xpt_create_path_unlocked(str
path_id_t path_id,
target_id_t target_id, lun_id_t lun_id);
void xpt_free_path(struct cam_path *path);
+void xpt_path_counts(struct cam_path *path, uint32_t *bus_ref,
+ uint32_t *periph_ref, uint32_t *target_ref,
+ uint32_t *device_ref);
int xpt_path_comp(struct cam_path *path1,
struct cam_path *path2);
void xpt_print_path(struct cam_path *path);
@@ -136,4 +139,3 @@ void xpt_release_path(struct cam_path
#endif /* _KERNEL */
#endif /* _CAM_CAM_XPT_H */
-
More information about the svn-src-stable-8
mailing list