Subject: Additional swap/dump magic
To: None <tech-userlevel@NetBSD.org>
From: Martin Husemann <martin@duskware.de>
List: tech-userlevel
Date: 08/24/2006 00:10:08
--bg08WKrSYDhXBjb5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Folks,
I would like your input on the attached changes. This is not fixing something
we did miss for years, but I think the addition of this "magic" is very
convenient for the user (albeit mostly invisible) and on the other hand
pretty cheap.
What I did is:
o A few swapctl(8) enhancements
- add an option (-q for query) to check if any swap or dump specs
are used in /etc/fstab
- add a new "auto" type to the -t argument that makes -A or -U not
parse /etc/fstab for explicitly configured swap/dump block
devices, but autodected all available (loacl) swap partitions
o A simple change to /etc/rc.d/swap1 using above enhancements so that
- if any explicit swap or dump is configured in /etc/fstab everything
behaves exactly as it does now (i.e. keep status quo)
- if no swap or dump is configured in /etc/fstab, use the new autodetect
magic to activate all swap partitions and set a dump device
If this change goes into tree, I'll change sysinst to not explicitly configure
a swap partition next (together with wedges support for archs that are there
already).
What do you think?
Martin
--bg08WKrSYDhXBjb5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=patch
Index: etc/rc.d/swap1
===================================================================
RCS file: /cvsroot/src/etc/rc.d/swap1,v
retrieving revision 1.9
diff -u -r1.9 swap1
--- etc/rc.d/swap1 13 Aug 2004 18:08:03 -0000 1.9
+++ etc/rc.d/swap1 23 Aug 2006 16:28:17 -0000
@@ -19,7 +19,7 @@
swap1_start()
{
if ! checkyesno no_swap; then
- swapctl -A -t blk
+ swapctl -A -t $t_arg
fi
}
@@ -29,9 +29,13 @@
{
if checkyesno swapoff || [ -n "$rc_force" ]; then
echo "Removing block-type swap devices"
- swapctl -U -t blk
+ swapctl -U -t $t_arg
fi
}
+# if any swap or dump configuration is found in /etc/fstab, just
+# use "blk" here - otherwise do full magic "auto"
+if swapctl -q >/dev/null; then t_arg="blk"; else t_arg="auto"; fi
+
load_rc_config swap
run_rc_command "$1"
Index: sbin/swapctl/Makefile
===================================================================
RCS file: /cvsroot/src/sbin/swapctl/Makefile,v
retrieving revision 1.4
diff -u -r1.4 Makefile
--- sbin/swapctl/Makefile 27 Jun 2005 01:00:07 -0000 1.4
+++ sbin/swapctl/Makefile 23 Aug 2006 16:28:17 -0000
@@ -3,6 +3,8 @@
PROG= swapctl
SRCS= swapctl.c swaplist.c
MAN= swapctl.8
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
LINKS= ${BINDIR}/swapctl ${BINDIR}/swapon
MLINKS= swapctl.8 swapon.8
Index: sbin/swapctl/swapctl.8
===================================================================
RCS file: /cvsroot/src/sbin/swapctl/swapctl.8,v
retrieving revision 1.33
diff -u -r1.33 swapctl.8
--- sbin/swapctl/swapctl.8 22 Aug 2006 21:38:39 -0000 1.33
+++ sbin/swapctl/swapctl.8 23 Aug 2006 16:28:17 -0000
@@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd August 22, 2006
+.Dd August 23, 2006
.Dt SWAPCTL 8
.Os
.Sh NAME
@@ -37,12 +37,12 @@
.Nm
.Fl A
.Op Fl p Ar priority
-.Op Fl t Ar blk|noblk
+.Op Fl t Ar blk|noblk|auto
.Nm
.Fl D Ar dumpdev|none
.Nm
.Fl U
-.Op Fl t Ar blk|noblk
+.Op Fl t Ar blk|noblk|auto
.Nm
.Fl a
.Op Fl p Ar priority
@@ -59,10 +59,12 @@
.Op Fl k | Fl m | Fl g
.Op Fl h
.Nm
+.Fl q
+.Nm
.Fl z
.Nm swapon
.Fl a
-.Op Fl t Ar blk|noblk
+.Op Fl t Ar blk|noblk|auto
.Nm swapon
.Ar path
.Sh DESCRIPTION
@@ -106,6 +108,11 @@
If no swap devices are configured,
.Nm
will exit with an error code.
+If usesd together with
+.Fl t Ar auto
+this option will not read
+.Pa /etc/fstab
+but query the kernel for all swap partitions on local hard disks.
.It Fl D
The
.Fl D
@@ -137,6 +144,11 @@
If no swap devices are unconfigured,
.Nm
will exit with an error code.
+If used together with
+.Fl t Ar auto
+this option will not read
+.Pa /etc/fstab
+but unconfigure all swap partitions.
.It Fl a
The
.Fl a
@@ -186,6 +198,14 @@
and
.Fl l
options.
+.It Fl q
+query
+.Pa /etc/fstab ,
+checking for any defined swap or dump devices.
+If any are found,
+.Nm
+returns with an exit status of 0, if none are found the exit status will
+be 1.
.It Fl k
The
.Fl k
@@ -223,6 +243,9 @@
causes all non-block devices in
.Pa /etc/fstab
to be added.
+An argument of
+.Ar auto
+causes all swap partitions on local hard disks to be used.
This option is useful in early system startup, where swapping
may be needed before all file systems are available, such as during
disk checks of large file systems.
Index: sbin/swapctl/swapctl.c
===================================================================
RCS file: /cvsroot/src/sbin/swapctl/swapctl.c,v
retrieving revision 1.30
diff -u -r1.30 swapctl.c
--- sbin/swapctl/swapctl.c 22 Aug 2006 14:08:36 -0000 1.30
+++ sbin/swapctl/swapctl.c 23 Aug 2006 16:28:17 -0000
@@ -35,8 +35,11 @@
* -D [<dev>|none] set dumpdev to <dev> or disable dumps
* -z show dumpdev
* -U remove all devices listed as `sw' in /etc/fstab.
- * -t [blk|noblk] if -A or -U , add (remove) either all block device
- * or all non-block devices
+ * -t [blk|noblk|auto]
+ * if -A or -U , add (remove) either all block device
+ * or all non-block devices, or all swap partitions
+ * -q check if any swap or dump devices are defined in
+ * /etc/fstab
* -a <dev> add this device
* -d <dev> remove this swap device
* -g use gigabytes
@@ -65,6 +68,9 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/swap.h>
+#include <sys/sysctl.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
#include <unistd.h>
#include <err.h>
@@ -73,6 +79,9 @@
#include <stdlib.h>
#include <string.h>
#include <fstab.h>
+#include <fcntl.h>
+#include <util.h>
+#include <paths.h>
#include "swapctl.h"
@@ -90,6 +99,7 @@
#define CMD_l 0x40 /* list swap files/devices */
#define CMD_s 0x80 /* summary of swap files/devices */
#define CMD_z 0x100 /* show dump device */
+#define CMD_q 0x200 /* check for dump/swap in /etc/fstab */
#define SET_COMMAND(cmd) \
do { \
@@ -103,7 +113,7 @@
* line, and the ones which require that none exist.
*/
#define REQUIRE_PATH (CMD_D | CMD_a | CMD_c | CMD_d)
-#define REQUIRE_NOPATH (CMD_A | CMD_U | CMD_l | CMD_s | CMD_z)
+#define REQUIRE_NOPATH (CMD_A | CMD_U | CMD_l | CMD_s | CMD_z | CMD_q)
/*
* Option flags, and the commands with which they are valid.
@@ -119,7 +129,9 @@
int pflag; /* priority was specified */
#define PFLAG_CMDS (CMD_A | CMD_a | CMD_c)
-char *tflag; /* swap device type (blk or noblk) */
+char *tflag; /* swap device type (blk, noblk, auto) */
+int autoflag; /* 1, if tflag is "auto" */
+int auto_add_dump; /* 1, if the next found swap will become dump */
#define TFLAG_CMDS (CMD_A | CMD_U)
int pri; /* uses 0 as default pri */
@@ -130,6 +142,11 @@
static void set_dumpdev(char *);
static int get_dumpdev(void);
static void do_fstab(int);
+static int check_fstab(void);
+static void do_localdevs(int);
+static void do_localdisk(const char *, int);
+static int do_wedgesofdisk(int fd, int);
+static int do_partitionsofdisk(const char *, int fd, int);
static void usage(void);
static void swapon_command(int, char **);
#if 0
@@ -153,7 +170,7 @@
}
#endif
- while ((c = getopt(argc, argv, "ADUacdghklmp:st:z")) != -1) {
+ while ((c = getopt(argc, argv, "ADUacdghklmp:qst:z")) != -1) {
switch (c) {
case 'A':
SET_COMMAND(CMD_A);
@@ -205,6 +222,10 @@
pri = atoi(optarg);
break;
+ case 'q':
+ SET_COMMAND(CMD_q);
+ break;
+
case 's':
SET_COMMAND(CMD_s);
break;
@@ -213,6 +234,8 @@
if (tflag != NULL)
usage();
tflag = optarg;
+ if (strcmp(tflag, "auto") == 0)
+ autoflag = 1;
break;
case 'z':
@@ -256,7 +279,8 @@
if (command != CMD_A && command != CMD_U)
usage();
if (strcmp(tflag, "blk") != 0 &&
- strcmp(tflag, "noblk") != 0)
+ strcmp(tflag, "noblk") != 0 &&
+ strcmp(tflag, "auto") != 0)
usage();
}
@@ -286,7 +310,10 @@
break;
case CMD_A:
- do_fstab(1);
+ if (autoflag)
+ do_localdevs(1);
+ else
+ do_fstab(1);
break;
case CMD_D:
@@ -299,8 +326,21 @@
break;
case CMD_U:
- do_fstab(0);
+ if (autoflag)
+ do_localdevs(0);
+ else
+ do_fstab(0);
break;
+ case CMD_q:
+ if (check_fstab()) {
+ printf("%s: there are swap or dump devices defined in "
+ _PATH_FSTAB "\n", getprogname());
+ exit(0);
+ } else {
+ printf("%s: no swap or dump devices in "
+ _PATH_FSTAB "\n", getprogname());
+ exit(1);
+ }
}
exit(0);
@@ -390,6 +430,9 @@
if (swapctl(SWAP_ON, path, priority) < 0) {
oops:
err(1, "%s", path);
+ } else if (auto_add_dump) {
+ set_dumpdev(path);
+ auto_add_dump = 0;
}
return (1);
}
@@ -446,6 +489,154 @@
}
static void
+do_localdevs(int add)
+{
+ size_t ressize;
+ char *disknames, *disk;
+ dev_t dev;
+ static const char mibname[] = "hw.disknames";
+
+ /*
+ * Check if we want to add a dump device too
+ */
+ if (swapctl(SWAP_GETDUMPDEV, &dev, 0) == 0 && dev == NODEV)
+ auto_add_dump = 1; /* no dump device available */
+
+ ressize = 0;
+ if (sysctlbyname(mibname, NULL, &ressize, NULL, 0))
+ return;
+ ressize += 200; /* add some arbitrary slope */
+ disknames = malloc(ressize);
+ if (sysctlbyname(mibname, disknames, &ressize, NULL, 0) == 0) {
+ for (disk = strtok(disknames, " "); disk;
+ disk = strtok(NULL, " "))
+ do_localdisk(disk, add);
+ }
+ free(disknames);
+}
+
+static void
+do_localdisk(const char *disk, int add)
+{
+ int fd;
+ char dvname[MAXPATHLEN];
+
+ if ((fd = opendisk(disk, O_RDONLY, dvname, sizeof(dvname), 0)) == -1)
+ return;
+
+ if (!do_wedgesofdisk(fd, add))
+ do_partitionsofdisk(disk, fd, add);
+
+ close(fd);
+}
+
+static int
+do_wedgesofdisk(int fd, int add)
+{
+ char devicename[MAXPATHLEN];
+ struct dkwedge_info *dkw;
+ struct dkwedge_list dkwl;
+ size_t bufsize;
+ u_int i;
+
+ dkw = NULL;
+ dkwl.dkwl_buf = dkw;
+ dkwl.dkwl_bufsize = 0;
+
+ for (;;) {
+ if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1)
+ return 0;
+ if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied)
+ break;
+ bufsize = dkwl.dkwl_nwedges * sizeof(*dkw);
+ if (dkwl.dkwl_bufsize < bufsize) {
+ dkw = realloc(dkwl.dkwl_buf, bufsize);
+ if (dkw == NULL)
+ return 0;
+ dkwl.dkwl_buf = dkw;
+ dkwl.dkwl_bufsize = bufsize;
+ }
+ }
+
+ for (i = 0; i < dkwl.dkwl_ncopied; i++) {
+ if (strcmp(dkw[i].dkw_ptype, DKW_PTYPE_SWAP) != 0)
+ continue;
+ snprintf(devicename, sizeof(devicename), "%s%s", _PATH_DEV,
+ dkw[i].dkw_devname);
+ devicename[sizeof(devicename)-1] = '\0';
+
+ if (add) {
+ if (add_swap(devicename, 0)) {
+ printf(
+ "%s: adding %s as swap device at priority 0\n",
+ getprogname(), devicename);
+ }
+ } else {
+ if (delete_swap(devicename)) {
+ printf(
+ "%s: removing %s as swap device\n",
+ getprogname(), devicename);
+ }
+ }
+
+ }
+
+ free(dkw);
+ return dkwl.dkwl_nwedges != 0;
+}
+
+static int
+do_partitionsofdisk(const char *prefix, int fd, int add)
+{
+ char devicename[MAXPATHLEN];
+ struct disklabel lab;
+ uint i;
+
+ if (ioctl(fd, DIOCGDINFO, &lab) != 0)
+ return 0;
+
+ for (i = 0; i < lab.d_npartitions; i++) {
+ if (lab.d_partitions[i].p_fstype != FS_SWAP)
+ continue;
+ snprintf(devicename, sizeof(devicename), "%s%s%c", _PATH_DEV,
+ prefix, 'a'+i);
+ devicename[sizeof(devicename)-1] = '\0';
+
+ if (add) {
+ if (add_swap(devicename, 0)) {
+ printf(
+ "%s: adding %s as swap device at priority 0\n",
+ getprogname(), devicename);
+ }
+ } else {
+ if (delete_swap(devicename)) {
+ printf(
+ "%s: removing %s as swap device\n",
+ getprogname(), devicename);
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+check_fstab(void)
+{
+ struct fstab *fp;
+
+ while ((fp = getfsent()) != NULL) {
+ if (strcmp(fp->fs_type, "dp") == 0)
+ return 1;
+
+ if (strcmp(fp->fs_type, "sw") == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
do_fstab(int add)
{
struct fstab *fp;
@@ -585,11 +776,12 @@
{
const char *progname = getprogname();
- fprintf(stderr, "usage: %s -A [-p priority] [-t blk|noblk]\n",
+ fprintf(stderr, "usage: %s -A [-p priority] [-t blk|noblk|auto]\n",
progname);
fprintf(stderr, " %s -D dumppath\n", progname);
- fprintf(stderr, " %s -U [-t blk|noblk]\n", progname);
+ fprintf(stderr, " %s -U [-t blk|noblk|auto]\n", progname);
fprintf(stderr, " %s -a [-p priority] path\n", progname);
+ fprintf(stderr, " %s -q\n", progname);
fprintf(stderr, " %s -c -p priority path\n", progname);
fprintf(stderr, " %s -d path\n", progname);
fprintf(stderr, " %s -l | -s [-k|-m|-g|-h]\n", progname);
--bg08WKrSYDhXBjb5--