Date: Fri, 13 Apr 2007 15:55:47 GMT From: Scott Long <scottl@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 118008 for review Message-ID: <200704131555.l3DFtlhe074896@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118008 Change 118008 by scottl@scottl-y1 on 2007/04/13 15:54:55 Untested but hopefully functional locking for the target driver. Affected files ... .. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_target.c#10 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_target.c#10 (text+ko) ==== @@ -47,6 +47,7 @@ #include <cam/cam_ccb.h> #include <cam/cam_periph.h> #include <cam/cam_xpt_periph.h> +#include <cam/cam_sim.h> #include <cam/scsi/scsi_targetio.h> /* Transaction information attached to each CCB sent by the user */ @@ -160,7 +161,11 @@ static MALLOC_DEFINE(M_TARG, "TARG", "TARG data"); -/* Create softc and initialize it. Only one proc can open each targ device. */ +/* + * Create softc and initialize it. Only one proc can open each targ device. + * There is no locking here because a periph doesn't get created until an + * ioctl is issued to do so, and that can't happen until this method returns. + */ static int targopen(struct cdev *dev, int flags, int fmt, struct thread *td) { @@ -199,9 +204,24 @@ targclose(struct cdev *dev, int flag, int fmt, struct thread *td) { struct targ_softc *softc; + struct cam_periph *periph; int error; softc = (struct targ_softc *)dev->si_drv1; + if ((softc->periph == NULL) || + (softc->state & TARG_STATE_LUN_ENABLED) == 0) { + destroy_dev(dev); + FREE(softc, M_TARG); + return (0); + } + + /* + * Acquire a hold on the periph so that it doesn't go away before + * we are ready at the end of the function. + */ + periph = softc->periph; + cam_periph_acquire(periph); + cam_periph_lock(periph); error = targdisable(softc); if (error == CAM_REQ_CMP) { dev->si_drv1 = 0; @@ -212,6 +232,9 @@ destroy_dev(dev); FREE(softc, M_TARG); } + cam_periph_unlock(periph); + cam_periph_release(periph); + return (error); } @@ -229,44 +252,56 @@ { struct ioc_enable_lun *new_lun; struct cam_path *path; + struct cam_sim *sim; new_lun = (struct ioc_enable_lun *)addr; - status = xpt_create_path(&path, /*periph*/NULL, - new_lun->path_id, - new_lun->target_id, - new_lun->lun_id); + status = xpt_create_path_unlocked(&path, /*periph*/NULL, + new_lun->path_id, + new_lun->target_id, + new_lun->lun_id); if (status != CAM_REQ_CMP) { printf("Couldn't create path, status %#x\n", status); break; } + sim = xpt_path_sim(path); + mtx_lock(sim->mtx); status = targenable(softc, path, new_lun->grp6_len, new_lun->grp7_len); xpt_free_path(path); + mtx_unlock(sim->mtx); break; } case TARGIOCDISABLE: + if (softc->periph == NULL) { + status = CAM_DEV_NOT_THERE; + break; + } + cam_periph_lock(softc->periph); status = targdisable(softc); + cam_periph_unlock(softc->periph); break; case TARGIOCDEBUG: { #ifdef CAMDEBUG struct ccb_debug cdbg; + /* If no periph available, disallow debugging changes */ + if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) { + status = CAM_DEV_NOT_THERE; + break; + } bzero(&cdbg, sizeof cdbg); if (*((int *)addr) != 0) cdbg.flags = CAM_DEBUG_PERIPH; else cdbg.flags = CAM_DEBUG_NONE; + cam_periph_lock(softc->periph); xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0); cdbg.ccb_h.func_code = XPT_DEBUG; cdbg.ccb_h.cbfcnp = targdone; - /* If no periph available, disallow debugging changes */ - if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) { - status = CAM_DEV_NOT_THERE; - break; - } xpt_action((union ccb *)&cdbg); + cam_periph_unlock(softc->periph); status = cdbg.ccb_h.status & CAM_STATUS_MASK; #else status = CAM_FUNC_NOTAVAIL; @@ -294,10 +329,12 @@ revents = poll_events & (POLLOUT | POLLWRNORM); if ((poll_events & (POLLIN | POLLRDNORM)) != 0) { /* Poll for read() depends on user and abort queues. */ + cam_periph_lock(softc->periph); if (!TAILQ_EMPTY(&softc->user_ccb_queue) || !TAILQ_EMPTY(&softc->abort_queue)) { revents |= poll_events & (POLLIN | POLLRDNORM); } + cam_periph_unlock(softc->periph); /* Only sleep if the user didn't poll for write. */ if (revents == 0) selrecord(td, &softc->read_select); @@ -335,8 +372,10 @@ int retval; softc = (struct targ_softc *)kn->kn_hook; + cam_periph_lock(softc->periph); retval = !TAILQ_EMPTY(&softc->user_ccb_queue) || !TAILQ_EMPTY(&softc->abort_queue); + cam_periph_unlock(softc->periph); return (retval); } @@ -532,6 +571,7 @@ switch (func_code) { case XPT_ACCEPT_TARGET_IO: case XPT_IMMED_NOTIFY: + cam_periph_lock(softc->periph); ccb = targgetccb(softc, func_code, priority); descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr; descr->user_ccb = user_ccb; @@ -542,8 +582,10 @@ TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, &ccb->ccb_h, periph_links.tqe); + cam_periph_unlock(softc->periph); break; default: + cam_periph_lock(softc->periph); if ((func_code & XPT_FC_QUEUED) != 0) { CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("Sending queued ccb %#x (%p)\n", @@ -569,6 +611,7 @@ targsendccb(softc, ccb, descr); targreturnccb(softc, ccb); } + cam_periph_unlock(softc->periph); break; } write_len += sizeof(user_ccb); @@ -796,8 +839,6 @@ union ccb *user_ccb; int read_len, error; - mtx_lock(&Giant); - error = 0; read_len = 0; softc = (struct targ_softc *)dev->si_drv1; @@ -806,11 +847,12 @@ CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n")); /* If no data is available, wait or return immediately */ + cam_periph_lock(softc->periph); ccb_h = TAILQ_FIRST(user_queue); user_descr = TAILQ_FIRST(abort_queue); while (ccb_h == NULL && user_descr == NULL) { if ((ioflag & IO_NDELAY) == 0) { - error = tsleep(user_queue, + error = msleep(user_queue, softc->periph->sim->mtx, PRIBIO | PCATCH, "targrd", 0); ccb_h = TAILQ_FIRST(user_queue); user_descr = TAILQ_FIRST(abort_queue); @@ -822,7 +864,7 @@ } } } else { - mtx_unlock(&Giant); + cam_periph_unlock(softc->periph); return (EAGAIN); } } @@ -841,7 +883,9 @@ error = targreturnccb(softc, (union ccb *)ccb_h); if (error != 0) goto read_fail; + cam_periph_unlock(softc->periph); error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio); + cam_periph_lock(softc->periph); if (error != 0) goto read_fail; read_len += sizeof(user_ccb); @@ -859,7 +903,9 @@ ("targread aborted descr %p (%p)\n", user_descr, user_ccb)); suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED); + cam_periph_unlock(softc->periph); error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio); + cam_periph_lock(softc->periph); if (error != 0) goto read_fail; read_len += sizeof(user_ccb); @@ -876,7 +922,7 @@ error = ENOSPC; read_fail: - mtx_unlock(&Giant); + cam_periph_unlock(softc->periph); return (error); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704131555.l3DFtlhe074896>