diff options
author | James Clarke <jrtc27@jrtc27.com> | 2015-08-27 17:22:11 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2015-09-06 21:40:20 +0200 |
commit | 7a2c17fcbb789997421725d726340301ef35d84c (patch) | |
tree | ea51083985eaf4c5aad3d21716a77863dd241e0a /libpager/pager.h | |
parent | 918a8c2ce462cea65e3e7a614f19b4f5ae4ff1e1 (diff) |
Fix race condition in ext2fs when remounting
On some systems, ext2fs.static would regularly hang at startup, as a
race condition meant it would process paging requests while remounting.
To fix this, libpager has been altered to allow inhibiting and resuming
its worker threads, and ext2fs uses this to inhibit paging while
remounting.
* console/pager.c (pager_requests): New variable.
(user_pager_init): Updated call to pager_start_workers to use new
pager_requests variable.
* daemons/runsystem.sh: Removed artificial delay working around the race
condition.
* ext2fs/ext2fs.c (diskfs_reload_global_state): Call new
inhibit_ext2_pager and resume_ext2_pager functions, and leave sblock as
non-NULL so it will be munmapped.
* ext2fs/ext2fs.h (inhibit_ext2_pager,resume_ext2_pager): New functions.
* ext2fs/pager.c (file_pager_requests): New variable.
(create_disk_pager): Updated call to pager_start_workers to use new
file_pager_requests variable.
(inhibit_ext2_pager,resume_ext2_pager): New functions.
* fatfs/fatfs.h (inhibit_fat_pager,resume_fat_pager): New functions.
* fatfs/pager.c (file_pager_requests): New variable.
(create_fat_pager): Updated call to pager_start_workers to use new
file_pager_requests variable.
(inhibit_fat_pager,resume_fat_pager): New functions.
* libdiskfs/disk-pager.c (diskfs_disk_pager_requests): New variable.
(diskfs_start_disk_pager): Updated call to pager_start_workers to use
new diskfs_disk_pager_requests variable.
* libdiskfs/diskfs-pager.h (diskfs_disk_pager_requests): New variable.
* libpager/demuxer.c (struct pager_requests): Renamed struct requests to
struct pager_requests. Replaced queue with queue_in and queue_out
pointers. Added inhibit_wakeup field.
(pager_demuxer): Updated to use new queue_in/queue_out pointers. Only
wake up workers if not inhibited.
(worker_func): Updated to use new queue_in/queue_out pointers. Final
worker thread to sleep notifies the inhibit_wakeup condition variable.
(pager_start_workers): Added out parameter for the requests instance.
Allocate heap space shared by both queues. Initialise new inhibit_wakeup
condition.
(pager_inhibit_workers,pager_resume_workers): New functions.
* libpager/pager.h (struct pager_requests): Public forward definition.
(pager_start_workers): Added out parameter for the requests instance.
(pager_inhibit_workers,pager_resume_workers): New functions.
* libpager/queue.h (queue_empty): New function.
* storeio/pager.c (pager_requests): New variable.
(init_dev_paging): Updated call to pager_start_workers to use new
pager_requests variable.
Diffstat (limited to 'libpager/pager.h')
-rw-r--r-- | libpager/pager.h | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/libpager/pager.h b/libpager/pager.h index fe342388..df4db686 100644 --- a/libpager/pager.h +++ b/libpager/pager.h @@ -25,8 +25,32 @@ scope. */ struct user_pager_info; -/* Start the worker threads libpager uses to service requests. */ -error_t pager_start_workers (struct port_bucket *pager_bucket); +struct pager_requests; + +/* Start the worker threads libpager uses to service requests. If no + error is returned, *requests will be a valid pointer, else it will be + set to NULL. */ +error_t +pager_start_workers (struct port_bucket *pager_bucket, + struct pager_requests **requests); + +/* Inhibit the worker threads libpager uses to service requests, + blocking until all requests sent before this function is called have + finished. + Note that RPCs will not be inhibited, so new requests will + queue up, but will not be handled until the workers are resumed. If + RPCs should be inhibited as well, call ports_inhibit_bucket_rpcs with + the bucket used to create the workers before calling this. However, + inhibiting RPCs and not calling this is generally insufficient, as + libports is unaware of our internal worker pool, and will return once + all the RPCs have been queued, before they have been handled by a + worker thread. */ +error_t +pager_inhibit_workers (struct pager_requests *requests); + +/* Resume the worker threads libpager uses to service requests. */ +void +pager_resume_workers (struct pager_requests *requests); /* Create a new pager. The pager will have a port created for it (using libports, in BUCKET) and will be immediately ready |