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:
parent
d72c481378
commit
4c8503deb3
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user