Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 30 Jul 2011 01:06:48 +0200
From:      Robert Millan <rmh@debian.org>
To:        Kostik Belousov <kostikbel@gmail.com>
Cc:        freebsd-hackers@freebsd.org, freebsd-emulation@freebsd.org
Subject:   Re: kern/159281: [PATCH] Linux-like /proc/swaps for linprocfs
Message-ID:  <CAOfDtXOJjOoQA8yNFPVdQRqCqr-Vc5nscMbgOLGLMuvTP9mp1w@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi Kostik,

2011/7/29 Kostik Belousov <kostikbel@gmail.com>:
> The patch is too hackish, IMHO.
> I would prefer to have an exported kernel function that fills xswdev
> by index, used both by vm_swap_info and linprocfs.
>
> For the device name, you would use sw_vp->v_rdev->si_name, see, for
> instance, the following fragment in the swapoff_all():
>                if (vn_isdisk(sp->sw_vp, NULL))
>                        devname = sp->sw_vp->v_rdev->si_name;
>                else
>                        devname = "[file]";
> This could be another function that returns swap information by index.

Here's a patch with the changes you requested.

-- 
Robert Millan

[-- Attachment #2 --]
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -502,6 +502,32 @@
 	return (0);
 }
 
+static int
+linprocfs_doswaps(PFS_FILL_ARGS)
+{
+	struct xswdev xsw;
+	int n;
+	long long total, used;
+	char devname[SPECNAMELEN + 1];
+
+	sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+
+	for (n = 0; ; n++) {
+		if (swap_info(n, &xsw) != 0)
+			break;
+
+		if (swap_devname(n, devname, sizeof(devname)) != 0)
+			break;
+
+		total = (long long)xsw.xsw_nblks * PAGE_SIZE / 1024;
+		used  = (long long)xsw.xsw_used * PAGE_SIZE / 1024;
+
+		sbuf_printf(sb, "/dev/%-34s unknown\t\t%lld\t%lld\t-1\n", devname, total, used);
+	}
+
+	return (0);
+}
+
 /*
  * Filler function for proc/uptime
  */
@@ -1490,6 +1516,8 @@
 	    NULL, NULL, NULL, 0);
 	pfs_create_file(root, "stat", &linprocfs_dostat,
 	    NULL, NULL, NULL, PFS_RD);
+	pfs_create_file(root, "swaps", &linprocfs_doswaps,
+	    NULL, NULL, NULL, PFS_RD);
 	pfs_create_file(root, "uptime", &linprocfs_douptime,
 	    NULL, NULL, NULL, PFS_RD);
 	pfs_create_file(root, "version", &linprocfs_doversion,
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -2315,6 +2315,31 @@
 	return (0);
 }
 
+int
+swap_devname(int name, char *devname, size_t len)
+{
+	int	n;
+	struct swdevt *sp;
+	char	*tmp_devname;
+
+	n = 0;
+	mtx_lock(&sw_dev_mtx);
+	TAILQ_FOREACH(sp, &swtailq, sw_list) {
+		if (n == name) {
+			if (vn_isdisk(sp->sw_vp, NULL))
+				tmp_devname = sp->sw_vp->v_rdev->si_name;
+			else
+				tmp_devname = "[file]";
+			strncpy(devname, tmp_devname, len);
+			mtx_unlock(&sw_dev_mtx);
+			return (0);
+		}
+		n++;
+	}
+	mtx_unlock(&sw_dev_mtx);
+	return (ENOENT);
+}
+
 void
 swapoff_all(void)
 {
@@ -2365,30 +2390,24 @@
 	mtx_unlock(&sw_dev_mtx);
 }
 
-static int
-sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS)
+int
+swap_info(int name, struct xswdev *xs)
 {
-	int	*name = (int *)arg1;
 	int	error, n;
-	struct xswdev xs;
 	struct swdevt *sp;
 
-	if (arg2 != 1) /* name length */
-		return (EINVAL);
-
 	n = 0;
 	mtx_lock(&sw_dev_mtx);
 	TAILQ_FOREACH(sp, &swtailq, sw_list) {
-		if (n == *name) {
+		if (n == name) {
 			mtx_unlock(&sw_dev_mtx);
-			xs.xsw_version = XSWDEV_VERSION;
-			xs.xsw_dev = sp->sw_dev;
-			xs.xsw_flags = sp->sw_flags;
-			xs.xsw_nblks = sp->sw_nblks;
-			xs.xsw_used = sp->sw_used;
+			xs->xsw_version = XSWDEV_VERSION;
+			xs->xsw_dev = sp->sw_dev;
+			xs->xsw_flags = sp->sw_flags;
+			xs->xsw_nblks = sp->sw_nblks;
+			xs->xsw_used = sp->sw_used;
 
-			error = SYSCTL_OUT(req, &xs, sizeof(xs));
-			return (error);
+			return (0);
 		}
 		n++;
 	}
@@ -2396,6 +2415,24 @@
 	return (ENOENT);
 }
 
+static int
+sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS)
+{
+	int	*name = (int *)arg1;
+	int	error;
+	struct xswdev xs;
+
+	if (arg2 != 1) /* name length */
+		return (EINVAL);
+
+	error = swap_info(*name, &xs);
+	if (error != 0)
+		return (error);
+
+	error = SYSCTL_OUT(req, &xs, sizeof(xs));
+	return (error);
+}
+
 SYSCTL_INT(_vm, OID_AUTO, nswapdev, CTLFLAG_RD, &nswapdev, 0,
     "Number of swap devices");
 SYSCTL_NODE(_vm, OID_AUTO, swap_info, CTLFLAG_RD, sysctl_vm_swap_info,
--- a/sys/vm/swap_pager.h
+++ b/sys/vm/swap_pager.h
@@ -83,6 +83,8 @@
 int swap_pager_reserve(vm_object_t, vm_pindex_t, vm_size_t);
 void swap_pager_status(int *total, int *used);
 void swapoff_all(void);
+int swap_info(int name, struct xswdev *xs);
+int swap_devname(int name, char *devname, size_t len);
 
 #endif				/* _KERNEL */
 #endif				/* _VM_SWAP_PAGER_H_ */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAOfDtXOJjOoQA8yNFPVdQRqCqr-Vc5nscMbgOLGLMuvTP9mp1w>