Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140079605
D33165.id99384.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D33165.id99384.diff
View Options
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 March 30, 2020
+.Dd December 2, 2021
.Dt SWAPON 2
.Os
.Sh NAME
@@ -37,6 +37,8 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
+.It vm/vm_param.h
+.It vm/swap_pager.h
.In unistd.h
.Ft int
.Fn swapon "const char *special"
@@ -63,6 +65,39 @@
system call disables paging and swapping on the given device.
All associated swap metadata are deallocated, and the device
is made available for other purposes.
+.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
+use of which allows to augment the syscall behavior.
+The
+.Va name_old_syscall
+member must be initialized to
+.Dv NULL
+for the system to recognize the extended syscall.
+It is recommended to zero the whole structure for future compatibility,
+due to padding.
+.Pp
+The
+.Va name
+string is the special device name, same as legacy syscall argument.
+.The
+.Va flags
+argument takes the following flags:
+.Bl -tag -width SWAPOFF_FORCE
+.It Dv SWAPOFF_FORCE
+Turns off very conservative heuristic which otherwise prevents swapoff
+if it is possible that total amount of free memory and remaining swap
+devices space is unsufficient for system operations.
+.El
.Sh RETURN VALUES
If an error has occurred, a value of -1 is returned and
.Va errno
diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8
--- a/sbin/swapon/swapon.8
+++ b/sbin/swapon/swapon.8
@@ -28,7 +28,7 @@
.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd May 19, 2020
+.Dd November 29, 2021
.Dt SWAPON 8
.Os
.Sh NAME
@@ -42,9 +42,9 @@
.Nm swapoff
.Oo Fl F Ar fstab
.Oc
-.Fl aLq | Ar
+.Fl afLq | Ar
.Nm swapctl
-.Op Fl AghklmsU
+.Op Fl AfghklmsU
.Oo
.Fl a Ar
|
@@ -125,9 +125,15 @@
written to standard output when a swap device is removed.
Note that
.Nm swapoff
-will fail and refuse to remove a swap device if there is insufficient
+will fail and refuse to remove a swap device if some very conservative
+estimation reports that there is insufficient
VM (memory + remaining swap devices) to run the system.
The
+.Fl f
+option turns off this heuristic, which could deadlock the system
+if there is insufficient swap space remaining.
+.Pp
+The
.Nm swapoff
utility
must move swapped pages out of the device being removed which could
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -51,6 +51,7 @@
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <vm/vm_param.h>
+#include <vm/swap_pager.h>
#include <err.h>
#include <errno.h>
@@ -78,7 +79,7 @@
static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
-static int Eflag, qflag;
+static int Eflag, fflag, qflag;
int
main(int argc, char **argv)
@@ -101,7 +102,7 @@
doall = 0;
etc_fstab = NULL;
- while ((ch = getopt(argc, argv, "AadEghklLmqsUF:")) != -1) {
+ while ((ch = getopt(argc, argv, "AadEfghklLmqsUF:")) != -1) {
switch(ch) {
case 'A':
if (which_prog == SWAPCTL) {
@@ -128,6 +129,12 @@
else
usage();
break;
+ case 'f':
+ if (which_prog == SWAPOFF)
+ fflag = 1;
+ else
+ usage();
+ break;
case 'g':
hflag = 'G';
break;
@@ -782,12 +789,18 @@
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 */
- error = swapoff(name);
+ else { /* SWAPOFF */
+ bzero(&sa, sizeof(sa));
+ sa.name = name;
+ if (fflag)
+ sa.flags |= SWAPOFF_FORCE;
+ error = swapoff((const char *)&sa);
+ }
if (error == -1) {
switch (errno) {
@@ -820,7 +833,7 @@
fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n");
break;
case SWAPOFF:
- fprintf(stderr, "[-F fstab] -aLq | file ...\n");
+ fprintf(stderr, "[-F fstab] -afLq | file ...\n");
break;
case SWAPCTL:
fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n");
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,6 +69,16 @@
#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
@@ -470,7 +470,7 @@
static int swapongeom(struct vnode *);
static int swaponvp(struct thread *, struct vnode *, u_long);
static int swapoff_one(struct swdevt *sp, struct ucred *cred,
- bool ignore_check);
+ u_int flags);
/*
* Swap bitmap functions
@@ -2340,10 +2340,6 @@
};
#endif
-/*
- * MPSAFE
- */
-/* ARGSUSED */
int
sys_swapon(struct thread *td, struct swapon_args *uap)
{
@@ -2489,25 +2485,44 @@
};
#endif
-/*
- * MPSAFE
- */
-/* ARGSUSED */
int
sys_swapoff(struct thread *td, struct swapoff_args *uap)
{
struct vnode *vp;
struct nameidata nd;
struct swdevt *sp;
- int error;
+ struct swapoff_new_args sa;
+ int error, probe_byte;
error = priv_check(td, PRIV_SWAPOFF);
if (error)
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;
+ }
+
sx_xlock(&swdev_syscall_lock);
- NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->name);
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, sa.name);
error = namei(&nd);
if (error)
goto done;
@@ -2524,14 +2539,14 @@
error = EINVAL;
goto done;
}
- error = swapoff_one(sp, td->td_ucred, false);
+ error = swapoff_one(sp, td->td_ucred, sa.flags);
done:
sx_xunlock(&swdev_syscall_lock);
return (error);
}
static int
-swapoff_one(struct swdevt *sp, struct ucred *cred, bool ignore_check)
+swapoff_one(struct swdevt *sp, struct ucred *cred, u_int flags)
{
u_long nblks;
#ifdef MAC
@@ -2561,7 +2576,7 @@
* means that we can lose swap data when filesystems go away,
* which is arguably worse.
*/
- if (!ignore_check &&
+ if ((flags & SWAPOFF_FORCE) == 0 &&
vm_free_count() + swap_pager_avail < nblks + nswap_lowat)
return (ENOMEM);
@@ -2612,7 +2627,7 @@
devname = devtoname(sp->sw_vp->v_rdev);
else
devname = "[file]";
- error = swapoff_one(sp, thread0.td_ucred, true);
+ error = swapoff_one(sp, thread0.td_ucred, SWAPOFF_FORCE);
if (error != 0) {
printf("Cannot remove swap device %s (error=%d), "
"skipping.\n", devname, error);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 20, 11:24 PM (6 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27102524
Default Alt Text
D33165.id99384.diff (7 KB)
Attached To
Mode
D33165: swapoff(8): add -f
Attached
Detach File
Event Timeline
Log In to Comment