aboutsummaryrefslogtreecommitdiff
path: root/libdiskfs/disk-pager.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdiskfs/disk-pager.c')
-rw-r--r--libdiskfs/disk-pager.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/libdiskfs/disk-pager.c b/libdiskfs/disk-pager.c
index 9ae2a2a5..fefd2ef4 100644
--- a/libdiskfs/disk-pager.c
+++ b/libdiskfs/disk-pager.c
@@ -1,5 +1,5 @@
/* Map the disk image and handle faults accessing it.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996,97,99,2001,02 Free Software Foundation, Inc.
Written by Roland McGrath.
This program is free software; you can redistribute it and/or
@@ -21,56 +21,53 @@
#include <hurd/sigpreempt.h>
#include <error.h>
-struct pager *disk_pager;
-void *disk_image;
-extern struct port_bucket *pager_bucket;
+struct pager *diskfs_disk_pager;
static void fault_handler (int sig, long int sigcode, struct sigcontext *scp);
-static struct hurd_signal_preempter preempter =
+static struct hurd_signal_preemptor preemptor =
{
signals: sigmask (SIGSEGV) | sigmask (SIGBUS),
- preempter: NULL,
+ preemptor: NULL,
handler: (sighandler_t) &fault_handler,
};
-
/* A top-level function for the paging thread that just services paging
requests. */
static void
-service_paging_requests (any_t foo __attribute__ ((unused)))
+service_paging_requests (any_t arg)
{
+ struct port_bucket *pager_bucket = arg;
for (;;)
- ports_manage_port_operations_multithread (pager_bucket, pager_demuxer,
- 1000 * 60 * 2, 1000 * 60 * 10,
- 1, MACH_PORT_NULL);
+ ports_manage_port_operations_multithread (pager_bucket,
+ pager_demuxer,
+ 1000 * 60 * 2,
+ 1000 * 60 * 10, 0);
}
void
-disk_pager_setup (struct user_pager_info *upi, int may_cache)
+diskfs_start_disk_pager (struct user_pager_info *upi,
+ struct port_bucket *pager_bucket, int may_cache,
+ size_t size, void **image)
{
error_t err;
mach_port_t disk_pager_port;
- if (! pager_bucket)
- pager_bucket = ports_create_bucket ();
-
/* Make a thread to service paging requests. */
cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests,
- (any_t) 0));
+ (any_t)pager_bucket));
/* Create the pager. */
- disk_pager = pager_create (upi, pager_bucket,
- may_cache, MEMORY_OBJECT_COPY_NONE);
- assert (disk_pager);
+ diskfs_disk_pager = pager_create (upi, pager_bucket,
+ may_cache, MEMORY_OBJECT_COPY_NONE);
+ assert (diskfs_disk_pager);
/* Get a port to the disk pager. */
- disk_pager_port = pager_get_port (disk_pager);
+ disk_pager_port = pager_get_port (diskfs_disk_pager);
mach_port_insert_right (mach_task_self (), disk_pager_port, disk_pager_port,
MACH_MSG_TYPE_MAKE_SEND);
/* Now map the disk image. */
- err = vm_map (mach_task_self (), (vm_address_t *)&disk_image,
- diskfs_device_size << diskfs_log2_device_block_size,
+ err = vm_map (mach_task_self (), (vm_address_t *)image, size,
0, 1, disk_pager_port, 0, 0,
VM_PROT_READ | (diskfs_readonly ? 0 : VM_PROT_WRITE),
VM_PROT_READ | VM_PROT_WRITE,
@@ -78,11 +75,10 @@ disk_pager_setup (struct user_pager_info *upi, int may_cache)
if (err)
error (2, err, "cannot vm_map whole disk");
- /* Set up the signal preempter to catch faults on the disk image. */
- preempter.first = (vm_address_t) disk_image;
- preempter.last = ((vm_address_t) disk_image +
- (diskfs_device_size << diskfs_log2_device_block_size));
- hurd_preempt_signals (&preempter);
+ /* Set up the signal preemptor to catch faults on the disk image. */
+ preemptor.first = (vm_address_t) *image;
+ preemptor.last = ((vm_address_t) *image + size);
+ hurd_preempt_signals (&preemptor);
/* We have the mapping; we no longer need the send right. */
mach_port_deallocate (mach_task_self (), disk_pager_port);
@@ -94,14 +90,28 @@ fault_handler (int sig, long int sigcode, struct sigcontext *scp)
jmp_buf *env = cthread_data (cthread_self ());
error_t err;
- assert (env && "unexpected fault on disk image");
+#ifndef NDEBUG
+ if (!env)
+ {
+ error (0, 0,
+ "BUG: unexpected fault on disk image (%d, %#lx) in [%#lx,%#lx)"
+ " eip %#zx err %#x",
+ sig, sigcode,
+ preemptor.first, preemptor.last,
+ scp->sc_pc, scp->sc_error);
+ assert (scp->sc_error == EKERN_MEMORY_ERROR);
+ err = pager_get_error (diskfs_disk_pager, sigcode);
+ assert (err);
+ assert_perror (err);
+ }
+#endif
/* Clear the record, since the faulting thread will not. */
cthread_set_data (cthread_self (), 0);
/* Fetch the error code from the pager. */
assert (scp->sc_error == EKERN_MEMORY_ERROR);
- err = pager_get_error (disk_pager, sigcode);
+ err = pager_get_error (diskfs_disk_pager, sigcode);
assert (err);
/* Make `diskfault_catch' return the error code. */