diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 955fcfd78ddb..6a9d144cf9ec 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -86,6 +87,7 @@ static int vop_stdadd_writecount(struct vop_add_writecount_args *ap); static int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap); static int vop_stdfdatasync(struct vop_fdatasync_args *ap); static int vop_stdgetpages_async(struct vop_getpages_async_args *ap); +static int vop_stdioctl(struct vop_ioctl_args *ap); /* * This vnode table stores what we want to do if the filesystem doesn't @@ -118,7 +120,7 @@ struct vop_vector default_vnodeops = { .vop_getpages_async = vop_stdgetpages_async, .vop_getwritemount = vop_stdgetwritemount, .vop_inactive = VOP_NULL, - .vop_ioctl = VOP_ENOTTY, + .vop_ioctl = vop_stdioctl, .vop_kqfilter = vop_stdkqfilter, .vop_islocked = vop_stdislocked, .vop_lock1 = vop_stdlock, @@ -1155,6 +1157,41 @@ vop_stdadd_writecount(struct vop_add_writecount_args *ap) return (error); } +static int +vop_stdioctl(struct vop_ioctl_args *ap) +{ + struct vnode *vp; + struct vattr va; + off_t *offp; + int error; + + switch (ap->a_command) { + case FIOSEEKDATA: + case FIOSEEKHOLE: + vp = ap->a_vp; + error = vn_lock(vp, LK_SHARED); + if (error != 0) + return (EBADF); + if (vp->v_type == VREG) + error = VOP_GETATTR(vp, &va, ap->a_cred); + else + error = ENOTTY; + if (error == 0) { + offp = ap->a_data; + if (*offp < 0 || *offp >= va.va_size) + error = ENXIO; + else if (ap->a_command == FIOSEEKHOLE) + *offp = va.va_size; + } + VOP_UNLOCK(vp, 0); + break; + default: + error = ENOTTY; + break; + } + return (error); +} + /* * vfs default ops * used to fill the vfs function table to get reasonable default return values.