summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2008-08-15 13:07:07 +0000
committered <ed@FreeBSD.org>2008-08-15 13:07:07 +0000
commitbd507c7cef0d90ce480caf8fccc35b5868afa229 (patch)
tree97fa442f4619eff0b084537b42202b5555ff9c24
parent311231d490d114d702898a3547094efcbd883851 (diff)
downloadFreeBSD-src-bd507c7cef0d90ce480caf8fccc35b5868afa229.zip
FreeBSD-src-bd507c7cef0d90ce480caf8fccc35b5868afa229.tar.gz
Convert the snp(4) driver to use cdevpriv.
Now we have a single /dev/snp device node, which can be opened by watch(8) multiple times. Even though snp(4) will be dead as of next week, it's nice having this in SVN, because: - We may want to MFC it to RELENG_7. - By the time we fix snp(4) again, it's already there, existing watch(8) binaries should already work. Just like bpf(4), I'm adding a symlink from snp0 to snp to remain binary compatible.
-rw-r--r--share/man/man4/snp.44
-rw-r--r--sys/dev/snp/snp.c112
-rw-r--r--usr.sbin/watch/watch.c23
3 files changed, 55 insertions, 84 deletions
diff --git a/share/man/man4/snp.4 b/share/man/man4/snp.4
index df70cb2..76bcc53 100644
--- a/share/man/man4/snp.4
+++ b/share/man/man4/snp.4
@@ -16,8 +16,8 @@
.Ft int
.Fn ioctl fd FIONREAD &result
.Sh DESCRIPTION
-.Pa /dev/snp?
-are snoop devices which allow users to attach to any tty
+.Pa /dev/snp
+is a snoop device which allows users to attach to any tty
and watch activities on it.
The kernel must be compiled with
.Cd "device snp" ,
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index 3b52e48..417b357 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
static l_close_t snplclose;
static l_write_t snplwrite;
static d_open_t snpopen;
-static d_close_t snpclose;
static d_read_t snpread;
static d_write_t snpwrite;
static d_ioctl_t snpioctl;
@@ -46,7 +45,6 @@ static struct cdevsw snp_cdevsw = {
.d_version = D_VERSION,
.d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR,
.d_open = snpopen,
- .d_close = snpclose,
.d_read = snpread,
.d_write = snpwrite,
.d_ioctl = snpioctl,
@@ -70,7 +68,6 @@ static struct linesw snpdisc = {
*/
struct snoop {
LIST_ENTRY(snoop) snp_list; /* List glue. */
- int snp_unit; /* Device number. */
struct cdev *snp_target; /* Target tty device. */
struct tty *snp_tty; /* Target tty pointer. */
u_long snp_len; /* Possible length. */
@@ -111,13 +108,11 @@ static MALLOC_DEFINE(M_SNP, "snp", "Snoop device data");
* module load time.
*/
static int snooplinedisc;
+static struct cdev *snoopdev;
static LIST_HEAD(, snoop) snp_sclist = LIST_HEAD_INITIALIZER(&snp_sclist);
-static struct clonedevs *snpclones;
static struct tty *snpdevtotty(struct cdev *dev);
-static void snp_clone(void *arg, struct ucred *cred, char *name,
- int namelen, struct cdev **dev);
static void snp_detach(void *arg);
static int snp_down(struct snoop *snp);
static int snp_in(struct snoop *snp, char *buf, int n);
@@ -220,14 +215,17 @@ snpwrite(struct cdev *dev, struct uio *uio, int flag)
int error, i, len;
unsigned char c[SNP_INPUT_BUF];
- snp = dev->si_drv1;
+ error = devfs_get_cdevpriv((void **)&snp);
+ if (error != 0)
+ return (error);
+
tp = snp->snp_tty;
if (tp == NULL)
return (EIO);
if ((tp->t_state & TS_SNOOP) && tp->t_line == snooplinedisc)
goto tty_input;
- printf("snp%d: attempt to write to bad tty\n", snp->snp_unit);
+ printf("snp: attempt to write to bad tty\n");
return (EIO);
tty_input:
@@ -255,7 +253,10 @@ snpread(struct cdev *dev, struct uio *uio, int flag)
caddr_t from;
char *nbuf;
- snp = dev->si_drv1;
+ error = devfs_get_cdevpriv((void **)&snp);
+ if (error != 0)
+ return (error);
+
KASSERT(snp->snp_len + snp->snp_base <= snp->snp_blen,
("snoop buffer error"));
@@ -324,12 +325,12 @@ snp_in(struct snoop *snp, char *buf, int n)
return (0);
if (snp->snp_flags & SNOOP_DOWN) {
- printf("snp%d: more data to down interface\n", snp->snp_unit);
+ printf("snp: more data to down interface\n");
return (0);
}
if (snp->snp_flags & SNOOP_OFLOW) {
- printf("snp%d: buffer overflow\n", snp->snp_unit);
+ printf("snp: buffer overflow\n");
/*
* On overflow we just repeat the standart close
* procedure...yes , this is waste of space but.. Then next
@@ -387,18 +388,30 @@ snp_in(struct snoop *snp, char *buf, int n)
return (n);
}
+static void
+snp_dtor(void *data)
+{
+ struct snoop *snp = data;
+
+ snp->snp_blen = 0;
+ LIST_REMOVE(snp, snp_list);
+ free(snp->snp_buf, M_SNP);
+ snp->snp_flags &= ~SNOOP_OPEN;
+ snp_detach(snp);
+}
+
static int
snpopen(struct cdev *dev, int flag, int mode, struct thread *td)
{
struct snoop *snp;
+ int error;
- if (dev->si_drv1 == NULL) {
- dev->si_flags &= ~SI_CHEAPCLONE;
- dev->si_drv1 = snp = malloc(sizeof(*snp), M_SNP,
- M_WAITOK | M_ZERO);
- snp->snp_unit = dev2unit(dev);
- } else
- return (EBUSY);
+ snp = malloc(sizeof(*snp), M_SNP, M_WAITOK | M_ZERO);
+ error = devfs_set_cdevpriv(snp, snp_dtor);
+ if (error != 0) {
+ free(snp, M_SNP);
+ return (error);
+ }
/*
* We intentionally do not OR flags with SNOOP_OPEN, but set them so
@@ -444,7 +457,7 @@ snp_detach(void *arg)
tp->t_state &= ~TS_SNOOP;
tp->t_line = snp->snp_olddisc;
} else
- printf("snp%d: bad attached tty data\n", snp->snp_unit);
+ printf("snp: bad attached tty data\n");
snp->snp_tty = NULL;
snp->snp_target = NULL;
@@ -456,23 +469,6 @@ detach_notty:
}
static int
-snpclose(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
- struct snoop *snp;
-
- snp = dev->si_drv1;
- snp->snp_blen = 0;
- LIST_REMOVE(snp, snp_list);
- free(snp->snp_buf, M_SNP);
- snp->snp_flags &= ~SNOOP_OPEN;
- dev->si_drv1 = NULL;
- snp_detach(snp);
- destroy_dev_sched(dev);
-
- return (0);
-}
-
-static int
snp_down(struct snoop *snp)
{
@@ -495,9 +491,12 @@ snpioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
struct tty *tp;
struct cdev *tdev;
struct file *fp;
- int s;
+ int error, s;
+
+ error = devfs_get_cdevpriv((void **)&snp);
+ if (error != 0)
+ return (error);
- snp = dev->si_drv1;
switch (cmd) {
case SNPSTTY:
s = *(int *)data;
@@ -587,7 +586,10 @@ snppoll(struct cdev *dev, int events, struct thread *td)
struct snoop *snp;
int revents;
- snp = dev->si_drv1;
+ if (devfs_get_cdevpriv((void **)&snp) != 0)
+ return (events &
+ (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
+
revents = 0;
/*
* If snoop is down, we don't want to poll() forever so we return 1.
@@ -603,44 +605,22 @@ snppoll(struct cdev *dev, int events, struct thread *td)
return (revents);
}
-static void
-snp_clone(void *arg, struct ucred *cred, char *name, int namelen,
- struct cdev **dev)
-{
- int u, i;
-
- if (*dev != NULL)
- return;
- if (dev_stdclone(name, NULL, "snp", &u) != 1)
- return;
- i = clone_create(&snpclones, &snp_cdevsw, &u, dev, 0);
- if (i)
- *dev = make_dev_credf(MAKEDEV_REF, &snp_cdevsw, unit2minor(u),
- NULL, UID_ROOT, GID_WHEEL, 0600, "snp%d", u);
- if (*dev != NULL) {
- (*dev)->si_flags |= SI_CHEAPCLONE;
- }
-}
-
static int
snp_modevent(module_t mod, int type, void *data)
{
- static eventhandler_tag eh_tag;
switch (type) {
case MOD_LOAD:
- /* XXX error checking. */
- clone_setup(&snpclones);
- eh_tag = EVENTHANDLER_REGISTER(dev_clone, snp_clone, 0, 1000);
snooplinedisc = ldisc_register(LDISC_LOAD, &snpdisc);
+ snoopdev = make_dev(&snp_cdevsw, 0, UID_ROOT, GID_WHEEL,
+ 0600, "snp");
+ /* For compatibility */
+ make_dev_alias(snoopdev, "snp0");
break;
case MOD_UNLOAD:
if (!LIST_EMPTY(&snp_sclist))
return (EBUSY);
- EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
- drain_dev_clone_events();
- clone_cleanup(&snpclones);
- destroy_dev_drain(&snp_cdevsw);
+ destroy_dev(snoopdev);
ldisc_deregister(snooplinedisc);
break;
default:
diff --git a/usr.sbin/watch/watch.c b/usr.sbin/watch/watch.c
index cc833ef..388614e 100644
--- a/usr.sbin/watch/watch.c
+++ b/usr.sbin/watch/watch.c
@@ -152,30 +152,21 @@ fatal(int error, const char *buf)
static int
open_snp(void)
{
- char snp[] = {_PATH_DEV "snpXXX"};
- int f, mode, pos, c;
+ int f, mode;
- pos = strlen(snp) - 3;
if (opt_write)
mode = O_RDWR;
else
mode = O_RDONLY;
if (opt_snpdev == NULL)
- for (c = 0; c <= 999; c++) {
- snprintf(snp+pos, 4, "%d", c);
- if ((f = open(snp, mode)) < 0) {
- if (errno == EBUSY)
- continue;
- err(1, "open %s", snp);
- }
- return f;
- }
+ f = open(_PATH_DEV "snp", mode);
else
- if ((f = open(opt_snpdev, mode)) != -1)
- return (f);
- fatal(EX_OSFILE, "cannot open snoop device");
- return (0);
+ f = open(opt_snpdev, mode);
+ if (f == -1)
+ fatal(EX_OSFILE, "cannot open snoop device");
+
+ return (f);
}
OpenPOWER on IntegriCloud