Index: share/man/man9/VOP_DEALLOCATE.9 =================================================================== --- share/man/man9/VOP_DEALLOCATE.9 +++ share/man/man9/VOP_DEALLOCATE.9 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 11, 2021 +.Dd August 11, 2021 .Dt VOP_DEALLOCATE 9 .Os .Sh NAME @@ -42,6 +42,7 @@ .Fa "off_t *offset" .Fa "off_t *len" .Fa "int flags" +.Fa "int ioflag" .Fa "struct ucred *cred" .Fc .Sh DESCRIPTION @@ -61,6 +62,8 @@ .It Fa flags The flags of this call. This should be set to 0 for now. +.It Fa ioflag +Directives and hints to be given to the file system. .It Fa cred The credentials of the caller. .El Index: share/man/man9/vn_deallocate.9 =================================================================== --- share/man/man9/vn_deallocate.9 +++ share/man/man9/vn_deallocate.9 @@ -67,7 +67,7 @@ The control flags of the operation. This should be set to 0 for now. .It Fa ioflag -The control flags of vnode locking. +Various flag. .It Fa active_cred The user credentials of the calling thread. .It Fa file_cred @@ -76,7 +76,8 @@ .Pp The .Fn ioflag -argument may be one or more of the following flags: +argument give directives and hints to the file system. +It may include one or more of the following flags: .Bl -tag -width IO_RANGELOCKED .It Dv IO_NODELOCKED The vnode was locked before the call. @@ -84,6 +85,10 @@ Rangelock was owned around the call. .It Dv IO_NOMACCHECK Skip MAC checking in the call. +.It Dv IO_SYNC +Do I/O synchronously. +.It Dv IO_DIRECT +Attempt to bypass buffer cache. .El .Pp .Fa *offset Index: sys/kern/vfs_default.c =================================================================== --- sys/kern/vfs_default.c +++ sys/kern/vfs_default.c @@ -1074,7 +1074,7 @@ static int vp_zerofill(struct vnode *vp, struct vattr *vap, off_t *offsetp, off_t *lenp, - struct ucred *cred) + int ioflag, struct ucred *cred) { int iosize; int error = 0; @@ -1110,7 +1110,7 @@ auio.uio_rw = UIO_WRITE; auio.uio_td = td; - error = VOP_WRITE(vp, &auio, 0, cred); + error = VOP_WRITE(vp, &auio, ioflag, cred); if (error != 0) { len -= xfersize - auio.uio_resid; offset += xfersize - auio.uio_resid; @@ -1175,7 +1175,7 @@ /* Fill zeroes */ xfersize = rem = omin(noff - offset, len); - error = vp_zerofill(vp, &va, &offset, &rem, cred); + error = vp_zerofill(vp, &va, &offset, &rem, ap->a_ioflag, cred); if (error) { len -= xfersize - rem; goto out; Index: sys/kern/vfs_vnops.c =================================================================== --- sys/kern/vfs_vnops.c +++ sys/kern/vfs_vnops.c @@ -916,6 +916,35 @@ return (ret); } +static int +get_write_ioflag(struct file *fp) +{ + int ioflag; + struct mount *mp; + struct vnode *vp; + + ioflag = 0; + vp = fp->f_vnode; + mp = atomic_load_ptr(&vp->v_mount); + + if (fp->f_flag & O_DIRECT) + ioflag |= IO_DIRECT; + + if ((fp->f_flag & O_FSYNC) || + (mp != NULL && (mp->mnt_flag & MNT_SYNCHRONOUS))) + ioflag |= IO_SYNC; + + /* + * For O_DSYNC we set both IO_SYNC and IO_DATASYNC, so that VOP_WRITE() + * or VOP_DEALLOCATE() implementations that don't understand IO_DATASYNC + * fall back to full O_SYNC behavior. + */ + if (fp->f_flag & O_DSYNC) + ioflag |= IO_SYNC | IO_DATASYNC; + + return (ioflag); +} + int vn_read_from_obj(struct vnode *vp, struct uio *uio) { @@ -1119,21 +1148,8 @@ ioflag |= IO_APPEND; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; - if (fp->f_flag & O_DIRECT) - ioflag |= IO_DIRECT; - - mp = atomic_load_ptr(&vp->v_mount); - if ((fp->f_flag & O_FSYNC) || - (mp != NULL && (mp->mnt_flag & MNT_SYNCHRONOUS))) - ioflag |= IO_SYNC; + ioflag |= get_write_ioflag(fp); - /* - * For O_DSYNC we set both IO_SYNC and IO_DATASYNC, so that VOP_WRITE() - * implementations that don't understand IO_DATASYNC fall back to full - * O_SYNC behavior. - */ - if (fp->f_flag & O_DSYNC) - ioflag |= IO_SYNC | IO_DATASYNC; mp = NULL; need_finished_write = false; if (vp->v_type != VCHR) { @@ -3489,7 +3505,7 @@ vp); #endif if (error == 0) - error = VOP_DEALLOCATE(vp, &off, &len, flags, + error = VOP_DEALLOCATE(vp, &off, &len, flags, ioflag, active_cred); if ((ioflag & IO_NODELOCKED) == 0) { @@ -3528,6 +3544,7 @@ { int error; struct vnode *vp; + int ioflag; vp = fp->f_vnode; @@ -3537,9 +3554,11 @@ if (vp->v_type != VREG) return (ENODEV); + ioflag = get_write_ioflag(fp); + switch (cmd) { case SPACECTL_DEALLOC: - error = vn_deallocate_impl(vp, offset, length, flags, 0, + error = vn_deallocate_impl(vp, offset, length, flags, ioflag, active_cred, fp->f_cred); break; default: Index: sys/kern/vnode_if.src =================================================================== --- sys/kern/vnode_if.src +++ sys/kern/vnode_if.src @@ -808,6 +808,7 @@ INOUT off_t *offset; INOUT off_t *len; IN int flags; + IN int ioflag; IN struct ucred *cred; };