Date: Sat, 9 Jun 2012 08:51:26 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r236800 - stable/8/sys/cam Message-ID: <201206090851.q598pQxg018870@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */ -
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206090851.q598pQxg018870>