summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2016-03-16 01:48:40 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2016-03-16 01:48:40 +0100
commit4f51b0e104481fb6d337140eeaa51af8c674d236 (patch)
tree452aacaf7f586e2ccd22bda15a92419d9616065b
parent0bc52ecb504401e089e1aa335c56e0c5db6d8e32 (diff)
Add getting swap information from swapon and procfs
* hurd/default_pager.defs (default_pager_storage_info): New RPC. * hurd/default_pager_reply.defs: Skip default_pager_storage_info RPC. * hurd/default_pager_types.h: Include <mach/machine/vm_types.h>. (vm_size_array_t): New type. * mach-defpager/priv.h (part): Add `name' field. * mach-defpager/default_pager.c (new_partition): Allocate and fill `part->name' field. Free it on error. (destroy_paging_partition): Free `part->name' field. (S_default_pager_storage_info): New function. * procfs/Makefile (SRCS): Add default_pagerUser.c. * procfs/rootdir.c: Include "default_pager_U.h". (rootdir_gc_swaps): New function. (rootdir_entries): Add "swaps" entry. * sutils/swapon.c: Include <argz.h> (show): New variable. (options): Add --show/-S option. (def_pager, dev_master): New variables (swaponoff): Move getting `def_pager' to... (get_def_pager): ... new function. (main): Support 'S' option. * trans/proxy-defpager.c (S_default_pager_storage_info): New function.
-rw-r--r--hurd/default_pager.defs9
-rw-r--r--hurd/default_pager_reply.defs2
-rw-r--r--hurd/default_pager_types.h2
-rw-r--r--mach-defpager/default_pager.c100
-rw-r--r--mach-defpager/priv.h1
-rw-r--r--procfs/Makefile2
-rw-r--r--procfs/rootdir.c58
-rw-r--r--sutils/swapon.c107
-rw-r--r--trans/proxy-defpager.c13
9 files changed, 262 insertions, 32 deletions
diff --git a/hurd/default_pager.defs b/hurd/default_pager.defs
index a97bff2a..14a5ec40 100644
--- a/hurd/default_pager.defs
+++ b/hurd/default_pager.defs
@@ -98,3 +98,12 @@ routine default_pager_object_set_size(
memory_object : memory_object_t;
msgseqno seqno : mach_port_seqno_t;
object_size_limit : vm_size_t);
+
+routine default_pager_storage_info(
+ default_pager : mach_port_t;
+ out size : vm_size_array_t =
+ array[] of vm_size_t, dealloc;
+ out free : vm_size_array_t =
+ array[] of vm_size_t, dealloc;
+ out name : data_t);
+
diff --git a/hurd/default_pager_reply.defs b/hurd/default_pager_reply.defs
index 0f9ff86b..02e0e911 100644
--- a/hurd/default_pager_reply.defs
+++ b/hurd/default_pager_reply.defs
@@ -15,3 +15,5 @@ skip; /* default_pager_paging_storage */
simpleroutine default_pager_object_set_size_reply(
reply_port: mach_port_send_once_t;
RETURN_CODE_ARG);
+
+skip; /* default_pager_storage_info */
diff --git a/hurd/default_pager_types.h b/hurd/default_pager_types.h
index 7cd14a3d..99ed3fad 100644
--- a/hurd/default_pager_types.h
+++ b/hurd/default_pager_types.h
@@ -21,8 +21,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define _DEFAULT_PAGER_TYPES_H
#include <mach/std_types.h> /* For mach_port_t et al. */
+#include <mach/machine/vm_types.h> /* For vm_size_t. */
#include <device/device_types.h> /* For recnum_t. */
typedef recnum_t *recnum_array_t;
+typedef vm_size_t *vm_size_array_t;
#endif
diff --git a/mach-defpager/default_pager.c b/mach-defpager/default_pager.c
index 83382c05..53797958 100644
--- a/mach-defpager/default_pager.c
+++ b/mach-defpager/default_pager.c
@@ -164,6 +164,7 @@ new_partition (const char *name, struct file_direct *fdp,
mach_msg_type_number_t rsize;
int rc;
unsigned int id = part_id(name);
+ unsigned int n = strlen(name);
pthread_mutex_lock(&all_partitions.lock);
{
@@ -185,6 +186,8 @@ new_partition (const char *name, struct file_direct *fdp,
part = (partition_t) kalloc(sizeof(struct part));
pthread_mutex_init(&part->p_lock, NULL);
+ part->name = (char*) kalloc(n + 1);
+ strcpy(part->name, name);
part->total_size = size;
part->free = size;
part->id = id;
@@ -333,6 +336,7 @@ new_partition (const char *name, struct file_direct *fdp,
name);
vm_deallocate(mach_task_self(), raddr, rsize);
kfree(part->bitmap, bmsize);
+ kfree(part->name, strlen(part->name) + 1);
kfree(part, sizeof *part);
return 0;
}
@@ -384,6 +388,7 @@ new_partition (const char *name, struct file_direct *fdp,
"SKIPPING %s (%uk partition)!",
name, part->total_size * (vm_page_size / 1024));
kfree(part->bitmap, bmsize);
+ kfree(part->name, strlen(part->name) + 1);
kfree(part, sizeof *part);
part = 0;
}
@@ -1905,6 +1910,7 @@ dprintf("Partition x%x (id x%x) for %s, all_ok %d\n", part, id, name, all_ok);
set_partition_of(pindex, 0);
*pp_private = part->file;
kfree(part->bitmap, howmany(part->total_size, NB_BM) * sizeof(bm_entry_t));
+ kfree(part->name, strlen(part->name) + 1);
kfree(part, sizeof(struct part));
dprintf("%s Removed paging partition %s\n", my_name, name);
return KERN_SUCCESS;
@@ -3224,6 +3230,100 @@ S_default_pager_info (mach_port_t pager,
}
kern_return_t
+S_default_pager_storage_info (mach_port_t pager,
+ vm_size_array_t *size,
+ mach_msg_type_number_t *sizeCnt,
+ vm_size_array_t *free,
+ mach_msg_type_number_t *freeCnt,
+ data_t *name,
+ mach_msg_type_number_t *nameCnt)
+{
+ int i, n, m;
+ int len = 0;
+ char *names;
+ kern_return_t kr;
+ vm_offset_t addr;
+ vm_size_array_t osize = *size;
+ vm_size_array_t ofree = *free;
+ data_t oname = *name;
+
+ if (pager != default_pager_default_port)
+ return KERN_INVALID_ARGUMENT;
+
+ pthread_mutex_lock(&all_partitions.lock);
+
+ n = all_partitions.n_partitions;
+
+ len = 0;
+ m = 0;
+ for (i = 0; i < n; i++) {
+ partition_t part = partition_of(i);
+ if (part == 0)
+ continue;
+ m++;
+ len += strlen(part->name) + 1;
+ }
+
+ if (*sizeCnt < m)
+ {
+ kr = vm_allocate(default_pager_self, &addr,
+ round_page(m * sizeof(*size)), TRUE);
+ if (kr != KERN_SUCCESS);
+ goto nomemory;
+ *size = (vm_size_array_t) addr;
+ }
+ *sizeCnt = m;
+
+ if (*freeCnt < m)
+ {
+ kr = vm_allocate(default_pager_self, &addr,
+ round_page(m * sizeof(*free)), TRUE);
+ if (kr != KERN_SUCCESS);
+ goto nomemory;
+ *free = (vm_size_array_t) addr;
+ }
+ *freeCnt = m;
+
+ if (*nameCnt < len)
+ {
+ kr = vm_allocate(default_pager_self, &addr,
+ round_page(len), TRUE);
+ if (kr != KERN_SUCCESS);
+ goto nomemory;
+ *name = (data_t) addr;
+ }
+ *nameCnt = len;
+
+ names = *name;
+ for (i = 0; i < n; i++) {
+ partition_t part = partition_of(i);
+ if (part == 0)
+ continue;
+
+ (*size)[i] = ptoa(part->total_size);
+ (*free)[i] = ptoa(part->free);
+ names = stpcpy(names, part->name) + 1;
+ }
+
+ pthread_mutex_unlock(&all_partitions.lock);
+
+ return KERN_SUCCESS;
+
+nomemory:
+ pthread_mutex_unlock(&all_partitions.lock);
+ if (*size != osize)
+ (void) vm_deallocate(default_pager_self, (vm_offset_t) *size,
+ round_page(m * sizeof(*size)));
+ if (*free != ofree)
+ (void) vm_deallocate(default_pager_self, (vm_offset_t) *free,
+ round_page(m * sizeof(*free)));
+ if (*name != oname)
+ (void) vm_deallocate(default_pager_self, (vm_offset_t) *name,
+ len);
+ return KERN_RESOURCE_SHORTAGE;
+}
+
+kern_return_t
S_default_pager_objects (mach_port_t pager,
default_pager_object_array_t *objectsp,
natural_t *ocountp,
diff --git a/mach-defpager/priv.h b/mach-defpager/priv.h
index 36845657..a8844521 100644
--- a/mach-defpager/priv.h
+++ b/mach-defpager/priv.h
@@ -51,6 +51,7 @@ typedef unsigned int bm_entry_t;
*/
struct part {
pthread_mutex_t p_lock; /* for bitmap/free */
+ char *name; /* name */
vm_size_t total_size; /* total number of blocks */
vm_size_t free; /* number of blocks free */
unsigned int id; /* named lookup */
diff --git a/procfs/Makefile b/procfs/Makefile
index 12fc9eee..13ee026c 100644
--- a/procfs/Makefile
+++ b/procfs/Makefile
@@ -21,7 +21,7 @@ makemode := server
target = procfs
-SRCS = procfs.c netfs.c procfs_dir.c process.c proclist.c rootdir.c dircat.c main.c mach_debugUser.c
+SRCS = procfs.c netfs.c procfs_dir.c process.c proclist.c rootdir.c dircat.c main.c mach_debugUser.c default_pagerUser.c
LCLHDRS = dircat.h main.h process.h procfs.h procfs_dir.h proclist.h rootdir.h
OBJS = $(SRCS:.c=.o)
diff --git a/procfs/rootdir.c b/procfs/rootdir.c
index 93fef8d9..dd693c89 100644
--- a/procfs/rootdir.c
+++ b/procfs/rootdir.c
@@ -21,6 +21,7 @@
#include <mach/vm_param.h>
#include <mach/vm_statistics.h>
#include <mach/vm_cache_statistics.h>
+#include "default_pager_U.h"
#include <mach/default_pager.h>
#include <mach_debug/mach_debug_types.h>
#include <hurd/paths.h>
@@ -521,6 +522,56 @@ rootdir_gc_filesystems (void *hook, char **contents, ssize_t *contents_len)
fclose (m);
return err;
}
+
+static error_t
+rootdir_gc_swaps (void *hook, char **contents, ssize_t *contents_len)
+{
+ mach_port_t defpager;
+ error_t err = 0;
+ FILE *m;
+ vm_size_t *free = NULL;
+ size_t nfree = 0;
+ vm_size_t *size = NULL;
+ size_t nsize = 0;
+ char *names = NULL, *name;
+ size_t names_len = 0;
+ size_t i;
+
+ m = open_memstream (contents, (size_t *) contents_len);
+ if (m == NULL)
+ return errno;
+
+ defpager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0);
+ if (defpager == MACH_PORT_NULL)
+ {
+ err = errno;
+ goto out_fclose;
+ }
+
+ err = default_pager_storage_info (defpager, &free, &nfree, &size, &nsize,
+ &names, &names_len);
+ if (err)
+ goto out;
+
+ fprintf(m, "Filename\tType\t\tSize\tUsed\tPriority\n");
+ name = names;
+ for (i = 0; i < nfree; i++)
+ {
+ fprintf (m, "/dev/%s\tpartition\t%zu\t%zu\t-1\n",
+ name, size[i] >> 10, (size[i] - free[i]) >> 10);
+ name = argz_next (names, names_len, name);
+ }
+
+ vm_deallocate (mach_task_self(), (vm_offset_t) free, nfree * sizeof(*free));
+ vm_deallocate (mach_task_self(), (vm_offset_t) size, nsize * sizeof(*size));
+ vm_deallocate (mach_task_self(), (vm_offset_t) names, names_len);
+
+out:
+ mach_port_deallocate (mach_task_self (), defpager);
+out_fclose:
+ fclose (m);
+ return err;
+}
/* Glue logic and entries table */
@@ -703,6 +754,13 @@ static const struct procfs_dir_entry rootdir_entries[] = {
.cleanup_contents = procfs_cleanup_contents_with_free,
},
},
+ {
+ .name = "swaps",
+ .hook = & (struct procfs_node_ops) {
+ .get_contents = rootdir_gc_swaps,
+ .cleanup_contents = procfs_cleanup_contents_with_free,
+ },
+ },
#ifdef PROFILE
/* In order to get a usable gmon.out file, we must apparently use exit(). */
{
diff --git a/sutils/swapon.c b/sutils/swapon.c
index 2403f1c2..ae830baa 100644
--- a/sutils/swapon.c
+++ b/sutils/swapon.c
@@ -27,6 +27,7 @@
#include <string.h>
#include <stdint.h>
#include <argp.h>
+#include <argz.h>
#include <error.h>
#include <assert.h>
#include <sys/mman.h>
@@ -42,7 +43,7 @@ const char *argp_program_version = STANDARD_HURD_VERSION (swapoff);
const char *argp_program_version = STANDARD_HURD_VERSION (swapon);
#endif
-static int ignore_signature, require_signature, quiet, ifexists;
+static int ignore_signature, require_signature, show, quiet, ifexists;
static struct argp_option options[] =
{
@@ -54,6 +55,8 @@ static struct argp_option options[] =
"Do not check for a Linux swap signature page"},
{"require-signature", 's', 0, 0,
"Require a Linux swap signature page"},
+ {"show", 'S', 0, 0,
+ "Show devices currently in use"},
{"silent", 'q', 0, 0, "Print only diagnostic messages"},
{"quiet", 'q', 0, OPTION_ALIAS | OPTION_HIDDEN },
{"verbose", 'v', 0, 0, "Be verbose"},
@@ -81,6 +84,39 @@ static char *doc =
verbose ("%s: Linux 2.2 swap signature v1, %zuk swap-space" fmt, \
name, freepages * (LINUX_PAGE_SIZE / 1024) ,##arg)
+
+static mach_port_t def_pager = MACH_PORT_NULL;
+static mach_port_t dev_master = MACH_PORT_NULL;
+
+static void get_def_pager(void)
+{
+ int err;
+ mach_port_t host;
+
+ if (def_pager != MACH_PORT_NULL)
+ return;
+
+ err = get_privileged_ports (&host, &dev_master);
+ if (err == EPERM)
+ {
+ /* We are not root, so try opening the /servers node. */
+ def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_WRITE, 0);
+ if (def_pager == MACH_PORT_NULL)
+ error (11, errno, _SERVERS_DEFPAGER);
+ }
+ else
+ {
+ if (err)
+ error (12, err, "Cannot get privileged ports");
+
+ err = vm_set_default_memory_manager (host, &def_pager);
+ mach_port_deallocate (mach_task_self (), host);
+ if (err)
+ error (13, err, "Cannot get default pager port");
+ if (def_pager == MACH_PORT_NULL)
+ error (14, 0, "No default pager (memory manager) is running!");
+ }
+}
/* Examine the store in *STOREP to see if it has a Linux-compatible
swap signature page as created by the Linux `mkswap' utility. If
@@ -326,8 +362,6 @@ swaponoff (const char *file, int add, int skipnotexisting)
{
error_t err;
struct store *store;
- static mach_port_t def_pager = MACH_PORT_NULL;
- static mach_port_t dev_master = MACH_PORT_NULL;
static int old_protocol;
int quiet_now = 0;
@@ -384,34 +418,7 @@ swaponoff (const char *file, int add, int skipnotexisting)
return EINVAL;
}
- if (def_pager == MACH_PORT_NULL)
- {
- mach_port_t host;
-
- err = get_privileged_ports (&host, &dev_master);
- if (err == EPERM)
- {
- /* We are not root, so try opening the /servers node. */
- def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_WRITE, 0);
- if (def_pager == MACH_PORT_NULL)
- {
- error (11, errno, _SERVERS_DEFPAGER);
- return 0;
- }
- }
- else
- {
- if (err)
- error (12, err, "Cannot get privileged ports");
-
- err = vm_set_default_memory_manager (host, &def_pager);
- mach_port_deallocate (mach_task_self (), host);
- if (err)
- error (13, err, "Cannot get default pager port");
- if (def_pager == MACH_PORT_NULL)
- error (14, 0, "No default pager (memory manager) is running!");
- }
- }
+ get_def_pager();
if (old_protocol)
{
@@ -487,6 +494,10 @@ main (int argc, char *argv[])
ignore_signature = 0;
break;
+ case 'S':
+ show = 1;
+ break;
+
case 'q':
quiet = 1;
break;
@@ -547,5 +558,39 @@ main (int argc, char *argv[])
}
}
+ if (show)
+ {
+ vm_size_t *free = NULL;
+ size_t nfree = 0;
+ vm_size_t *size = NULL;
+ size_t nsize = 0;
+ char *names = NULL, *name;
+ size_t names_len = 0;
+ size_t i;
+ int err;
+
+ get_def_pager();
+
+ err = default_pager_storage_info (def_pager, &free, &nfree, &size, &nsize,
+ &names, &names_len);
+ if (err)
+ error (3, 0, "Can not get default pager storage information");
+
+ printf("Filename\tType\t\tSize\tUsed\tPriority\n");
+ name = names;
+ for (i = 0; i < nfree; i++)
+ {
+ printf ("/dev/%s\tpartition\t%zuM\t%zuM\t-1\n",
+ name, size[i] >> 20, (size[i] - free[i]) >> 20);
+ name = argz_next (names, names_len, name);
+ }
+
+ vm_deallocate (mach_task_self(), (vm_offset_t) free,
+ nfree * sizeof(*free));
+ vm_deallocate (mach_task_self(), (vm_offset_t) size,
+ nsize * sizeof(*size));
+ vm_deallocate (mach_task_self(), (vm_offset_t) names, names_len);
+ }
+
return 0;
}
diff --git a/trans/proxy-defpager.c b/trans/proxy-defpager.c
index 4fdeb35b..9a8436ae 100644
--- a/trans/proxy-defpager.c
+++ b/trans/proxy-defpager.c
@@ -64,6 +64,19 @@ S_default_pager_info (mach_port_t default_pager, default_pager_info_t *info)
}
kern_return_t
+S_default_pager_storage_info (mach_port_t default_pager,
+ vm_size_array_t *size,
+ mach_msg_type_number_t *sizeCnt,
+ vm_size_array_t *free,
+ mach_msg_type_number_t *freeCnt,
+ data_t *name,
+ mach_msg_type_number_t *nameCnt)
+{
+ return allowed (default_pager, O_READ)
+ ?: default_pager_storage_info (real_defpager, size, sizeCnt, free, freeCnt, name, nameCnt);
+}
+
+kern_return_t
S_default_pager_objects (mach_port_t default_pager,
default_pager_object_array_t *objects,
mach_msg_type_number_t *objectsCnt,