+ case F_SPECULATIVE_READ: {
+ fspecread_t args;
+
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EBADF;
+ goto out;
+ }
+
+ vp = (struct vnode *)fp->f_data;
+ proc_fdunlock(p);
+
+ if ((error = copyin(argp, (caddr_t)&args, sizeof(args)))) {
+ goto outdrop;
+ }
+
+ /* Discard invalid offsets or lengths */
+ if ((args.fsr_offset < 0) || (args.fsr_length < 0)) {
+ error = EINVAL;
+ goto outdrop;
+ }
+
+ /*
+ * Round the file offset down to a page-size boundary (or to 0).
+ * The filesystem will need to round the length up to the end of the page boundary
+ * or to the EOF of the file.
+ */
+ uint64_t foff = (((uint64_t)args.fsr_offset) & ~((uint64_t)PAGE_MASK));
+ uint64_t foff_delta = args.fsr_offset - foff;
+ args.fsr_offset = (off_t) foff;
+
+ /*
+ * Now add in the delta to the supplied length. Since we may have adjusted the
+ * offset, increase it by the amount that we adjusted.
+ */
+ args.fsr_length += foff_delta;
+
+ if ((error = vnode_getwithref(vp))) {
+ goto outdrop;
+ }
+ error = VNOP_IOCTL(vp, F_SPECULATIVE_READ, (caddr_t)&args, 0, &context);
+ (void)vnode_put(vp);
+
+ goto outdrop;
+ }