PERFORCE change 118008 for review
Scott Long
scottl at FreeBSD.org
Fri Apr 13 15:55:48 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=118008
Change 118008 by scottl at 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);
}
More information about the p4-projects
mailing list