From owner-svn-src-head@FreeBSD.ORG Sat Sep 19 20:25:55 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1E8DA106566B; Sat, 19 Sep 2009 20:25:55 +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 0D7D98FC28; Sat, 19 Sep 2009 20:25:55 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n8JKPsRI034527; Sat, 19 Sep 2009 20:25:54 GMT (envelope-from mjacob@svn.freebsd.org) Received: (from mjacob@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8JKPste034525; Sat, 19 Sep 2009 20:25:54 GMT (envelope-from mjacob@svn.freebsd.org) Message-Id: <200909192025.n8JKPste034525@svn.freebsd.org> From: Matt Jacob Date: Sat, 19 Sep 2009 20:25:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197332 - head/sys/cam/scsi X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Sep 2009 20:25:55 -0000 Author: mjacob Date: Sat Sep 19 20:25:54 2009 New Revision: 197332 URL: http://svn.freebsd.org/changeset/base/197332 Log: 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. Obtained from: Sean Bruno MFC after: 1 month Modified: head/sys/cam/scsi/scsi_target.c Modified: head/sys/cam/scsi/scsi_target.c ============================================================================== --- head/sys/cam/scsi/scsi_target.c Sat Sep 19 18:01:32 2009 (r197331) +++ head/sys/cam/scsi/scsi_target.c Sat Sep 19 20:25:54 2009 (r197332) @@ -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; @@ -154,6 +160,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 = { @@ -211,10 +218,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); } @@ -226,18 +241,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); } @@ -821,7 +841,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", @@ -969,13 +991,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); } @@ -1013,8 +1041,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); } @@ -1094,8 +1124,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 */ @@ -1188,3 +1221,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__); +}