Index: lib/libc/sys/fspacectl.2 =================================================================== --- lib/libc/sys/fspacectl.2 +++ lib/libc/sys/fspacectl.2 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 4, 2021 +.Dd August 18, 2021 .Dt FSPACECTL 2 .Os .Sh NAME @@ -67,6 +67,17 @@ .Fa spacectl_range structure it points to is updated to contain the unprocessed operation range after the system call returns. +.Pp +For a successful completion without an unprocessed part in the requested +operation range, +.Fa "rmsr->r_len" +is updated to be the value 0, and +.Fa "rmsr->r_offset" +is updated to be the smallest of +.Fa "rqsr->r_offset" + +.Fa "rqsr->r_len" ; +and the end-of-file offset. +The file descriptor's file offset is not used or modified by the system call. Both .Fa rqsr and @@ -92,9 +103,9 @@ .Fa rqsr argument. The -.Va "rqsr->r_offset" +.Fa "rqsr->r_offset" has to be a value greater than or equal to 0, and the -.Va "rqsr->r_len" +.Fa "rqsr->r_len" has to be a value greater than 0. .Pp If the file system supports hole-punching, @@ -132,11 +143,17 @@ argument is .Dv SPACECTL_DEALLOC , either the -.Fa "range->r_offset" +.Fa "rqsr->r_offset" argument was less than zero, or the -.Fa "range->r_len" +.Fa "rqsr->r_len" argument was less than or equal to zero. .It Bq Er EINVAL +The value of +.Fa "rqsr->r_offset" + +.Fa "rqsr->r_len" +is greater than +.Dv OFF_MAX . +.It Bq Er EINVAL An invalid or unsupported flag is included in .Fa flags . .It Bq Er EINVAL Index: share/man/man9/VOP_DEALLOCATE.9 =================================================================== --- share/man/man9/VOP_DEALLOCATE.9 +++ share/man/man9/VOP_DEALLOCATE.9 @@ -74,6 +74,14 @@ are updated to reflect the portion of the range that still needs to be zeroed/deallocated on return. Partial result is considered a successful operation. +For a successful completion without an unprocessed portion of the range, +.Fa *len +is updated to be the value 0, and +.Fa *offset +is updated to be the smallest of +.Fa *offset + +.Fa *len +passed to the call and the end-of-file offset. .Sh LOCKS The vnode should be locked on entry and will still be locked on exit. .Sh RETURN VALUES Index: share/man/man9/vn_deallocate.9 =================================================================== --- share/man/man9/vn_deallocate.9 +++ share/man/man9/vn_deallocate.9 @@ -95,6 +95,14 @@ and .Fa *length are updated to reflect the unprocessed operation range of the call. +For a successful completion, +.Fa *length +is updated to be the value 0, and +.Fa *offset +is updated to be the smallest of +.Fa *offset + +.Fa *length +passed to the call and the end-of-file offset. .Sh RETURN VALUES Upon successful completion, the value 0 is returned; otherwise the appropriate error is returned. Index: sys/kern/uipc_shm.c =================================================================== --- sys/kern/uipc_shm.c +++ sys/kern/uipc_shm.c @@ -1898,13 +1898,16 @@ { vm_object_t object; vm_pindex_t pistart, pi, piend; - vm_ooffset_t off, len; + vm_ooffset_t off; + off_t len; int startofs, endofs, end; int error; off = *offset; len = *length; KASSERT(off + len <= (vm_ooffset_t)OFF_MAX, ("off + len overflows")); + if (off + len > shmfd->shm_size) + len = shmfd->shm_size - off; object = shmfd->shm_object; startofs = off & PAGE_MASK; endofs = (off + len) & PAGE_MASK; @@ -1939,6 +1942,12 @@ len -= endofs; } + /* Handle the case when offset is beyond shm size */ + if (len < 0) { + off -= len; + len = 0; + } + out: VM_OBJECT_WUNLOCK(shmfd->shm_object); *offset = off; @@ -1974,8 +1983,6 @@ break; } error = shm_deallocate(shmfd, &off, &len, flags); - if (error != 0) - break; *offset = off; *length = len; break; Index: sys/kern/vfs_default.c =================================================================== --- sys/kern/vfs_default.c +++ sys/kern/vfs_default.c @@ -1138,14 +1138,13 @@ vp = ap->a_vp; offset = *ap->a_offset; - len = *ap->a_len; cred = ap->a_cred; error = VOP_GETATTR(vp, &va, cred); if (error) return (error); - len = omin(OFF_MAX - offset, *ap->a_len); + len = omin(va.va_size - offset, *ap->a_len); while (len > 0) { noff = offset; error = vn_bmap_seekhole_locked(vp, FIOSEEKDATA, &noff, cred); @@ -1185,6 +1184,11 @@ if (should_yield()) break; } + /* Handle the case when offset is beyond EOF */ + if (len < 0) { + offset += len; + len = 0; + } out: *ap->a_offset = offset; *ap->a_len = len;