Index: lib/libc/sys/aio_return.2 =================================================================== --- lib/libc/sys/aio_return.2 +++ lib/libc/sys/aio_return.2 @@ -34,7 +34,7 @@ .Lb libc .Sh SYNOPSIS .In aio.h -.Ft int +.Ft ssize_t .Fn aio_return "struct aiocb *iocb" .Sh DESCRIPTION The Index: lib/libc/sys/aio_waitcomplete.2 =================================================================== --- lib/libc/sys/aio_waitcomplete.2 +++ lib/libc/sys/aio_waitcomplete.2 @@ -34,7 +34,7 @@ .Lb libc .Sh SYNOPSIS .In aio.h -.Ft int +.Ft ssize_t .Fn aio_waitcomplete "struct aiocb **iocbp" "struct timespec *timeout" .Sh DESCRIPTION The Index: sys/kern/syscalls.master =================================================================== --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -554,7 +554,7 @@ 312 AUE_SETRESGID STD { int setresgid(gid_t rgid, gid_t egid, \ gid_t sgid); } 313 AUE_NULL OBSOL signanosleep -314 AUE_NULL STD { int aio_return(struct aiocb *aiocbp); } +314 AUE_NULL STD { ssize_t aio_return(struct aiocb *aiocbp); } 315 AUE_NULL STD { int aio_suspend( \ struct aiocb * const * aiocbp, int nent, \ const struct timespec *timeout); } @@ -643,7 +643,7 @@ 358 AUE_EXTATTR_DELETE_FILE STD { int extattr_delete_file(const char *path, \ int attrnamespace, \ const char *attrname); } -359 AUE_NULL STD { int aio_waitcomplete( \ +359 AUE_NULL STD { ssize_t aio_waitcomplete( \ struct aiocb **aiocbp, \ struct timespec *timeout); } 360 AUE_GETRESUID STD { int getresuid(uid_t *ruid, uid_t *euid, \ Index: sys/kern/systrace_args.c =================================================================== --- sys/kern/systrace_args.c +++ sys/kern/systrace_args.c @@ -9796,7 +9796,7 @@ /* aio_return */ case 314: if (ndx == 0 || ndx == 1) - p = "int"; + p = "ssize_t"; break; /* aio_suspend */ case 315: @@ -9972,7 +9972,7 @@ /* aio_waitcomplete */ case 359: if (ndx == 0 || ndx == 1) - p = "int"; + p = "ssize_t"; break; /* getresuid */ case 360: Index: sys/kern/vfs_aio.c =================================================================== --- sys/kern/vfs_aio.c +++ sys/kern/vfs_aio.c @@ -743,7 +743,7 @@ struct file *fp; struct uio auio; struct iovec aiov; - int cnt; + ssize_t cnt; int error; int oublock_st, oublock_end; int inblock_st, inblock_end; @@ -1446,8 +1446,7 @@ return (error); } - /* XXX: aio_nbytes is later casted to signed types. */ - if (job->uaiocb.aio_nbytes > INT_MAX) { + if (job->uaiocb.aio_nbytes > IOSIZE_MAX) { uma_zfree(aiocb_zone, job); return (EINVAL); } @@ -1788,7 +1787,7 @@ struct proc *p = td->td_proc; struct kaiocb *job; struct kaioinfo *ki; - int status, error; + long status, error; ki = p->p_aioinfo; if (ki == NULL) @@ -2344,7 +2343,8 @@ struct kaioinfo *ki; struct kaiocb *job; struct aiocb *ujob; - int error, status, timo; + long error, status; + int timo; ops->store_aiocb(ujobp, NULL); @@ -2641,6 +2641,7 @@ error = copyin(ujob, &job32, sizeof(job32)); if (error) return (error); + CP(job32, *kjob, aio_fildes); CP(job32, *kjob, aio_offset); PTRIN_CP(job32, *kjob, aio_buf); Index: sys/sys/aio.h =================================================================== --- sys/sys/aio.h +++ sys/sys/aio.h @@ -238,7 +238,7 @@ int aio_mlock(struct aiocb *); #ifdef __BSD_VISIBLE -int aio_waitcomplete(struct aiocb **, struct timespec *); +ssize_t aio_waitcomplete(struct aiocb **, struct timespec *); #endif int aio_fsync(int op, struct aiocb *aiocbp); Index: tests/sys/aio/aio_test.c =================================================================== --- tests/sys/aio/aio_test.c +++ tests/sys/aio/aio_test.c @@ -649,6 +649,81 @@ aio_md_cleanup(&arg); } +ATF_TC_WITHOUT_HEAD(aio_large_read_test); +ATF_TC_BODY(aio_large_read_test, tc) +{ + char pathname[PATH_MAX]; + struct aiocb cb, *cbp; + ssize_t nread; + size_t len; + int fd; +#ifdef __LP64__ + int clamped; +#endif + + ATF_REQUIRE_KERNEL_MODULE("aio"); + ATF_REQUIRE_UNSAFE_AIO(); + +#ifdef __LP64__ + len = sizeof(clamped); + if (sysctlbyname("debug.iosize_max_clamp", &clamped, &len, NULL, 0) == + -1) + atf_libc_error(errno, "Failed to read debug.iosize_max_clamp"); +#endif + + /* Determine the maximum supported read(2) size. */ + len = SSIZE_MAX; +#ifdef __LP64__ + if (clamped) + len = INT_MAX; +#endif + + strcpy(pathname, PATH_TEMPLATE); + fd = mkstemp(pathname); + ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno)); + + unlink(pathname); + + memset(&cb, 0, sizeof(cb)); + cb.aio_nbytes = len; + cb.aio_fildes = fd; + cb.aio_buf = NULL; + if (aio_read(&cb) == -1) + atf_tc_fail("aio_read() of maximum read size failed: %s", + strerror(errno)); + + nread = aio_waitcomplete(&cbp, NULL); + if (nread == -1) + atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno)); + if (nread != 0) + atf_tc_fail("aio_read() from /dev/null returned data: %zd", + nread); + + memset(&cb, 0, sizeof(cb)); + cb.aio_nbytes = len + 1; + cb.aio_fildes = fd; + cb.aio_buf = NULL; + if (aio_read(&cb) == -1) { + if (errno == EINVAL) + goto finished; + atf_tc_fail("aio_read() of too large read size failed: %s", + strerror(errno)); + } + + nread = aio_waitcomplete(&cbp, NULL); + if (nread == -1) { + if (errno == EINVAL) + goto finished; + atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno)); + } + atf_tc_fail( + "aio_read() of too large read size from /dev/null returned: %zd", + nread); + +finished: + close(fd); +} + ATF_TP_ADD_TCS(tp) { @@ -658,6 +733,7 @@ ATF_TP_ADD_TC(tp, aio_pty_test); ATF_TP_ADD_TC(tp, aio_pipe_test); ATF_TP_ADD_TC(tp, aio_md_test); + ATF_TP_ADD_TC(tp, aio_large_read_test); return (atf_no_error()); }