Change targ(4) to use cdevpriv, instead of multiple character devices.

Also update the manpage and the scsi_target example program accordingly.

Discussed on:	scsi@
Tested by:	Chuck Tuffli <chuck tuffli net>
This commit is contained in:
Ed Schouten 2011-12-13 21:26:33 +00:00
parent c0220d815a
commit 2f467d2d16
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=228481
3 changed files with 55 additions and 142 deletions

View File

@ -100,8 +100,8 @@ static void usage(void);
int
main(int argc, char *argv[])
{
int ch, unit;
char *file_name, targname[16];
int ch;
char *file_name;
u_int16_t req_flags, sim_flags;
off_t user_size;
@ -283,17 +283,11 @@ main(int argc, char *argv[])
warnx("aio support tested ok");
}
/* Go through all the control devices and find one that isn't busy. */
unit = 0;
do {
snprintf(targname, sizeof(targname), "/dev/targ%d", unit++);
targ_fd = open(targname, O_RDWR);
} while (targ_fd < 0 && errno == EBUSY);
targ_fd = open("/dev/targ", O_RDWR);
if (targ_fd < 0)
errx(1, "Tried to open %d devices, none available", unit);
err(1, "/dev/targ");
else
warnx("opened %s", targname);
warnx("opened /dev/targ");
/* The first three are handled by kevent() later */
signal(SIGHUP, SIG_IGN);

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd November 15, 2002
.Dd December 13, 2011
.Dt TARG 4
.Os
.Sh NAME
@ -49,16 +49,8 @@ can be found in
.Pp
The
.Nm
driver supplies control devices,
.Pa /dev/targ0 ,
.Pa /dev/targ1 ,
etc.
If a device is already in use,
.Xr open 2
will fail and
.Va errno
will be set to
.Er EBUSY .
driver supplies the control device
.Pa /dev/targ .
After opening the device, the file descriptor must be bound to a
specific bus/target/LUN and enabled to process CCBs using the
.Dv TARGIOCENABLE
@ -123,8 +115,8 @@ it.
describes the usermode interface.
.It Pa /sys/cam/scsi/scsi_target.c
is the driver source file.
.It Pa /dev/targ*
are the control devices.
.It Pa /dev/targ
is the control device.
.El
.Sh SEE ALSO
.Pa /usr/share/examples/scsi_target ,

View File

@ -96,12 +96,9 @@ 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;
static d_close_t targclose;
static d_read_t targread;
static d_write_t targwrite;
static d_ioctl_t targioctl;
@ -119,7 +116,6 @@ static struct cdevsw targ_cdevsw = {
.d_version = D_VERSION,
.d_flags = D_NEEDGIANT,
.d_open = targopen,
.d_close = targclose,
.d_read = targread,
.d_write = targwrite,
.d_ioctl = targioctl,
@ -152,15 +148,12 @@ static void targfreeccb(struct targ_softc *softc, union ccb *ccb);
static struct targ_cmd_descr *
targgetdescr(struct targ_softc *softc);
static periph_init_t targinit;
static void targclone(void *arg, struct ucred *cred, char *name,
int namelen, struct cdev **dev);
static void targasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg);
static void abort_all_pending(struct targ_softc *softc);
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 =
{
@ -171,31 +164,50 @@ PERIPHDRIVER_DECLARE(targ, targdriver);
static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
/* Disable LUN if enabled and teardown softc */
static void
targcdevdtor(void *data)
{
struct targ_softc *softc;
struct cam_periph *periph;
softc = data;
if (softc->periph == NULL) {
printf("%s: destroying non-enabled target\n", __func__);
free(softc, M_TARG);
return;
}
/*
* 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);
(void)targdisable(softc);
if (softc->periph != NULL) {
cam_periph_invalidate(softc->periph);
softc->periph = NULL;
}
cam_periph_unlock(periph);
cam_periph_release(periph);
free(softc, M_TARG);
}
/*
* 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.
* Create softc and initialize it. 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)
{
struct targ_softc *softc;
if (dev->si_drv1 != 0) {
return (EBUSY);
}
/* Mark device busy before any potentially blocking operations */
dev->si_drv1 = (void *)~0;
/* Create the targ device, allocate its softc, initialize it */
if ((dev->si_flags & SI_NAMED) == 0) {
make_dev(&targ_cdevsw, dev2unit(dev), UID_ROOT, GID_WHEEL, 0600,
"targ%d", dev2unit(dev));
}
/* Allocate its softc, initialize it */
softc = malloc(sizeof(*softc), M_TARG,
M_WAITOK | M_ZERO);
dev->si_drv1 = softc;
softc->state = TARG_STATE_OPENED;
softc->periph = NULL;
softc->path = NULL;
@ -206,61 +218,10 @@ targopen(struct cdev *dev, int flags, int fmt, struct thread *td)
TAILQ_INIT(&softc->user_ccb_queue);
knlist_init_mtx(&softc->read_select.si_note, NULL);
devfs_set_cdevpriv(softc, targcdevdtor);
return (0);
}
/* Disable LUN if enabled and teardown softc */
static int
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;
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);
}
/*
* 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 (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);
}
/* Enable/disable LUNs, set debugging level */
static int
targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
@ -268,7 +229,7 @@ targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
struct targ_softc *softc;
cam_status status;
softc = (struct targ_softc *)dev->si_drv1;
devfs_get_cdevpriv((void **)&softc);
switch (cmd) {
case TARGIOCENABLE:
@ -346,7 +307,7 @@ targpoll(struct cdev *dev, int poll_events, struct thread *td)
struct targ_softc *softc;
int revents;
softc = (struct targ_softc *)dev->si_drv1;
devfs_get_cdevpriv((void **)&softc);
/* Poll for write() is always ok. */
revents = poll_events & (POLLOUT | POLLWRNORM);
@ -371,7 +332,7 @@ targkqfilter(struct cdev *dev, struct knote *kn)
{
struct targ_softc *softc;
softc = (struct targ_softc *)dev->si_drv1;
devfs_get_cdevpriv((void **)&softc);
kn->kn_hook = (caddr_t)softc;
kn->kn_fop = &targread_filtops;
knlist_add(&softc->read_select.si_note, kn, 0);
@ -572,7 +533,7 @@ targwrite(struct cdev *dev, struct uio *uio, int ioflag)
int write_len, error;
int func_code, priority;
softc = (struct targ_softc *)dev->si_drv1;
devfs_get_cdevpriv((void **)&softc);
write_len = error = 0;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
("write - uio_resid %zd\n", uio->uio_resid));
@ -866,7 +827,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
error = 0;
read_len = 0;
softc = (struct targ_softc *)dev->si_drv1;
devfs_get_cdevpriv((void **)&softc);
user_queue = &softc->user_ccb_queue;
abort_queue = &softc->abort_queue;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
@ -1051,23 +1012,11 @@ targgetdescr(struct targ_softc *softc)
static void
targinit(void)
{
EVENTHANDLER_REGISTER(dev_clone, targclone, 0, 1000);
}
struct cdev *dev;
static void
targclone(void *arg, struct ucred *cred, char *name, int namelen,
struct cdev **dev)
{
int u;
if (*dev != NULL)
return;
if (dev_stdclone(name, NULL, "targ", &u) != 1)
return;
*dev = make_dev(&targ_cdevsw, u, UID_ROOT, GID_WHEEL,
0600, "targ%d", u);
dev_ref(*dev);
(*dev)->si_flags |= SI_CHEAPCLONE;
/* Add symbolic link to targ0 for compatibility. */
dev = make_dev(&targ_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "targ");
make_dev_alias(dev, "targ0");
}
static void
@ -1221,25 +1170,3 @@ 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__);
}