Index: kern/vfs_default.c =================================================================== --- kern/vfs_default.c +++ kern/vfs_default.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,7 @@ 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 @@ .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, @@ -1131,6 +1133,41 @@ error = 0; } VI_UNLOCK(vp); + 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); }