devfs: Move most ioctl logic down to vnode layer

Devfs' file layer ioctl is now just a thin shim around the vnode layer.

Reviewed by:	kib
Sponsored by:	EMC / Isilon Storage Division
Differential Revision:	https://reviews.freebsd.org/D7286
This commit is contained in:
cem 2016-07-25 16:28:02 +00:00
parent d72c481378
commit 4c8503deb3
2 changed files with 45 additions and 24 deletions

View File

@ -779,47 +779,61 @@ devfs_getattr(struct vop_getattr_args *ap)
static int
devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struct thread *td)
{
struct cdev *dev;
struct cdevsw *dsw;
struct vnode *vp;
struct vnode *vpold;
int error, i, ref;
const char *p;
struct fiodgname_arg *fgn;
struct file *fpop;
int error;
fpop = td->td_fpop;
error = devfs_fp_check(fp, &dev, &dsw, &ref);
if (error != 0) {
error = vnops.fo_ioctl(fp, com, data, cred, td);
return (error);
}
td->td_fpop = fp;
error = vnops.fo_ioctl(fp, com, data, cred, td);
td->td_fpop = fpop;
return (error);
}
static int
devfs_ioctl(struct vop_ioctl_args *ap)
{
struct fiodgname_arg *fgn;
struct vnode *vpold, *vp;
struct cdevsw *dsw;
struct thread *td;
struct cdev *dev;
int error, ref, i;
const char *p;
u_long com;
vp = ap->a_vp;
com = ap->a_command;
td = ap->a_td;
dsw = devvn_refthread(vp, &dev, &ref);
if (dsw == NULL)
return (ENXIO);
KASSERT(dev->si_refcount > 0,
("devfs: un-referenced struct cdev *(%s)", devtoname(dev)));
if (com == FIODTYPE) {
*(int *)data = dsw->d_flags & D_TYPEMASK;
td->td_fpop = fpop;
dev_relthread(dev, ref);
return (0);
*(int *)ap->a_data = dsw->d_flags & D_TYPEMASK;
error = 0;
goto out;
} else if (com == FIODGNAME) {
fgn = data;
fgn = ap->a_data;
p = devtoname(dev);
i = strlen(p) + 1;
if (i > fgn->len)
error = EINVAL;
else
error = copyout(p, fgn->buf, i);
td->td_fpop = fpop;
dev_relthread(dev, ref);
return (error);
goto out;
}
error = dsw->d_ioctl(dev, com, data, fp->f_flag, td);
td->td_fpop = NULL;
error = dsw->d_ioctl(dev, com, ap->a_data, ap->a_fflag, td);
out:
dev_relthread(dev, ref);
if (error == ENOIOCTL)
error = ENOTTY;
if (error == 0 && com == TIOCSCTTY) {
vp = fp->f_vnode;
if (error == 0 && com == TIOCSCTTY) {
/* Do nothing if reassigning same control tty */
sx_slock(&proctree_lock);
if (td->td_proc->p_session->s_ttyvp == vp) {
@ -1862,6 +1876,7 @@ static struct fileops devfs_ops_f = {
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
/* Vops for non-CHR vnodes in /dev. */
static struct vop_vector devfs_vnodeops = {
.vop_default = &default_vnodeops,
@ -1885,6 +1900,7 @@ static struct vop_vector devfs_vnodeops = {
.vop_vptocnp = devfs_vptocnp,
};
/* Vops for VCHR vnodes in /dev. */
static struct vop_vector devfs_specops = {
.vop_default = &default_vnodeops,
@ -1894,6 +1910,7 @@ static struct vop_vector devfs_specops = {
.vop_create = VOP_PANIC,
.vop_fsync = devfs_fsync,
.vop_getattr = devfs_getattr,
.vop_ioctl = devfs_ioctl,
.vop_link = VOP_PANIC,
.vop_mkdir = VOP_PANIC,
.vop_mknod = VOP_PANIC,

View File

@ -1492,6 +1492,10 @@ vn_ioctl(fp, com, data, active_cred, td)
return (VOP_IOCTL(vp, com, data, fp->f_flag,
active_cred, td));
}
break;
case VCHR:
return (VOP_IOCTL(vp, com, data, fp->f_flag,
active_cred, td));
default:
return (ENOTTY);
}