svn commit: r208752 - head/sys/cam
Chagin Dmitry
dchagin at freebsd.org
Mon Jun 28 21:23:15 UTC 2010
On Wed, Jun 02, 2010 at 06:06:32PM +0000, Matt Jacob wrote:
> Author: mjacob
> Date: Wed Jun 2 18:06:32 2010
> New Revision: 208752
> URL: http://svn.freebsd.org/changeset/base/208752
>
> Log:
> Protect periph drivers list and rearrange things to minimize the chance of
> stepping oneself during probing.
>
> Don't blindly decrement a periph probe count.
>
This commit causes a kernel panic on cdrecord -scanbus:
Unread portion of the kernel message buffer:
panic: _mtx_lock_sleep: recursed on non-recursive mutex XPT topology
lock @ /work/head/sys/cam/cam_xpt.c:4814
#11 0xffffffff80319dd9 in _mtx_lock_flags (m=0xffffffff808761d8,
opts=0x0,
file=0xffffffff8061ae4f "/work/head/sys/cam/cam_xpt.c", line=0x12ce)
at /work/head/sys/kern/kern_mutex.c:203
#12 0xffffffff80179adc in xptpdperiphtraverse (pdrv=0xffffff000377e600,
start_periph=0x0,
tr_func=0xffffffff8017a670 <xptplistperiphfunc>,
arg=0xffffff006b872000) at /work/head/sys/cam/cam_xpt.c:2151
#13 0xffffffff80179753 in xptpdrvtraverse (start_pdrv=Variable
"start_pdrv" is not available.
) at /work/head/sys/cam/cam_xpt.c:2132
#14 0xffffffff8017fd09 in xpt_action_default
(start_ccb=0xffffff006b872000) at /work/head/sys/cam/cam_xpt.c:1967
#15 0xffffffff8017bc63 in xptioctl (dev=Variable "dev" is not available.
) at /work/head/sys/cam/cam_xpt.c:598
#16 0xffffffff802bc3c6 in devfs_ioctl_f (fp=0xffffff006b4a0a00,
com=0xc4a81502, data=Variable "data" is not available.
)
at /work/head/sys/fs/devfs/devfs_vnops.c:669
#17 0xffffffff80379632 in kern_ioctl (td=0xffffff006b4b83f0, fd=Variable
"fd" is not available.
) at file.h:254
#18 0xffffffff80379890 in ioctl (td=0xffffff006b4b83f0,
uap=0xffffff80b1312bf0)
at /work/head/sys/kern/sys_generic.c:678
> Reviewed by: scsi@
> Obtained from: Alexander Motin, Atillio Rao, Others
> MFC after: 1 month
>
> Modified:
> head/sys/cam/cam_periph.c
> head/sys/cam/cam_xpt.c
>
> Modified: head/sys/cam/cam_periph.c
> ==============================================================================
> --- head/sys/cam/cam_periph.c Wed Jun 2 17:27:23 2010 (r208751)
> +++ head/sys/cam/cam_periph.c Wed Jun 2 18:06:32 2010 (r208752)
> @@ -185,17 +185,6 @@ cam_periph_alloc(periph_ctor_t *periph_c
>
> init_level++;
>
> - xpt_lock_buses();
> - for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
> - if (strcmp((*p_drv)->driver_name, name) == 0)
> - break;
> - }
> - xpt_unlock_buses();
> - if (*p_drv == NULL) {
> - printf("cam_periph_alloc: invalid periph name '%s'\n", name);
> - free(periph, M_CAMPERIPH);
> - return (CAM_REQ_INVALID);
> - }
>
> sim = xpt_path_sim(path);
> path_id = xpt_path_path_id(path);
> @@ -208,7 +197,6 @@ cam_periph_alloc(periph_ctor_t *periph_c
> periph->periph_oninval = periph_oninvalidate;
> periph->type = type;
> periph->periph_name = name;
> - periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id);
> periph->immediate_priority = CAM_PRIORITY_NONE;
> periph->refcount = 0;
> periph->sim = sim;
> @@ -216,26 +204,39 @@ cam_periph_alloc(periph_ctor_t *periph_c
> status = xpt_create_path(&path, periph, path_id, target_id, lun_id);
> if (status != CAM_REQ_CMP)
> goto failure;
> -
> periph->path = path;
> - init_level++;
> -
> - status = xpt_add_periph(periph);
> -
> - if (status != CAM_REQ_CMP)
> - goto failure;
>
> + xpt_lock_buses();
> + for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
> + if (strcmp((*p_drv)->driver_name, name) == 0)
> + break;
> + }
> + if (*p_drv == NULL) {
> + printf("cam_periph_alloc: invalid periph name '%s'\n", name);
> + xpt_free_path(periph->path);
> + free(periph, M_CAMPERIPH);
> + xpt_unlock_buses();
> + return (CAM_REQ_INVALID);
> + }
> + periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id);
> cur_periph = TAILQ_FIRST(&(*p_drv)->units);
> while (cur_periph != NULL
> && cur_periph->unit_number < periph->unit_number)
> cur_periph = TAILQ_NEXT(cur_periph, unit_links);
> -
> - if (cur_periph != NULL)
> + if (cur_periph != NULL) {
> + KASSERT(cur_periph->unit_number != periph->unit_number, ("duplicate units on periph list"));
> TAILQ_INSERT_BEFORE(cur_periph, periph, unit_links);
> - else {
> + } else {
> TAILQ_INSERT_TAIL(&(*p_drv)->units, periph, unit_links);
> (*p_drv)->generation++;
> }
> + xpt_unlock_buses();
> +
> + init_level++;
> +
> + status = xpt_add_periph(periph);
> + if (status != CAM_REQ_CMP)
> + goto failure;
>
> init_level++;
>
> @@ -250,10 +251,12 @@ failure:
> /* Initialized successfully */
> break;
> case 3:
> - TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
> xpt_remove_periph(periph);
> /* FALLTHROUGH */
> case 2:
> + xpt_lock_buses();
> + TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
> + xpt_unlock_buses();
> xpt_free_path(periph->path);
> /* FALLTHROUGH */
> case 1:
> @@ -288,6 +291,7 @@ cam_periph_find(struct cam_path *path, c
> TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) {
> if (xpt_path_comp(periph->path, path) == 0) {
> xpt_unlock_buses();
> + mtx_assert(periph->sim->mtx, MA_OWNED);
> return(periph);
> }
> }
> @@ -322,8 +326,13 @@ cam_periph_release_locked(struct cam_per
> return;
>
> xpt_lock_buses();
> - if ((--periph->refcount == 0)
> - && (periph->flags & CAM_PERIPH_INVALID)) {
> + if (periph->refcount != 0) {
> + periph->refcount--;
> + } else {
> + xpt_print(periph->path, "%s: release %p when refcount is zero\n ", __func__, periph);
> + }
> + if (periph->refcount == 0
> + && (periph->flags & CAM_PERIPH_INVALID)) {
> camperiphfree(periph);
> }
> xpt_unlock_buses();
>
> Modified: head/sys/cam/cam_xpt.c
> ==============================================================================
> --- head/sys/cam/cam_xpt.c Wed Jun 2 17:27:23 2010 (r208751)
> +++ head/sys/cam/cam_xpt.c Wed Jun 2 18:06:32 2010 (r208752)
> @@ -2138,6 +2138,7 @@ xptpdperiphtraverse(struct periph_driver
>
> retval = 1;
>
> + xpt_lock_buses();
already acquired in xpt_action_default?
> for (periph = (start_periph ? start_periph :
> TAILQ_FIRST(&(*pdrv)->units)); periph != NULL;
> periph = next_periph) {
> @@ -2145,9 +2146,12 @@ xptpdperiphtraverse(struct periph_driver
> next_periph = TAILQ_NEXT(periph, unit_links);
>
> retval = tr_func(periph, arg);
> - if (retval == 0)
> + if (retval == 0) {
> + xpt_unlock_buses();
> return(retval);
> + }
> }
> + xpt_unlock_buses();
> return(retval);
> }
>
> @@ -2323,7 +2327,6 @@ xpt_action_default(union ccb *start_ccb)
>
> CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action_default\n"));
>
> -
> switch (start_ccb->ccb_h.func_code) {
> case XPT_SCSI_IO:
> {
> @@ -2670,7 +2673,9 @@ xpt_action_default(union ccb *start_ccb)
> xptedtmatch(cdm);
> break;
> case CAM_DEV_POS_PDRV:
> + xpt_lock_buses();
> xptperiphlistmatch(cdm);
> + xpt_unlock_buses();
> break;
> default:
> cdm->status = CAM_DEV_MATCH_ERROR;
--
Have fun!
chd
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/svn-src-all/attachments/20100628/4faf2ca2/attachment.pgp
More information about the svn-src-all
mailing list