Date: Sat, 13 Oct 2012 11:23:16 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r241504 - head/sys/cam Message-ID: <201210131123.q9DBNGjK001654@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Sat Oct 13 11:23:16 2012 New Revision: 241504 URL: http://svn.freebsd.org/changeset/base/241504 Log: Fix XPT_DEBUG paths operations locking: - Extend the lock to cover xpt_path_release() for the new path. - While xpt_action() is called while holding right SIM lock for the new bus, the old path release may require different SIM lock. So we have to temporary drop the new lock and get the old one. Modified: head/sys/cam/cam_xpt.c Modified: head/sys/cam/cam_xpt.c ============================================================================== --- head/sys/cam/cam_xpt.c Sat Oct 13 10:18:36 2012 (r241503) +++ head/sys/cam/cam_xpt.c Sat Oct 13 11:23:16 2012 (r241504) @@ -533,9 +533,9 @@ xptioctl(struct cdev *dev, u_long cmd, c xpt_merge_ccb(&ccb, inccb); ccb.ccb_h.cbfcnp = xptdone; xpt_action(&ccb); - CAM_SIM_UNLOCK(bus->sim); bcopy(&ccb, inccb, sizeof(union ccb)); xpt_free_path(ccb.ccb_h.path); + CAM_SIM_UNLOCK(bus->sim); break; } @@ -2989,34 +2989,42 @@ xpt_action_default(union ccb *start_ccb) break; } case XPT_DEBUG: { + struct cam_path *oldpath; + struct cam_sim *oldsim; + /* Check that all request bits are supported. */ if (start_ccb->cdbg.flags & ~(CAM_DEBUG_COMPILE)) { start_ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; break; } - cam_dflags = start_ccb->cdbg.flags; + cam_dflags = CAM_DEBUG_NONE; if (cam_dpath != NULL) { - xpt_free_path(cam_dpath); + /* To release the old path we must hold proper lock. */ + oldpath = cam_dpath; cam_dpath = NULL; + oldsim = xpt_path_sim(oldpath); + CAM_SIM_UNLOCK(xpt_path_sim(start_ccb->ccb_h.path)); + CAM_SIM_LOCK(oldsim); + xpt_free_path(oldpath); + CAM_SIM_UNLOCK(oldsim); + CAM_SIM_LOCK(xpt_path_sim(start_ccb->ccb_h.path)); } - if (cam_dflags != CAM_DEBUG_NONE) { + if (start_ccb->cdbg.flags != CAM_DEBUG_NONE) { if (xpt_create_path(&cam_dpath, xpt_periph, start_ccb->ccb_h.path_id, start_ccb->ccb_h.target_id, start_ccb->ccb_h.target_lun) != CAM_REQ_CMP) { start_ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - cam_dflags = CAM_DEBUG_NONE; } else { + cam_dflags = start_ccb->cdbg.flags; start_ccb->ccb_h.status = CAM_REQ_CMP; xpt_print(cam_dpath, "debugging flags now %x\n", cam_dflags); } - } else { - cam_dpath = NULL; + } else start_ccb->ccb_h.status = CAM_REQ_CMP; - } break; } case XPT_FREEZE_QUEUE:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210131123.q9DBNGjK001654>