diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-03-16 01:48:40 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-03-16 01:48:40 +0100 |
commit | 4f51b0e104481fb6d337140eeaa51af8c674d236 (patch) | |
tree | 452aacaf7f586e2ccd22bda15a92419d9616065b | |
parent | 0bc52ecb504401e089e1aa335c56e0c5db6d8e32 (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.defs | 9 | ||||
-rw-r--r-- | hurd/default_pager_reply.defs | 2 | ||||
-rw-r--r-- | hurd/default_pager_types.h | 2 | ||||
-rw-r--r-- | mach-defpager/default_pager.c | 100 | ||||
-rw-r--r-- | mach-defpager/priv.h | 1 | ||||
-rw-r--r-- | procfs/Makefile | 2 | ||||
-rw-r--r-- | procfs/rootdir.c | 58 | ||||
-rw-r--r-- | sutils/swapon.c | 107 | ||||
-rw-r--r-- | trans/proxy-defpager.c | 13 |
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, |