From owner-svn-src-all@FreeBSD.ORG Fri Jul 15 21:30:51 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 53EA3106564A; Fri, 15 Jul 2011 21:30:51 +0000 (UTC) (envelope-from mjacob@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 42DCF8FC0C; Fri, 15 Jul 2011 21:30:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p6FLUpoG096671; Fri, 15 Jul 2011 21:30:51 GMT (envelope-from mjacob@svn.freebsd.org) Received: (from mjacob@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p6FLUpqd096669; Fri, 15 Jul 2011 21:30:51 GMT (envelope-from mjacob@svn.freebsd.org) Message-Id: <201107152130.p6FLUpqd096669@svn.freebsd.org> From: Matt Jacob Date: Fri, 15 Jul 2011 21:30:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r224070 - stable/8/sys/cam/scsi X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Jul 2011 21:30:51 -0000 Author: mjacob Date: Fri Jul 15 21:30:50 2011 New Revision: 224070 URL: http://svn.freebsd.org/changeset/base/224070 Log: MFC of 197332: Remember to unlock the peripheral prior to notifying the user. Make some allocations M_NOWAIT so that we don't try and sleep with a nested non-sleepable lock. This makes the userland scsi_target begin to function again. Modified: stable/8/sys/cam/scsi/scsi_target.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/cam/scsi/scsi_target.c ============================================================================== --- stable/8/sys/cam/scsi/scsi_target.c Fri Jul 15 21:08:58 2011 (r224069) +++ stable/8/sys/cam/scsi/scsi_target.c Fri Jul 15 21:30:50 2011 (r224070) @@ -42,6 +42,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +/* Includes to support callout */ +#include +#include #include #include @@ -50,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include + /* Transaction information attached to each CCB sent by the user */ struct targ_cmd_descr { struct cam_periph_map_info mapinfo; @@ -92,6 +96,8 @@ struct targ_softc { targ_state state; struct selinfo read_select; struct devstat device_stats; + struct callout destroy_dev_callout; + struct mtx destroy_mtx; }; static d_open_t targopen; @@ -151,6 +157,7 @@ static void abort_all_pending(struct ta static void notify_user(struct targ_softc *softc); static int targcamstatus(cam_status status); static size_t targccblen(xpt_opcode func_code); +static void targdestroy(void *); static struct periph_driver targdriver = { @@ -208,10 +215,18 @@ targclose(struct cdev *dev, int flag, in int error; softc = (struct targ_softc *)dev->si_drv1; - if ((softc->periph == NULL) || - (softc->state & TARG_STATE_LUN_ENABLED) == 0) { + mtx_init(&softc->destroy_mtx, "targ_destroy", "SCSI Target dev destroy", MTX_DEF); + callout_init_mtx(&softc->destroy_dev_callout, &softc->destroy_mtx, CALLOUT_RETURNUNLOCKED); + if (softc->periph == NULL) { +#if 0 destroy_dev(dev); free(softc, M_TARG); +#endif + printf("%s: destroying non-enabled target\n", __func__); + mtx_lock(&softc->destroy_mtx); + callout_reset(&softc->destroy_dev_callout, hz / 2, + (void *)targdestroy, (void *)dev); + mtx_unlock(&softc->destroy_mtx); return (0); } @@ -223,18 +238,23 @@ targclose(struct cdev *dev, int flag, in cam_periph_acquire(periph); cam_periph_lock(periph); error = targdisable(softc); - if (error == CAM_REQ_CMP) { - dev->si_drv1 = 0; - if (softc->periph != NULL) { - cam_periph_invalidate(softc->periph); - softc->periph = NULL; - } - destroy_dev(dev); - free(softc, M_TARG); + if (softc->periph != NULL) { + cam_periph_invalidate(softc->periph); + softc->periph = NULL; } cam_periph_unlock(periph); cam_periph_release(periph); +#if 0 + destroy_dev(dev); + free(softc, M_TARG); +#endif + + printf("%s: close finished error(%d)\n", __func__, error); + mtx_lock(&softc->destroy_mtx); + callout_reset(&softc->destroy_dev_callout, hz / 2, + (void *)targdestroy, (void *)dev); + mtx_unlock(&softc->destroy_mtx); return (error); } @@ -818,7 +838,9 @@ targdone(struct cam_periph *periph, unio case XPT_CONT_TARGET_IO: TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h, periph_links.tqe); + cam_periph_unlock(softc->periph); notify_user(softc); + cam_periph_lock(softc->periph); break; default: panic("targdone: impossible xpt opcode %#x", @@ -966,13 +988,19 @@ targgetccb(struct targ_softc *softc, xpt int ccb_len; ccb_len = targccblen(type); - ccb = malloc(ccb_len, M_TARG, M_WAITOK); + ccb = malloc(ccb_len, M_TARG, M_NOWAIT); CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb)); - + if (ccb == NULL) { + return (ccb); + } xpt_setup_ccb(&ccb->ccb_h, softc->path, priority); ccb->ccb_h.func_code = type; ccb->ccb_h.cbfcnp = targdone; ccb->ccb_h.targ_descr = targgetdescr(softc); + if (ccb->ccb_h.targ_descr == NULL) { + free (ccb, M_TARG); + ccb = NULL; + } return (ccb); } @@ -1010,8 +1038,10 @@ targgetdescr(struct targ_softc *softc) struct targ_cmd_descr *descr; descr = malloc(sizeof(*descr), M_TARG, - M_WAITOK); - descr->mapinfo.num_bufs_used = 0; + M_NOWAIT); + if (descr) { + descr->mapinfo.num_bufs_used = 0; + } return (descr); } @@ -1091,8 +1121,11 @@ abort_all_pending(struct targ_softc *sof /* If we aborted anything from the work queue, wakeup user. */ if (!TAILQ_EMPTY(&softc->user_ccb_queue) - || !TAILQ_EMPTY(&softc->abort_queue)) + || !TAILQ_EMPTY(&softc->abort_queue)) { + cam_periph_unlock(softc->periph); notify_user(softc); + cam_periph_lock(softc->periph); + } } /* Notify the user that data is ready */ @@ -1185,3 +1218,25 @@ targccblen(xpt_opcode func_code) return (len); } + +/* + * work around to destroy targ device + * outside of targclose + */ +static void +targdestroy(void *dev) +{ + struct cdev *device = (struct cdev *)dev; + struct targ_softc *softc = (struct targ_softc *)device->si_drv1; + +#if 0 + callout_stop(&softc->destroy_dev_callout); +#endif + + mtx_unlock(&softc->destroy_mtx); + mtx_destroy(&softc->destroy_mtx); + free(softc, M_TARG); + device->si_drv1 = 0; + destroy_dev(device); + printf("%s: destroyed dev\n", __func__); +}