summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext2fs/pager.c87
1 files changed, 62 insertions, 25 deletions
diff --git a/ext2fs/pager.c b/ext2fs/pager.c
index 9116b8c7..017efcca 100644
--- a/ext2fs/pager.c
+++ b/ext2fs/pager.c
@@ -21,14 +21,18 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <error.h>
#include <hurd/store.h>
#include "ext2fs.h"
/* XXX */
#include "../libpager/priv.h"
-/* A ports bucket to hold pager ports. */
-struct port_bucket *pager_bucket;
+/* A ports bucket to hold disk pager ports. */
+struct port_bucket *disk_pager_bucket;
+
+/* A ports bucket to hold file pager ports. */
+struct port_bucket *file_pager_bucket;
pthread_spinlock_t node_to_page_lock = PTHREAD_SPINLOCK_INITIALIZER;
@@ -1188,21 +1192,56 @@ disk_cache_block_is_ref (block_t block)
return ref;
}
-/* Create the DISK pager. */
+/* A top-level function for the paging thread that just services paging
+ requests. */
+static void *
+service_paging_requests (void *arg)
+{
+ struct port_bucket *pager_bucket = arg;
+ ports_manage_port_operations_multithread (pager_bucket,
+ pager_demuxer,
+ 1000,
+ 0,
+ NULL);
+ /* Not reached. */
+ return NULL;
+}
+
+/* Create the disk pager, and the file pager. */
void
create_disk_pager (void)
{
+ pthread_t thread;
+ pthread_attr_t attr;
+ error_t err;
+
+ /* The disk pager. */
struct user_pager_info *upi = malloc (sizeof (struct user_pager_info));
if (!upi)
ext2_panic ("can't create disk pager: %s", strerror (errno));
upi->type = DISK;
- pager_bucket = ports_create_bucket ();
+ disk_pager_bucket = ports_create_bucket ();
get_hypermetadata ();
disk_cache_blocks = DISK_CACHE_BLOCKS;
disk_cache_size = disk_cache_blocks << log2_block_size;
- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 1,
+ diskfs_start_disk_pager (upi, disk_pager_bucket, MAY_CACHE, 1,
disk_cache_size, &disk_cache);
disk_cache_init ();
+
+ /* The file pager. */
+ file_pager_bucket = ports_create_bucket ();
+
+#define STACK_SIZE (64 * 1024)
+ pthread_attr_init (&attr);
+ pthread_attr_setstacksize (&attr, STACK_SIZE);
+#undef STACK_SIZE
+
+ /* Make a thread to service file paging requests. */
+ err = pthread_create (&thread, &attr,
+ service_paging_requests, file_pager_bucket);
+ if (err)
+ error (2, err, "pthread_create");
+ pthread_detach (thread);
}
/* Call this to create a FILE_DATA pager and return a send right.
@@ -1241,7 +1280,7 @@ diskfs_get_filemap (struct node *node, vm_prot_t prot)
upi->max_prot = prot;
diskfs_nref_light (node);
node->dn->pager =
- pager_create (upi, pager_bucket, MAY_CACHE,
+ pager_create (upi, file_pager_bucket, MAY_CACHE,
MEMORY_OBJECT_COPY_DELAY, 0);
if (node->dn->pager == 0)
{
@@ -1324,14 +1363,13 @@ diskfs_shutdown_pager ()
error_t shutdown_one (void *v_p)
{
struct pager *p = v_p;
- if (p != diskfs_disk_pager)
- pager_shutdown (p);
+ pager_shutdown (p);
return 0;
}
write_all_disknodes ();
- ports_bucket_iterate (pager_bucket, shutdown_one);
+ ports_bucket_iterate (file_pager_bucket, shutdown_one);
/* Sync everything on the the disk pager. */
sync_global (1);
@@ -1347,13 +1385,12 @@ diskfs_sync_everything (int wait)
error_t sync_one (void *v_p)
{
struct pager *p = v_p;
- if (p != diskfs_disk_pager)
- pager_sync (p, wait);
+ pager_sync (p, wait);
return 0;
}
write_all_disknodes ();
- ports_bucket_iterate (pager_bucket, sync_one);
+ ports_bucket_iterate (file_pager_bucket, sync_one);
/* Do things on the the disk pager. */
sync_global (wait);
@@ -1372,7 +1409,8 @@ disable_caching ()
/* Loop through the pagers and turn off caching one by one,
synchronously. That should cause termination of each pager. */
- ports_bucket_iterate (pager_bucket, block_cache);
+ ports_bucket_iterate (disk_pager_bucket, block_cache);
+ ports_bucket_iterate (file_pager_bucket, block_cache);
}
static void
@@ -1400,7 +1438,8 @@ enable_caching ()
return 0;
}
- ports_bucket_iterate (pager_bucket, enable_cache);
+ ports_bucket_iterate (disk_pager_bucket, enable_cache);
+ ports_bucket_iterate (file_pager_bucket, enable_cache);
}
/* Tell diskfs if there are pagers exported, and if none, then
@@ -1408,7 +1447,7 @@ enable_caching ()
int
diskfs_pager_users ()
{
- int npagers = ports_count_bucket (pager_bucket);
+ int npagers = ports_count_bucket (file_pager_bucket);
if (npagers <= 1)
return 0;
@@ -1421,8 +1460,8 @@ diskfs_pager_users ()
immediately. XXX */
sleep (1);
- npagers = ports_count_bucket (pager_bucket);
- if (npagers <= 1)
+ npagers = ports_count_bucket (file_pager_bucket);
+ if (npagers == 0)
return 0;
/* Darn, there are actual honest users. Turn caching back on,
@@ -1430,7 +1469,7 @@ diskfs_pager_users ()
enable_caching ();
}
- ports_enable_bucket (pager_bucket);
+ ports_enable_bucket (file_pager_bucket);
return 1;
}
@@ -1441,17 +1480,15 @@ vm_prot_t
diskfs_max_user_pager_prot ()
{
vm_prot_t max_prot = 0;
- int npagers = ports_count_bucket (pager_bucket);
+ int npagers = ports_count_bucket (file_pager_bucket);
- if (npagers > 1)
- /* More than just the disk pager. */
+ if (npagers > 0)
{
error_t add_pager_max_prot (void *v_p)
{
struct pager *p = v_p;
struct user_pager_info *upi = pager_get_upi (p);
- if (upi->type == FILE_DATA)
- max_prot |= upi->max_prot;
+ max_prot |= upi->max_prot;
/* Stop iterating if MAX_PROT is as filled as it's going to get. */
return max_prot == (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
}
@@ -1462,12 +1499,12 @@ diskfs_max_user_pager_prot ()
immediately. XXX */
sleep (1);
- ports_bucket_iterate (pager_bucket, add_pager_max_prot);
+ ports_bucket_iterate (file_pager_bucket, add_pager_max_prot);
enable_caching ();
}
- ports_enable_bucket (pager_bucket);
+ ports_enable_bucket (file_pager_bucket);
return max_prot;
}