summaryrefslogtreecommitdiff
path: root/debian/patches/mach-defpager-fix-receiver-lookups.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/mach-defpager-fix-receiver-lookups.patch')
-rw-r--r--debian/patches/mach-defpager-fix-receiver-lookups.patch941
1 files changed, 941 insertions, 0 deletions
diff --git a/debian/patches/mach-defpager-fix-receiver-lookups.patch b/debian/patches/mach-defpager-fix-receiver-lookups.patch
new file mode 100644
index 00000000..2fe57a6c
--- /dev/null
+++ b/debian/patches/mach-defpager-fix-receiver-lookups.patch
@@ -0,0 +1,941 @@
+diff --git a/hurd/default_pager.defs b/hurd/default_pager.defs
+index 8ad82dc..4885503 100644
+--- a/hurd/default_pager.defs
++++ b/hurd/default_pager.defs
+@@ -36,6 +36,10 @@ subsystem default_pager 2275;
+
+ import <hurd/default_pager_types.h>; /* XXX */
+
++#ifdef DEFAULT_PAGER_IMPORTS
++DEFAULT_PAGER_IMPORTS
++#endif
++
+ routine default_pager_object_create(
+ default_pager : mach_port_t;
+ out memory_object : memory_object_t =
+@@ -90,6 +94,6 @@ routine default_pager_paging_storage(
+ to fix the object's maximum size. Any references to pages beyond the limit
+ will fail. */
+ routine default_pager_object_set_size(
+- memory_object : mach_port_t;
++ memory_object : memory_object_t;
+ msgseqno seqno : mach_port_seqno_t;
+ object_size_limit : vm_size_t);
+diff --git a/mach-defpager/Makefile b/mach-defpager/Makefile
+index e38a0be..09debed 100644
+--- a/mach-defpager/Makefile
++++ b/mach-defpager/Makefile
+@@ -29,9 +29,10 @@ OBJS := $(SRCS:.c=.o) \
+ memory_object default_pager memory_object_default exc) \
+ default_pager_replyUser.o
+
++HURDLIBS:= ihash
+ OTHERLIBS:= -lpthread
+ LDFLAGS += -static
+
+ include ../Makeconf
+
+-MIGSFLAGS = -DSEQNOS
++MIGSFLAGS = -DSEQNOS -imacros $(srcdir)/mig-mutate.h
+diff --git a/mach-defpager/default_pager.c b/mach-defpager/default_pager.c
+index 8f8e13e..f514ea6 100644
+--- a/mach-defpager/default_pager.c
++++ b/mach-defpager/default_pager.c
+@@ -38,14 +38,17 @@
+ #include <mach/default_pager_types.h>
+
+ #include <pthread.h>
++#include <stddef.h>
+
+ #include <device/device_types.h>
+ #include <device/device.h>
+
+-#include <queue.h>
+-#include <wiring.h>
+-#include <kalloc.h>
+-#include <default_pager.h>
++#include <hurd/ihash.h>
++
++#include "queue.h"
++#include "wiring.h"
++#include "kalloc.h"
++#include "default_pager.h"
+
+ #include <assert.h>
+ #include <errno.h>
+@@ -60,6 +63,8 @@
+ #include "default_pager_S.h"
+ #include "exc_S.h"
+
++#include "priv.h"
++
+ #define debug 0
+
+ static char my_name[] = "(default pager):";
+@@ -106,47 +111,6 @@ synchronized_printf (const char *fmt, ...)
+ #define ptoa(p) ((p)*vm_page_size)
+ #define atop(a) ((a)/vm_page_size)
+
+-/*
+- * Bitmap allocation.
+- */
+-typedef unsigned int bm_entry_t;
+-#define NB_BM 32
+-#define BM_MASK 0xffffffff
+-
+-#define howmany(a,b) (((a) + (b) - 1)/(b))
+-
+-/*
+- * Value to indicate no block assigned
+- */
+-#define NO_BLOCK ((vm_offset_t)-1)
+-
+-/*
+- * 'Partition' structure for each paging area.
+- * Controls allocation of blocks within paging area.
+- */
+-struct part {
+- pthread_mutex_t p_lock; /* for bitmap/free */
+- vm_size_t total_size; /* total number of blocks */
+- vm_size_t free; /* number of blocks free */
+- unsigned int id; /* named lookup */
+- bm_entry_t *bitmap; /* allocation map */
+- boolean_t going_away; /* destroy attempt in progress */
+- struct file_direct *file; /* file paged to */
+-};
+-typedef struct part *partition_t;
+-
+-struct {
+- pthread_mutex_t lock;
+- int n_partitions;
+- partition_t *partition_list;/* array, for quick mapping */
+-} all_partitions; /* list of all such */
+-
+-typedef unsigned char p_index_t;
+-
+-#define P_INDEX_INVALID ((p_index_t)-1)
+-
+-#define no_partition(x) ((x) == P_INDEX_INVALID)
+-
+ partition_t partition_of(x)
+ int x;
+ {
+@@ -632,81 +596,6 @@ ddprintf ("pager_dealloc_page(%d,%x,%d)\n",pindex,page,lock_it);
+ }
+
+ /*
+- * Allocation info for each paging object.
+- *
+- * Most operations, even pager_write_offset and pager_put_checksum,
+- * just need a read lock. Higher-level considerations prevent
+- * conflicting operations on a single page. The lock really protects
+- * the underlying size and block map memory, so pager_extend needs a
+- * write lock.
+- *
+- * An object can now span multiple paging partitions. The allocation
+- * info we keep is a pair (offset,p_index) where the index is in the
+- * array of all partition ptrs, and the offset is partition-relative.
+- * Size wise we are doing ok fitting the pair into a single integer:
+- * the offset really is in pages so we have vm_page_size bits available
+- * for the partition index.
+- */
+-#define DEBUG_READER_CONFLICTS 0
+-
+-#if DEBUG_READER_CONFLICTS
+-int default_pager_read_conflicts = 0;
+-#endif
+-
+-union dp_map {
+-
+- struct {
+- unsigned int p_offset : 24,
+- p_index : 8;
+- } block;
+-
+- union dp_map *indirect;
+-};
+-typedef union dp_map *dp_map_t;
+-
+-/* quick check for part==block==invalid */
+-#define no_block(e) ((e).indirect == (dp_map_t)NO_BLOCK)
+-#define invalidate_block(e) ((e).indirect = (dp_map_t)NO_BLOCK)
+-
+-struct dpager {
+- pthread_mutex_t lock; /* lock for extending block map */
+- /* XXX should be read-write lock */
+-#if DEBUG_READER_CONFLICTS
+- int readers;
+- boolean_t writer;
+-#endif
+- dp_map_t map; /* block map */
+- vm_size_t size; /* size of paging object, in pages */
+- vm_size_t limit; /* limit (bytes) allowed to grow to */
+- vm_size_t byte_limit; /* limit, which wasn't
+- rounded to page boundary */
+- p_index_t cur_partition;
+-#ifdef CHECKSUM
+- vm_offset_t *checksum; /* checksum - parallel to block map */
+-#define NO_CHECKSUM ((vm_offset_t)-1)
+-#endif /* CHECKSUM */
+-};
+-typedef struct dpager *dpager_t;
+-
+-/*
+- * A paging object uses either a one- or a two-level map of offsets
+- * into a paging partition.
+- */
+-#define PAGEMAP_ENTRIES 64
+- /* number of pages in a second-level map */
+-#define PAGEMAP_SIZE(npgs) ((npgs)*sizeof(vm_offset_t))
+-
+-#define INDIRECT_PAGEMAP_ENTRIES(npgs) \
+- ((((npgs)-1)/PAGEMAP_ENTRIES) + 1)
+-#define INDIRECT_PAGEMAP_SIZE(npgs) \
+- (INDIRECT_PAGEMAP_ENTRIES(npgs) * sizeof(vm_offset_t *))
+-#define INDIRECT_PAGEMAP(size) \
+- (size > PAGEMAP_ENTRIES)
+-
+-#define ROUNDUP_TO_PAGEMAP(npgs) \
+- (((npgs) + PAGEMAP_ENTRIES - 1) & ~(PAGEMAP_ENTRIES - 1))
+-
+-/*
+ * Object sizes are rounded up to the next power of 2,
+ * unless they are bigger than a given maximum size.
+ */
+@@ -1885,40 +1774,6 @@ default_has_page(ds, offset)
+ return ( ! no_block(pager_read_offset(ds, offset)) );
+ }
+
+-/*
+- * Mapping between pager port and paging object.
+- */
+-struct dstruct {
+- queue_chain_t links; /* Link in pager-port list */
+-
+- pthread_mutex_t lock; /* Lock for the structure */
+- pthread_cond_t
+- waiting_seqno, /* someone waiting on seqno */
+- waiting_read, /* someone waiting on readers */
+- waiting_write, /* someone waiting on writers */
+- waiting_refs; /* someone waiting on refs */
+-
+- memory_object_t pager; /* Pager port */
+- mach_port_seqno_t seqno; /* Pager port sequence number */
+- mach_port_t pager_request; /* Request port */
+- mach_port_urefs_t request_refs; /* Request port user-refs */
+- mach_port_t pager_name; /* Name port */
+- mach_port_urefs_t name_refs; /* Name port user-refs */
+- boolean_t external; /* Is an external object? */
+-
+- unsigned int readers; /* Reads in progress */
+- unsigned int writers; /* Writes in progress */
+-
+- /* This is the reply port of an outstanding
+- default_pager_object_set_size call. */
+- mach_port_t lock_request;
+-
+- unsigned int errors; /* Pageout error count */
+- struct dpager dpager; /* Actual pager */
+-};
+-typedef struct dstruct * default_pager_t;
+-#define DEFAULT_PAGER_NULL ((default_pager_t)0)
+-
+ #if PARALLEL
+ #define dstruct_lock_init(ds) pthread_mutex_init(&ds->lock, NULL)
+ #define dstruct_lock(ds) pthread_mutex_lock(&ds->lock)
+@@ -1929,25 +1784,14 @@ typedef struct dstruct * default_pager_t;
+ #define dstruct_unlock(ds)
+ #endif /* PARALLEL */
+
+-/*
+- * List of all pagers. A specific pager is
+- * found directly via its port, this list is
+- * only used for monitoring purposes by the
+- * default_pager_object* calls
+- */
+-struct pager_port {
+- queue_head_t queue;
+- pthread_mutex_t lock;
+- int count; /* saves code */
+- queue_head_t leak_queue;
+-} all_pagers;
++struct pager_port all_pagers;
+
+ #define pager_port_list_init() \
+ { \
+ pthread_mutex_init(&all_pagers.lock, NULL); \
+- queue_init(&all_pagers.queue); \
++ hurd_ihash_init (&all_pagers.htable, \
++ offsetof (struct dstruct, htable_locp)); \
+ queue_init(&all_pagers.leak_queue); \
+- all_pagers.count = 0; \
+ }
+
+ void pager_port_list_insert(port, ds)
+@@ -1955,28 +1799,18 @@ void pager_port_list_insert(port, ds)
+ default_pager_t ds;
+ {
+ pthread_mutex_lock(&all_pagers.lock);
+- queue_enter(&all_pagers.queue, ds, default_pager_t, links);
+- all_pagers.count++;
++ hurd_ihash_add (&all_pagers.htable,
++ (hurd_ihash_key_t) port,
++ (hurd_ihash_value_t) ds);
+ pthread_mutex_unlock(&all_pagers.lock);
+ }
+
+-/* given a data structure return a good port-name to associate it to */
+-#define pnameof(_x_) (((vm_offset_t)(_x_))+1)
+-/* reverse, assumes no-odd-pointers */
+-#define dnameof(_x_) (((vm_offset_t)(_x_))&~1)
+-
+-/* The magic typecast */
+-#define pager_port_lookup(_port_) \
+- ((! MACH_PORT_VALID(_port_) || \
+- ((default_pager_t)dnameof(_port_))->pager != (_port_)) ? \
+- DEFAULT_PAGER_NULL : (default_pager_t)dnameof(_port_))
+-
+ void pager_port_list_delete(ds)
+ default_pager_t ds;
+ {
+ pthread_mutex_lock(&all_pagers.lock);
+- queue_remove(&all_pagers.queue, ds, default_pager_t, links);
+- all_pagers.count--;
++ hurd_ihash_locp_remove (&all_pagers.htable,
++ ds->htable_locp);
+ pthread_mutex_unlock(&all_pagers.lock);
+ }
+
+@@ -2023,7 +1857,8 @@ dprintf("Partition x%x (id x%x) for %s, all_ok %d\n", part, id, name, all_ok);
+ pthread_mutex_lock(&part->p_lock);
+
+ pthread_mutex_lock(&all_pagers.lock);
+- queue_iterate(&all_pagers.queue, entry, default_pager_t, links) {
++ HURD_IHASH_ITERATE (&all_pagers.htable, val) {
++ entry = (default_pager_t) val;
+
+ dstruct_lock(entry);
+
+@@ -2397,7 +2232,6 @@ seqnos_memory_object_create(old_pager, seqno, new_pager, new_size,
+ vm_size_t new_page_size;
+ {
+ default_pager_t ds;
+- kern_return_t kr;
+
+ assert(old_pager == default_pager_default_port);
+ assert(MACH_PORT_VALID(new_pager_request));
+@@ -2405,24 +2239,6 @@ seqnos_memory_object_create(old_pager, seqno, new_pager, new_size,
+ assert(new_page_size == vm_page_size);
+
+ ds = pager_port_alloc(new_size);
+-rename_it:
+- kr = mach_port_rename( default_pager_self,
+- new_pager, (mach_port_t)pnameof(ds));
+- if (kr != KERN_SUCCESS) {
+- default_pager_t ds1;
+-
+- if (kr != KERN_NAME_EXISTS)
+- panic("%s m_o_create", my_name);
+- ds1 = (default_pager_t) kalloc(sizeof *ds1);
+- *ds1 = *ds;
+- pthread_mutex_lock(&all_pagers.lock);
+- queue_enter(&all_pagers.leak_queue, ds, default_pager_t, links);
+- pthread_mutex_unlock(&all_pagers.lock);
+- ds = ds1;
+- goto rename_it;
+- }
+-
+- new_pager = (mach_port_t) pnameof(ds);
+
+ /*
+ * Set up associations between these ports
+@@ -2450,15 +2266,14 @@ memory_object_copy_strategy_t default_pager_copy_strategy =
+ MEMORY_OBJECT_COPY_DELAY;
+
+ kern_return_t
+-seqnos_memory_object_init(pager, seqno, pager_request, pager_name,
++seqnos_memory_object_init(ds, seqno, pager_request, pager_name,
+ pager_page_size)
+- mach_port_t pager;
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ mach_port_t pager_name;
+ vm_size_t pager_page_size;
+ {
+- default_pager_t ds;
+ kern_return_t kr;
+ static char here[] = "%sinit";
+
+@@ -2466,7 +2281,6 @@ seqnos_memory_object_init(pager, seqno, pager_request, pager_name,
+ assert(MACH_PORT_VALID(pager_name));
+ assert(pager_page_size == vm_page_size);
+
+- ds = pager_port_lookup(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ panic(here, my_name);
+ pager_port_lock(ds, seqno);
+@@ -2498,13 +2312,12 @@ seqnos_memory_object_init(pager, seqno, pager_request, pager_name,
+ }
+
+ kern_return_t
+-seqnos_memory_object_terminate(pager, seqno, pager_request, pager_name)
+- mach_port_t pager;
++seqnos_memory_object_terminate(ds, seqno, pager_request, pager_name)
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ mach_port_t pager_name;
+ {
+- default_pager_t ds;
+ static char here[] = "%sterminate";
+
+ /*
+@@ -2512,7 +2325,6 @@ seqnos_memory_object_terminate(pager, seqno, pager_request, pager_name)
+ * not send rights.
+ */
+
+- ds = pager_port_lookup(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ panic(here, my_name);
+ ddprintf ("seqnos_memory_object_terminate <%p>: pager_port_lock: <%p>[s:%d,r:%d,w:%d,l:%d], %d\n",
+@@ -2578,7 +2390,7 @@ void default_pager_no_senders(pager, seqno, mscount)
+ */
+
+
+- ds = pager_port_lookup(pager);
++ ds = begin_using_default_pager(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ panic(here,my_name);
+ pager_port_lock(ds, seqno);
+@@ -2639,16 +2451,15 @@ int default_pager_pageout_count = 0;
+ static __thread default_pager_thread_t *dpt;
+
+ kern_return_t
+-seqnos_memory_object_data_request(pager, seqno, reply_to, offset,
++seqnos_memory_object_data_request(ds, seqno, reply_to, offset,
+ length, protection_required)
+- memory_object_t pager;
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t reply_to;
+ vm_offset_t offset;
+ vm_size_t length;
+ vm_prot_t protection_required;
+ {
+- default_pager_t ds;
+ vm_offset_t addr;
+ unsigned int errors;
+ kern_return_t rc;
+@@ -2657,7 +2468,6 @@ seqnos_memory_object_data_request(pager, seqno, reply_to, offset,
+ if (length != vm_page_size)
+ panic(here,my_name);
+
+- ds = pager_port_lookup(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ panic(here,my_name);
+ ddprintf ("seqnos_memory_object_data_request <%p>: pager_port_lock: <%p>[s:%d,r:%d,w:%d,l:%d], %d\n",
+@@ -2742,9 +2552,9 @@ ddprintf ("seqnos_memory_object_data_request <%p>: pager_port_unlock: <%p>[s:%d,
+ * also assumes that the default_pager is single-threaded.
+ */
+ kern_return_t
+-seqnos_memory_object_data_initialize(pager, seqno, pager_request,
++seqnos_memory_object_data_initialize(ds, seqno, pager_request,
+ offset, addr, data_cnt)
+- memory_object_t pager;
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ register
+@@ -2754,14 +2564,12 @@ seqnos_memory_object_data_initialize(pager, seqno, pager_request,
+ vm_size_t data_cnt;
+ {
+ vm_offset_t amount_sent;
+- default_pager_t ds;
+ static char here[] = "%sdata_initialize";
+
+ #ifdef lint
+ pager_request++;
+ #endif /* lint */
+
+- ds = pager_port_lookup(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ panic(here,my_name);
+ ddprintf ("seqnos_memory_object_data_initialize <%p>: pager_port_lock: <%p>[s:%d,r:%d,w:%d,l:%d], %d\n",
+@@ -2804,9 +2612,9 @@ ddprintf ("seqnos_memory_object_data_initialize <%p>: pager_port_unlock: <%p>[s:
+ * into individual pages and pass them off to default_write.
+ */
+ kern_return_t
+-seqnos_memory_object_data_write(pager, seqno, pager_request,
++seqnos_memory_object_data_write(ds, seqno, pager_request,
+ offset, addr, data_cnt)
+- memory_object_t pager;
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ register
+@@ -2817,7 +2625,6 @@ seqnos_memory_object_data_write(pager, seqno, pager_request,
+ {
+ register
+ vm_size_t amount_sent;
+- default_pager_t ds;
+ static char here[] = "%sdata_write";
+ int err;
+
+@@ -2828,7 +2635,6 @@ seqnos_memory_object_data_write(pager, seqno, pager_request,
+ if ((data_cnt % vm_page_size) != 0)
+ panic(here,my_name);
+
+- ds = pager_port_lookup(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ panic(here,my_name);
+
+@@ -2888,7 +2694,7 @@ seqnos_memory_object_data_write(pager, seqno, pager_request,
+ kern_return_t
+ seqnos_memory_object_copy(old_memory_object, seqno, old_memory_control,
+ offset, length, new_memory_object)
+- memory_object_t old_memory_object;
++ default_pager_t old_memory_object;
+ mach_port_seqno_t seqno;
+ memory_object_control_t
+ old_memory_control;
+@@ -2903,7 +2709,7 @@ seqnos_memory_object_copy(old_memory_object, seqno, old_memory_control,
+ /* We get this when our memory_object_lock_request has completed
+ after we truncated an object. */
+ kern_return_t
+-seqnos_memory_object_lock_completed (memory_object_t pager,
++seqnos_memory_object_lock_completed (default_pager_t ds,
+ mach_port_seqno_t seqno,
+ mach_port_t pager_request,
+ vm_offset_t offset,
+@@ -2916,7 +2722,7 @@ seqnos_memory_object_lock_completed (memory_object_t pager,
+ kern_return_t
+ seqnos_memory_object_data_unlock(pager, seqno, pager_request,
+ offset, length, protection_required)
+- memory_object_t pager;
++ default_pager_t pager;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ vm_offset_t offset;
+@@ -2928,10 +2734,10 @@ seqnos_memory_object_data_unlock(pager, seqno, pager_request,
+ }
+
+ kern_return_t
+-seqnos_memory_object_supply_completed(pager, seqno, pager_request,
++seqnos_memory_object_supply_completed(ds, seqno, pager_request,
+ offset, length,
+ result, error_offset)
+- memory_object_t pager;
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ vm_offset_t offset;
+@@ -2949,10 +2755,10 @@ seqnos_memory_object_supply_completed(pager, seqno, pager_request,
+ * into individual pages and pass them off to default_write.
+ */
+ kern_return_t
+-seqnos_memory_object_data_return(pager, seqno, pager_request,
++seqnos_memory_object_data_return(ds, seqno, pager_request,
+ offset, addr, data_cnt,
+ dirty, kernel_copy)
+- memory_object_t pager;
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ mach_port_t pager_request;
+ vm_offset_t offset;
+@@ -2962,13 +2768,13 @@ seqnos_memory_object_data_return(pager, seqno, pager_request,
+ boolean_t kernel_copy;
+ {
+
+- return seqnos_memory_object_data_write (pager, seqno, pager_request,
++ return seqnos_memory_object_data_write (ds, seqno, pager_request,
+ offset, addr, data_cnt);
+ }
+
+ kern_return_t
+-seqnos_memory_object_change_completed(pager, seqno, may_cache, copy_strategy)
+- memory_object_t pager;
++seqnos_memory_object_change_completed(ds, seqno, may_cache, copy_strategy)
++ default_pager_t ds;
+ mach_port_seqno_t seqno;
+ boolean_t may_cache;
+ memory_object_copy_strategy_t copy_strategy;
+@@ -3364,23 +3170,14 @@ S_default_pager_object_create (mach_port_t pager,
+ return KERN_INVALID_ARGUMENT;
+
+ ds = pager_port_alloc(size);
+-rename_it:
+- port = (mach_port_t) pnameof(ds);
+- result = mach_port_allocate_name(default_pager_self,
+- MACH_PORT_RIGHT_RECEIVE, port);
+- if (result != KERN_SUCCESS) {
+- default_pager_t ds1;
+-
+- if (result != KERN_NAME_EXISTS) return (result);
+-
+- ds1 = (default_pager_t) kalloc(sizeof *ds1);
+- *ds1 = *ds;
+- pthread_mutex_lock(&all_pagers.lock);
+- queue_enter(&all_pagers.leak_queue, ds, default_pager_t, links);
+- pthread_mutex_unlock(&all_pagers.lock);
+- ds = ds1;
+- goto rename_it;
+- }
++ result = mach_port_allocate (default_pager_self,
++ MACH_PORT_RIGHT_RECEIVE,
++ &port);
++ if (result != KERN_SUCCESS)
++ {
++ kfree ((char *) ds, sizeof *ds);
++ return result;
++ }
+
+ /*
+ * Set up associations between these ports
+@@ -3454,7 +3251,7 @@ S_default_pager_objects (mach_port_t pager,
+ /*
+ * We will send no more than this many
+ */
+- actual = all_pagers.count;
++ actual = all_pagers.htable.nr_items;
+ pthread_mutex_unlock(&all_pagers.lock);
+
+ if (opotential < actual) {
+@@ -3496,7 +3293,8 @@ S_default_pager_objects (mach_port_t pager,
+ pthread_mutex_lock(&all_pagers.lock);
+
+ num_pagers = 0;
+- queue_iterate(&all_pagers.queue, entry, default_pager_t, links) {
++ HURD_IHASH_ITERATE (&all_pagers.htable, val) {
++ entry = (default_pager_t) val;
+
+ mach_port_t port;
+ vm_size_t size;
+@@ -3674,7 +3472,8 @@ S_default_pager_object_pages (mach_port_t pager,
+ default_pager_t entry;
+
+ pthread_mutex_lock(&all_pagers.lock);
+- queue_iterate(&all_pagers.queue, entry, default_pager_t, links) {
++ HURD_IHASH_ITERATE (&all_pagers.htable, val) {
++ entry = (default_pager_t) val;
+ dstruct_lock(entry);
+ if (entry->pager_name == object) {
+ pthread_mutex_unlock(&all_pagers.lock);
+@@ -3756,14 +3555,12 @@ S_default_pager_object_pages (mach_port_t pager,
+
+
+ kern_return_t
+-S_default_pager_object_set_size (mach_port_t pager,
++S_default_pager_object_set_size (default_pager_t ds,
+ mach_port_seqno_t seqno,
+ vm_size_t limit)
+ {
+ kern_return_t kr = KERN_SUCCESS;
+- default_pager_t ds;
+
+- ds = pager_port_lookup(pager);
+ if (ds == DEFAULT_PAGER_NULL)
+ return KERN_INVALID_ARGUMENT;
+
+diff --git a/mach-defpager/main.c b/mach-defpager/main.c
+index fe6f735..e33c2b3 100644
+--- a/mach-defpager/main.c
++++ b/mach-defpager/main.c
+@@ -43,7 +43,7 @@
+ #include <hurd/fd.h>
+ /* XXX */
+
+-#include <default_pager.h>
++#include "default_pager.h"
+
+ mach_port_t bootstrap_master_device_port; /* local name */
+ mach_port_t bootstrap_master_host_port; /* local name */
+diff --git a/mach-defpager/mig-decls.h b/mach-defpager/mig-decls.h
+new file mode 100644
+index 0000000..8118d61
+--- /dev/null
++++ b/mach-defpager/mig-decls.h
+@@ -0,0 +1,34 @@
++/*
++ Copyright (C) 2014 Free Software Foundation, Inc.
++ Written by Justus Winter.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2, or (at
++ your option) any later version.
++
++ The GNU Hurd is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
++
++#ifndef __MACH_DEFPAGER_MIG_DECLS_H__
++#define __MACH_DEFPAGER_MIG_DECLS_H__
++
++#include "priv.h"
++
++/* Called by server stub functions. */
++
++static inline struct dstruct * __attribute__ ((unused))
++begin_using_default_pager (mach_port_t port)
++{
++ return (default_pager_t) hurd_ihash_find (&all_pagers.htable,
++ (hurd_ihash_key_t) port);
++}
++
++#endif /* __MACH_DEFPAGER_MIG_DECLS_H__ */
+diff --git a/mach-defpager/mig-mutate.h b/mach-defpager/mig-mutate.h
+new file mode 100644
+index 0000000..54aeeba
+--- /dev/null
++++ b/mach-defpager/mig-mutate.h
+@@ -0,0 +1,22 @@
++/*
++ Copyright (C) 2014 Free Software Foundation, Inc.
++ Written by Justus Winter.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2, or (at
++ your option) any later version.
++
++ The GNU Hurd is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
++
++#define MEMORY_OBJECT_INTRAN default_pager_t begin_using_default_pager (mach_port_t)
++#define MEMORY_OBJECT_IMPORTS import "mig-decls.h";
++#define DEFAULT_PAGER_IMPORTS import "mig-decls.h";
+diff --git a/mach-defpager/priv.h b/mach-defpager/priv.h
+new file mode 100644
+index 0000000..3684565
+--- /dev/null
++++ b/mach-defpager/priv.h
+@@ -0,0 +1,200 @@
++/*
++ * Mach Operating System
++ * Copyright (c) 1993-1989 Carnegie Mellon University
++ * All Rights Reserved.
++ *
++ * Permission to use, copy, modify and distribute this software and its
++ * documentation is hereby granted, provided that both the copyright
++ * notice and this permission notice appear in all copies of the
++ * software, derivative works or modified versions, and any portions
++ * thereof, and that both notices appear in supporting documentation.
++ *
++ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
++ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
++ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
++ *
++ * Carnegie Mellon requests users of this software to return to
++ *
++ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
++ * School of Computer Science
++ * Carnegie Mellon University
++ * Pittsburgh PA 15213-3890
++ *
++ * any improvements or extensions that they make and grant Carnegie Mellon
++ * the rights to redistribute these changes.
++ */
++
++#ifndef __MACH_DEFPAGER_PRIV_H__
++#define __MACH_DEFPAGER_PRIV_H__
++
++#include <mach.h>
++#include <queue.h>
++#include <hurd/ihash.h>
++
++/*
++ * Bitmap allocation.
++ */
++typedef unsigned int bm_entry_t;
++#define NB_BM 32
++#define BM_MASK 0xffffffff
++
++#define howmany(a,b) (((a) + (b) - 1)/(b))
++
++/*
++ * Value to indicate no block assigned
++ */
++#define NO_BLOCK ((vm_offset_t)-1)
++
++/*
++ * 'Partition' structure for each paging area.
++ * Controls allocation of blocks within paging area.
++ */
++struct part {
++ pthread_mutex_t p_lock; /* for bitmap/free */
++ vm_size_t total_size; /* total number of blocks */
++ vm_size_t free; /* number of blocks free */
++ unsigned int id; /* named lookup */
++ bm_entry_t *bitmap; /* allocation map */
++ boolean_t going_away; /* destroy attempt in progress */
++ struct file_direct *file; /* file paged to */
++};
++typedef struct part *partition_t;
++
++struct {
++ pthread_mutex_t lock;
++ int n_partitions;
++ partition_t *partition_list;/* array, for quick mapping */
++} all_partitions; /* list of all such */
++
++typedef unsigned char p_index_t;
++
++#define P_INDEX_INVALID ((p_index_t)-1)
++
++#define no_partition(x) ((x) == P_INDEX_INVALID)
++
++/*
++ * Allocation info for each paging object.
++ *
++ * Most operations, even pager_write_offset and pager_put_checksum,
++ * just need a read lock. Higher-level considerations prevent
++ * conflicting operations on a single page. The lock really protects
++ * the underlying size and block map memory, so pager_extend needs a
++ * write lock.
++ *
++ * An object can now span multiple paging partitions. The allocation
++ * info we keep is a pair (offset,p_index) where the index is in the
++ * array of all partition ptrs, and the offset is partition-relative.
++ * Size wise we are doing ok fitting the pair into a single integer:
++ * the offset really is in pages so we have vm_page_size bits available
++ * for the partition index.
++ */
++#define DEBUG_READER_CONFLICTS 0
++
++#if DEBUG_READER_CONFLICTS
++int default_pager_read_conflicts = 0;
++#endif
++
++union dp_map {
++
++ struct {
++ unsigned int p_offset : 24,
++ p_index : 8;
++ } block;
++
++ union dp_map *indirect;
++};
++typedef union dp_map *dp_map_t;
++
++/* quick check for part==block==invalid */
++#define no_block(e) ((e).indirect == (dp_map_t)NO_BLOCK)
++#define invalidate_block(e) ((e).indirect = (dp_map_t)NO_BLOCK)
++
++struct dpager {
++ pthread_mutex_t lock; /* lock for extending block map */
++ /* XXX should be read-write lock */
++#if DEBUG_READER_CONFLICTS
++ int readers;
++ boolean_t writer;
++#endif
++ dp_map_t map; /* block map */
++ vm_size_t size; /* size of paging object, in pages */
++ vm_size_t limit; /* limit (bytes) allowed to grow to */
++ vm_size_t byte_limit; /* limit, which wasn't
++ rounded to page boundary */
++ p_index_t cur_partition;
++#ifdef CHECKSUM
++ vm_offset_t *checksum; /* checksum - parallel to block map */
++#define NO_CHECKSUM ((vm_offset_t)-1)
++#endif /* CHECKSUM */
++};
++typedef struct dpager *dpager_t;
++
++/*
++ * A paging object uses either a one- or a two-level map of offsets
++ * into a paging partition.
++ */
++#define PAGEMAP_ENTRIES 64
++ /* number of pages in a second-level map */
++#define PAGEMAP_SIZE(npgs) ((npgs)*sizeof(vm_offset_t))
++
++#define INDIRECT_PAGEMAP_ENTRIES(npgs) \
++ ((((npgs)-1)/PAGEMAP_ENTRIES) + 1)
++#define INDIRECT_PAGEMAP_SIZE(npgs) \
++ (INDIRECT_PAGEMAP_ENTRIES(npgs) * sizeof(vm_offset_t *))
++#define INDIRECT_PAGEMAP(size) \
++ (size > PAGEMAP_ENTRIES)
++
++#define ROUNDUP_TO_PAGEMAP(npgs) \
++ (((npgs) + PAGEMAP_ENTRIES - 1) & ~(PAGEMAP_ENTRIES - 1))
++
++/*
++ * Mapping between pager port and paging object.
++ */
++struct dstruct {
++ hurd_ihash_locp_t htable_locp; /* for the ihash table */
++ queue_chain_t links; /* Link in pager-port list */
++
++ pthread_mutex_t lock; /* Lock for the structure */
++ pthread_cond_t
++ waiting_seqno, /* someone waiting on seqno */
++ waiting_read, /* someone waiting on readers */
++ waiting_write, /* someone waiting on writers */
++ waiting_refs; /* someone waiting on refs */
++
++ memory_object_t pager; /* Pager port */
++ mach_port_seqno_t seqno; /* Pager port sequence number */
++ mach_port_t pager_request; /* Request port */
++ mach_port_urefs_t request_refs; /* Request port user-refs */
++ mach_port_t pager_name; /* Name port */
++ mach_port_urefs_t name_refs; /* Name port user-refs */
++ boolean_t external; /* Is an external object? */
++
++ unsigned int readers; /* Reads in progress */
++ unsigned int writers; /* Writes in progress */
++
++ /* This is the reply port of an outstanding
++ default_pager_object_set_size call. */
++ mach_port_t lock_request;
++
++ unsigned int errors; /* Pageout error count */
++ struct dpager dpager; /* Actual pager */
++};
++typedef struct dstruct * default_pager_t;
++#define DEFAULT_PAGER_NULL ((default_pager_t)0)
++
++/*
++ * List of all pagers. A specific pager is
++ * found directly via its port, this list is
++ * only used for monitoring purposes by the
++ * default_pager_object* calls
++ */
++struct pager_port {
++ struct hurd_ihash htable;
++ pthread_mutex_t lock;
++ queue_head_t leak_queue;
++};
++
++/* The list of pagers. */
++extern struct pager_port all_pagers;
++
++#endif /* __MACH_DEFPAGER_PRIV_H__ */
+diff --git a/mach-defpager/setup.c b/mach-defpager/setup.c
+index 7c1afbc..e4ec8d9 100644
+--- a/mach-defpager/setup.c
++++ b/mach-defpager/setup.c
+@@ -25,8 +25,8 @@
+ #include <string.h>
+ #include <strings.h>
+
+-#include <default_pager.h>
+-#include <kalloc.h>
++#include "default_pager.h"
++#include "kalloc.h"
+
+ #include "file_io.h"
+ #include "default_pager_S.h"