diff --git a/include/unistd.h b/include/unistd.h --- a/include/unistd.h +++ b/include/unistd.h @@ -579,7 +579,7 @@ void setusershell(void); int strtofflags(char **, u_long *, u_long *); int swapon(const char *); -int swapoff(const char *); +int swapoff(const char *, u_int); int syscall(int, ...); off_t __syscall(quad_t, ...); int undelete(const char *); diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h --- a/lib/libc/include/compat.h +++ b/lib/libc/include/compat.h @@ -69,6 +69,8 @@ __sym_compat(kevent, freebsd11_kevent, FBSD_1.0); +__sym_compat(swapoff, freebsd13_swapoff, FBSD_1.0); + #undef __sym_compat #define __weak_reference(sym,alias) \ diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -260,7 +260,6 @@ sigwaitinfo; socket; socketpair; - swapoff; swapon; symlink; sync; @@ -420,6 +419,7 @@ FBSD_1.7 { _Fork; fspacectl; + swapoff; }; FBSDprivate_1.0 { diff --git a/lib/libc/sys/swapon.2 b/lib/libc/sys/swapon.2 --- a/lib/libc/sys/swapon.2 +++ b/lib/libc/sys/swapon.2 @@ -28,7 +28,7 @@ .\" @(#)swapon.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd December 2, 2021 +.Dd December 8, 2021 .Dt SWAPON 2 .Os .Sh NAME @@ -43,7 +43,7 @@ .Ft int .Fn swapon "const char *special" .Ft int -.Fn swapoff "const char *special" +.Fn swapoff "const char *special" "u_int flags" .Sh DESCRIPTION The .Fn swapon @@ -68,27 +68,7 @@ .Pp The .Fa special -argument points to either the string that names the special device -used for swapping or the following structure -.Bd -literal -struct swapoff_new_args { - const char *name_old_syscall; - const char *name; - u_int flags; -}; -.Ed -that extends swapoff's interface to include optional flags. -The -.Va name_old_syscall -member must be initialized to -.Dv NULL -for the system to recognize the extended interface. -It is recommended that the whole structure be zeroed for future -compatibility, due to padding. -.Pp -The -.Va name -string is the special device name, same as legacy syscall argument. +argument points to the name of the device or file used for swapping. .The .Va flags argument takes the following flags: diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -789,18 +789,12 @@ static const char * swap_on_off_sfile(const char *name, int doingall) { - struct swapoff_new_args sa; int error; if (which_prog == SWAPON) error = Eflag ? swapon_trim(name) : swapon(name); - else { /* SWAPOFF */ - bzero(&sa, sizeof(sa)); - sa.name = name; - if (fflag) - sa.flags |= SWAPOFF_FORCE; - error = swapoff((const char *)&sa); - } + else /* SWAPOFF */ + error = swapoff(name, fflag ? SWAPOFF_FORCE : 0); if (error == -1) { switch (errno) { diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -34,6 +34,7 @@ ; COMPAT10 included on COMPAT_FREEBSD10 #ifdef (FreeBSD 10 compat) ; COMPAT11 included on COMPAT_FREEBSD11 #ifdef (FreeBSD 11 compat) ; COMPAT12 included on COMPAT_FREEBSD12 #ifdef (FreeBSD 12 compat) +; COMPAT13 included on COMPAT_FREEBSD13 #ifdef (FreeBSD 13 compat) ; OBSOL obsolete, not included in system, only specifies name ; RESERVED reserved for local or vendor use (not for FreeBSD) ; UNIMPL not implemented, placeholder only @@ -2246,7 +2247,7 @@ _In_ _Contains_long_ptr_ const struct __ucontext *ucp ); } -424 AUE_SWAPOFF STD { +424 AUE_SWAPOFF COMPAT13 { int swapoff( _In_z_ const char *name ); @@ -3299,6 +3300,13 @@ int sched_getcpu(void); } +582 AUE_SWAPOFF STD { + int swapoff( + _In_z_ const char *name, + u_int flags, + ); + } + ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master ; vim: syntax=off diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h --- a/sys/sys/unistd.h +++ b/sys/sys/unistd.h @@ -198,6 +198,8 @@ RFPROCDESC | RFSPAWN | RFPPWAIT) #define RFKERNELONLY (RFSTOPPED | RFHIGHPID | RFPROCDESC) +#define SWAPOFF_FORCE 0x00000001 + #endif /* __BSD_VISIBLE */ #endif /* !_SYS_UNISTD_H_ */ diff --git a/sys/tools/makesyscalls.lua b/sys/tools/makesyscalls.lua --- a/sys/tools/makesyscalls.lua +++ b/sys/tools/makesyscalls.lua @@ -226,6 +226,7 @@ { stdcompat = "FREEBSD10" }, { stdcompat = "FREEBSD11" }, { stdcompat = "FREEBSD12" }, + { stdcompat = "FREEBSD13" }, } local function trim(s, char) diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h --- a/sys/vm/swap_pager.h +++ b/sys/vm/swap_pager.h @@ -69,16 +69,6 @@ #define SW_UNMAPPED 0x01 #define SW_CLOSING 0x04 -struct swapoff_new_args { - const char *name_old_syscall; - const char *name; - u_int flags; - u_int pad0; - uintptr_t pad1[8]; -}; - -#define SWAPOFF_FORCE 0x00000001 - #ifdef _KERNEL extern int swap_pager_avail; diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -100,6 +100,7 @@ #include #include #include +#include #include #include #include @@ -2479,50 +2480,24 @@ * rather than filename as specification. We keep sw_vp around * only to make this work. */ -#ifndef _SYS_SYSPROTO_H_ -struct swapoff_args { - char *name; -}; -#endif - -int -sys_swapoff(struct thread *td, struct swapoff_args *uap) +static int +kern_swapoff(struct thread *td, const char *name, enum uio_seg name_seg, + u_int flags) { struct vnode *vp; struct nameidata nd; struct swdevt *sp; - struct swapoff_new_args sa; - int error, probe_byte; + int error; error = priv_check(td, PRIV_SWAPOFF); - if (error) + if (error != 0) return (error); - - /* - * Detect old vs. new-style swapoff(2) syscall. The first - * pointer in the memory pointed to by uap->name is NULL for - * the new variant. - */ - probe_byte = fubyte(uap->name); - switch (probe_byte) { - case -1: - return (EFAULT); - case 0: - error = copyin(uap->name, &sa, sizeof(sa)); - if (error != 0) - return (error); - if ((sa.flags & ~(SWAPOFF_FORCE)) != 0) - return (EINVAL); - break; - default: - bzero(&sa, sizeof(sa)); - sa.name = uap->name; - break; - } + if ((flags & ~(SWAPOFF_FORCE)) != 0) + return (EINVAL); sx_xlock(&swdev_syscall_lock); - NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, sa.name); + NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, name_seg, name); error = namei(&nd); if (error) goto done; @@ -2539,12 +2514,27 @@ error = EINVAL; goto done; } - error = swapoff_one(sp, td->td_ucred, sa.flags); + error = swapoff_one(sp, td->td_ucred, flags); done: sx_xunlock(&swdev_syscall_lock); return (error); } + +#ifdef COMPAT_FREEBSD13 +int +freebsd13_swapoff(struct thread *td, struct freebsd13_swapoff_args *uap) +{ + return (kern_swapoff(td, uap->name, UIO_USERSPACE, 0)); +} +#endif + +int +sys_swapoff(struct thread *td, struct swapoff_args *uap) +{ + return (kern_swapoff(td, uap->name, UIO_USERSPACE, uap->flags)); +} + static int swapoff_one(struct swdevt *sp, struct ucred *cred, u_int flags) { diff --git a/tests/sys/audit/administrative.c b/tests/sys/audit/administrative.c --- a/tests/sys/audit/administrative.c +++ b/tests/sys/audit/administrative.c @@ -1605,7 +1605,7 @@ FILE *pipefd = setup(fds, auclass); /* Failure reason: Block device required */ - ATF_REQUIRE_EQ(-1, swapoff(path)); + ATF_REQUIRE_EQ(-1, swapoff(path, 0)); check_audit(fds, adregex, pipefd); }