diff options
Diffstat (limited to 'debian')
-rw-r--r-- | debian/patches/ext2fs-fix-remount.patch | 679 | ||||
-rw-r--r-- | debian/patches/fix-remount0001-yyy-fix-remount.patch | 144 | ||||
-rw-r--r-- | debian/patches/series | 2 |
3 files changed, 680 insertions, 145 deletions
diff --git a/debian/patches/ext2fs-fix-remount.patch b/debian/patches/ext2fs-fix-remount.patch new file mode 100644 index 00000000..120d8ae3 --- /dev/null +++ b/debian/patches/ext2fs-fix-remount.patch @@ -0,0 +1,679 @@ +Return-Path: <bug-hurd-bounces+4winter=informatik.uni-hamburg.de@gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on jade.jade-hamburg.de +X-Spam-Level: +X-Spam-Status: No, score=-3.1 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, + TVD_RCVD_SPACE_BRACKET,T_DKIM_INVALID,UNPARSEABLE_RELAY,URIBL_BLOCKED + autolearn=ham version=3.3.1 +Received: from mailhost.informatik.uni-hamburg.de [134.100.9.70] + by jade.jade-hamburg.de with IMAP (fetchmail-6.3.9-rc2) + for <teythoon@localhost> (single-drop); Thu, 23 Jul 2015 19:35:41 +0200 (CEST) +Received: from mailhost.informatik.uni-hamburg.de ([unix socket]) + by mailhost (Cyrus v2.3.18) with LMTPA; + Thu, 23 Jul 2015 19:34:57 +0200 +X-Sieve: CMU Sieve 2.3 +Received: by mailhost.informatik.uni-hamburg.de (Postfix) + id 25BA94D; Thu, 23 Jul 2015 19:34:57 +0200 (CEST) +Delivered-To: 4winter@informatik.uni-hamburg.de +Received: from localhost (localhost [127.0.0.1]) + by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 1B35E4C + for <4winter@informatik.uni-hamburg.de>; Thu, 23 Jul 2015 19:34:57 +0200 (CEST) +X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de +Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1]) + by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024) + with LMTP id VLxwzMHbQTir for <4winter@informatik.uni-hamburg.de>; + Thu, 23 Jul 2015 19:34:47 +0200 (CEST) +Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) + (using TLSv1 with cipher AES256-SHA (256/256 bits)) + (Client did not present a certificate) + by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPS id 2594F49 + for <4winter@informatik.uni-hamburg.de>; Thu, 23 Jul 2015 19:34:46 +0200 (CEST) +Received: from eggs.gnu.org ([2001:4830:134:3::10]:40942) + by lists.gnu.org with esmtp (Exim 4.71) + (envelope-from <jrtc27@jrtc27.com>) id 1ZIKO4-0007qU-QR + for bug-hurd@gnu.org; Thu, 23 Jul 2015 13:34:31 -0400 +Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) + (envelope-from <jrtc27@jrtc27.com>) id 1ZIKO0-0002Hh-GH + for bug-hurd@gnu.org; Thu, 23 Jul 2015 13:34:28 -0400 +Received: from mail-wi0-x232.google.com ([2a00:1450:400c:c05::232]:37033) + by eggs.gnu.org with esmtp (Exim 4.71) + (envelope-from <jrtc27@jrtc27.com>) id 1ZIKNz-0002Gs-Oc + for bug-hurd@gnu.org; Thu, 23 Jul 2015 13:34:24 -0400 +Received: by wibud3 with SMTP id ud3so3837098wib.0 + for <bug-hurd@gnu.org>; Thu, 23 Jul 2015 10:34:22 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jrtc27.com; s=google; + h=from:to:cc:subject:date:message-id; + bh=MZx4v6IKvYqW2p9EGv4bjIw37GP1x3TFNJaYlejzfE0=; + b=hkiuwxdVQ68sVd6CkTch33kqkgnZ9s4CH7SZzY38ggPING7qgOCDBCue6guf4GF2We + ff42ryixXeN4PfOBGuWFQV4wjPxHUvadTqU3AcVvOqbzpGaCnsoLyqbXF6XtTcEmLtGk + q54TByl6OjRYhlBc0l4pqkPZrMJdMwyLQLXZA= +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20130820; + h=x-gm-message-state:from:to:cc:subject:date:message-id; + bh=MZx4v6IKvYqW2p9EGv4bjIw37GP1x3TFNJaYlejzfE0=; + b=AGdApX6eRz/QjNXK/ayMLnE5fEP7sx450w2wQNw62XwbVOtmCbTnSuZ66PhQ7ZVBym + mVQk0f4HpgYXWcdXGgX8+lUScJPqhM+jgktgVaRtgNCVgMf4zcbrZJdc/xRb/4UgTAHy + 6A5v+Z3RwqrY5cqcRzDdVafP/zD1qE824WYd7fVM0Xkmeozr5rogNfEY6ug46n2THq1v + hfC9WA/CRUBoAwK3Ul7+6bj7BdXAlhIl6UWDGUebfMN7ov471mJfgEDmeh5blC8WNU5/ + dxdZ2zNPE47wHS1xkfjhXMKO7GJNgvaLUb2/jkTSV0i6b/gsGI2qzBtCXeoV7pqmhXzi + 3TTg== +X-Gm-Message-State: ALoCoQkhcH2D4+79mwdeHYjrBQLxsFBIYEmUR02QpaOfkNGg5bNh4sTRLCMAG2jwoxx8+W/WfW62 +X-Received: by 10.194.58.69 with SMTP id o5mr18159012wjq.22.1437672861959; + Thu, 23 Jul 2015 10:34:21 -0700 (PDT) +From: James Clarke <jrtc27@jrtc27.com> +To: bug-hurd@gnu.org +Subject: [PATCH v3] Fix race condition in ext2fs when remounting +Date: Thu, 23 Jul 2015 18:33:42 +0100 +Message-Id: <1437672822-99155-1-git-send-email-jrtc27@jrtc27.com> +X-Mailer: git-send-email 2.4.6 +X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address + (bad octet value). +X-Received-From: 2a00:1450:400c:c05::232 +Cc: James Clarke <jrtc27@jrtc27.com> +X-BeenThere: bug-hurd@gnu.org +X-Mailman-Version: 2.1.14 +Precedence: list +List-Id: Bug reports for the GNU Hurd <bug-hurd.gnu.org> +List-Unsubscribe: <https://lists.gnu.org/mailman/options/bug-hurd>, + <mailto:bug-hurd-request@gnu.org?subject=unsubscribe> +List-Archive: <http://lists.gnu.org/archive/html/bug-hurd> +List-Post: <mailto:bug-hurd@gnu.org> +List-Help: <mailto:bug-hurd-request@gnu.org?subject=help> +List-Subscribe: <https://lists.gnu.org/mailman/listinfo/bug-hurd>, + <mailto:bug-hurd-request@gnu.org?subject=subscribe> +Errors-To: bug-hurd-bounces+4winter=informatik.uni-hamburg.de@gnu.org +Sender: bug-hurd-bounces+4winter=informatik.uni-hamburg.de@gnu.org + +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. +--- + console/pager.c | 3 +- + daemons/runsystem.sh | 3 -- + ext2fs/ext2fs.c | 12 ++++- + ext2fs/ext2fs.h | 6 +++ + ext2fs/pager.c | 33 ++++++++++++- + fatfs/fatfs.h | 2 + + fatfs/pager.c | 33 ++++++++++++- + libdiskfs/disk-pager.c | 3 +- + libdiskfs/diskfs-pager.h | 1 + + libpager/demuxer.c | 119 ++++++++++++++++++++++++++++++++++++++++------- + libpager/pager.h | 28 ++++++++++- + libpager/queue.h | 8 ++++ + storeio/pager.c | 3 +- + 13 files changed, 227 insertions(+), 27 deletions(-) + +diff --git a/console/pager.c b/console/pager.c +index 5e13ba4..818e49d 100644 +--- a/console/pager.c ++++ b/console/pager.c +@@ -42,6 +42,7 @@ struct user_pager_info + + /* We need a separate bucket for the pager ports. */ + static struct port_bucket *pager_bucket; ++static struct pager_requests *pager_requests; + + + /* Implement the pager_clear_user_data callback from the pager library. */ +@@ -133,7 +134,7 @@ user_pager_init (void) + error (5, errno, "Cannot create pager bucket"); + + /* Start libpagers worker threads. */ +- err = pager_start_workers (pager_bucket); ++ err = pager_start_workers (pager_bucket, &pager_requests); + if (err) + error (5, err, "Cannot start pager worker threads"); + } +diff --git a/daemons/runsystem.sh b/daemons/runsystem.sh +index ae25a7d..5d0ad01 100644 +--- a/daemons/runsystem.sh ++++ b/daemons/runsystem.sh +@@ -118,9 +118,6 @@ esac + /hurd/mach-defpager + + # This is necessary to make stat / return the correct device ids. +-# Work around a race condition (probably in the root translator). +-for i in `seq 1 100000` ; do : ; done # XXX +- + fsysopts / --update --readonly + + # Finally, start the actual init. +diff --git a/ext2fs/ext2fs.c b/ext2fs/ext2fs.c +index d0fdfe7..03c9eed 100644 +--- a/ext2fs/ext2fs.c ++++ b/ext2fs/ext2fs.c +@@ -207,10 +207,20 @@ main (int argc, char **argv) + error_t + diskfs_reload_global_state () + { ++ error_t err; ++ + pokel_flush (&global_pokel); + pager_flush (diskfs_disk_pager, 1); +- sblock = NULL; ++ ++ /* libdiskfs is not responsible for inhibiting paging. */ ++ err = inhibit_ext2_pager (); ++ if (err) ++ return err; ++ + get_hypermetadata (); + map_hypermetadata (); ++ ++ resume_ext2_pager (); ++ + return 0; + } +diff --git a/ext2fs/ext2fs.h b/ext2fs/ext2fs.h +index 96d8e9d..a744685 100644 +--- a/ext2fs/ext2fs.h ++++ b/ext2fs/ext2fs.h +@@ -201,6 +201,12 @@ struct user_pager_info + /* Set up the disk pager. */ + void create_disk_pager (void); + ++/* Inhibit the disk pager. */ ++error_t inhibit_ext2_pager (void); ++ ++/* Resume the disk pager. */ ++void resume_ext2_pager (void); ++ + /* Call this when we should turn off caching so that unused memory object + ports get freed. */ + void drop_pager_softrefs (struct node *node); +diff --git a/ext2fs/pager.c b/ext2fs/pager.c +index b56c923..3e080f8 100644 +--- a/ext2fs/pager.c ++++ b/ext2fs/pager.c +@@ -34,6 +34,10 @@ struct port_bucket *disk_pager_bucket; + /* A ports bucket to hold file pager ports. */ + struct port_bucket *file_pager_bucket; + ++/* Stores a reference to the requests instance used by the file pager so its ++ worker threads can be inhibited and resumed. */ ++struct pager_requests *file_pager_requests; ++ + pthread_spinlock_t node_to_page_lock = PTHREAD_SPINLOCK_INITIALIZER; + + +@@ -1217,11 +1221,38 @@ create_disk_pager (void) + file_pager_bucket = ports_create_bucket (); + + /* Start libpagers worker threads. */ +- err = pager_start_workers (file_pager_bucket); ++ err = pager_start_workers (file_pager_bucket, &file_pager_requests); + if (err) + ext2_panic ("can't create libpager worker threads: %s", strerror (err)); + } + ++error_t ++inhibit_ext2_pager (void) ++{ ++ error_t err; ++ ++ /* The file pager can rely on the disk pager, so inhibit the file ++ pager first. */ ++ ++ err = pager_inhibit_workers (file_pager_requests); ++ if (err) ++ return err; ++ ++ err = pager_inhibit_workers (diskfs_disk_pager_requests); ++ /* We don't want only one pager disabled. */ ++ if (err) ++ pager_resume_workers (file_pager_requests); ++ ++ return err; ++} ++ ++void ++resume_ext2_pager (void) ++{ ++ pager_resume_workers (diskfs_disk_pager_requests); ++ pager_resume_workers (file_pager_requests); ++} ++ + /* Call this to create a FILE_DATA pager and return a send right. + NODE must be locked. */ + mach_port_t +diff --git a/fatfs/fatfs.h b/fatfs/fatfs.h +index 3c3d836..54c3426 100644 +--- a/fatfs/fatfs.h ++++ b/fatfs/fatfs.h +@@ -121,6 +121,8 @@ extern struct dirrect dr_root_node; + void drop_pager_softrefs (struct node *); + void allow_pager_softrefs (struct node *); + void create_fat_pager (void); ++error_t inhibit_fat_pager (void); ++void resume_fat_pager (void); + + void flush_node_pager (struct node *node); + +diff --git a/fatfs/pager.c b/fatfs/pager.c +index 10d1fc9..d255f29 100644 +--- a/fatfs/pager.c ++++ b/fatfs/pager.c +@@ -29,6 +29,10 @@ struct port_bucket *disk_pager_bucket; + /* A ports bucket to hold file pager ports. */ + struct port_bucket *file_pager_bucket; + ++/* Stores a reference to the requests instance used by the file pager so its ++ worker threads can be inhibited and resumed. */ ++struct pager_requests *file_pager_requests; ++ + /* Mapped image of the FAT. */ + void *fat_image; + +@@ -776,11 +780,38 @@ create_fat_pager (void) + file_pager_bucket = ports_create_bucket (); + + /* Start libpagers worker threads. */ +- err = pager_start_workers (file_pager_bucket); ++ err = pager_start_workers (file_pager_bucket, &file_pager_requests); + if (err) + error (2, err, "can't create libpager worker threads"); + } + ++error_t ++inhibit_fat_pager (void) ++{ ++ error_t err; ++ ++ /* The file pager can rely on the disk pager, so inhibit the file ++ pager first. */ ++ ++ err = pager_inhibit_workers (file_pager_requests); ++ if (err) ++ return err; ++ ++ err = pager_inhibit_workers (diskfs_disk_pager_requests); ++ /* We don't want only one pager disabled. */ ++ if (err) ++ pager_resume_workers (file_pager_requests); ++ ++ return err; ++} ++ ++void ++resume_fat_pager (void) ++{ ++ pager_resume_workers (diskfs_disk_pager_requests); ++ pager_resume_workers (file_pager_requests); ++} ++ + /* Call this to create a FILE_DATA pager and return a send right. + NODE must be locked. */ + mach_port_t +diff --git a/libdiskfs/disk-pager.c b/libdiskfs/disk-pager.c +index 008aa2d..33b109c 100644 +--- a/libdiskfs/disk-pager.c ++++ b/libdiskfs/disk-pager.c +@@ -24,6 +24,7 @@ + __thread struct disk_image_user *diskfs_exception_diu; + + struct pager *diskfs_disk_pager; ++struct requests *diskfs_disk_pager_requests; + + static void fault_handler (int sig, long int sigcode, struct sigcontext *scp); + static struct hurd_signal_preemptor preemptor = +@@ -43,7 +44,7 @@ diskfs_start_disk_pager (struct user_pager_info *upi, + mach_port_t disk_pager_port; + + /* Start libpagers worker threads. */ +- err = pager_start_workers (pager_bucket); ++ err = pager_start_workers (pager_bucket, &diskfs_disk_pager_requests); + if (err) + error (2, err, "creating pager worker threads failed"); + +diff --git a/libdiskfs/diskfs-pager.h b/libdiskfs/diskfs-pager.h +index a253069..db99f9ff 100644 +--- a/libdiskfs/diskfs-pager.h ++++ b/libdiskfs/diskfs-pager.h +@@ -40,6 +40,7 @@ extern void diskfs_start_disk_pager (struct user_pager_info *info, + size_t size, void **image); + + extern struct pager *diskfs_disk_pager; ++extern struct requests *diskfs_disk_pager_requests; + + struct disk_image_user + { +diff --git a/libpager/demuxer.c b/libpager/demuxer.c +index 4dd3cd8..59dd1c5 100644 +--- a/libpager/demuxer.c ++++ b/libpager/demuxer.c +@@ -60,7 +60,7 @@ request_inp (const struct request *r) + /* A worker. */ + struct worker + { +- struct requests *requests; /* our pagers request queue */ ++ struct pager_requests *requests; /* our pagers request queue */ + struct queue queue; /* other workers may delegate requests to us */ + unsigned long tag; /* tag of the object we are working on */ + }; +@@ -68,12 +68,18 @@ struct worker + /* This is the queue for incoming requests. A single thread receives + messages from the port set, looks the service routine up, and + enqueues the request here. */ +-struct requests ++struct pager_requests + { + struct port_bucket *bucket; +- struct queue queue; ++ /* Normally, both queues are the same. However, when the workers are ++ inhibited, a new queue_in is created, but queue_out is left as the ++ old value, so the workers drain queue_out but do not receive new ++ requests. */ ++ struct queue *queue_in; /* the queue to add to */ ++ struct queue *queue_out; /* the queue to take from */ + int asleep; + pthread_cond_t wakeup; ++ pthread_cond_t inhibit_wakeup; + pthread_mutex_t lock; + struct worker workers[WORKER_COUNT]; + }; +@@ -81,7 +87,7 @@ struct requests + /* Demultiplex a single message directed at a pager port; INP is the + message received; fill OUTP with the reply. */ + static int +-pager_demuxer (struct requests *requests, ++pager_demuxer (struct pager_requests *requests, + mach_msg_header_t *inp, + mach_msg_header_t *outp) + { +@@ -108,10 +114,10 @@ pager_demuxer (struct requests *requests, + + pthread_mutex_lock (&requests->lock); + +- queue_enqueue (&requests->queue, &r->item); ++ queue_enqueue (requests->queue_in, &r->item); + +- /* Awake worker. */ +- if (requests->asleep > 0) ++ /* Awake worker, but only if not inhibited. */ ++ if (requests->asleep > 0 && requests->queue_in == requests->queue_out) + pthread_cond_signal (&requests->wakeup); + + pthread_mutex_unlock (&requests->lock); +@@ -160,7 +166,7 @@ static void * + worker_func (void *arg) + { + struct worker *self = (struct worker *) arg; +- struct requests *requests = self->requests; ++ struct pager_requests *requests = self->requests; + struct request *r = NULL; + mig_reply_header_t reply_msg; + +@@ -186,9 +192,11 @@ worker_func (void *arg) + + get_request_locked: + /* ... get a request from the global queue instead. */ +- while ((r = queue_dequeue (&requests->queue)) == NULL) ++ while ((r = queue_dequeue (requests->queue_out)) == NULL) + { + requests->asleep += 1; ++ if (requests->asleep == WORKER_COUNT) ++ pthread_cond_broadcast (&requests->inhibit_wakeup); + pthread_cond_wait (&requests->wakeup, &requests->lock); + requests->asleep -= 1; + } +@@ -281,7 +289,7 @@ worker_func (void *arg) + static void * + service_paging_requests (void *arg) + { +- struct requests *requests = arg; ++ struct pager_requests *requests = arg; + + int demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outp) +@@ -298,27 +306,44 @@ service_paging_requests (void *arg) + + /* Start the worker threads libpager uses to service requests. */ + error_t +-pager_start_workers (struct port_bucket *pager_bucket) ++pager_start_workers (struct port_bucket *pager_bucket, ++ struct pager_requests **out_requests) + { + error_t err; + int i; + pthread_t t; +- struct requests *requests; ++ struct pager_requests *requests; ++ ++ assert (out_requests != NULL); + + requests = malloc (sizeof *requests); + if (requests == NULL) +- return ENOMEM; ++ { ++ err = ENOMEM; ++ goto done; ++ } + + requests->bucket = pager_bucket; + requests->asleep = 0; +- queue_init (&requests->queue); ++ ++ requests->queue_in = malloc (sizeof *requests->queue_in); ++ if (requests->queue_in == NULL) ++ { ++ err = ENOMEM; ++ goto done; ++ } ++ queue_init (requests->queue_in); ++ /* Until the workers are inhibited, both queues are the same. */ ++ requests->queue_out = requests->queue_in; ++ + pthread_cond_init (&requests->wakeup, NULL); ++ pthread_cond_init (&requests->inhibit_wakeup, NULL); + pthread_mutex_init (&requests->lock, NULL); + + /* Make a thread to service paging requests. */ + err = pthread_create (&t, NULL, service_paging_requests, requests); + if (err) +- return err; ++ goto done; + pthread_detach (t); + + for (i = 0; i < WORKER_COUNT; i++) +@@ -329,9 +354,71 @@ pager_start_workers (struct port_bucket *pager_bucket) + + err = pthread_create (&t, NULL, &worker_func, &requests->workers[i]); + if (err) +- return err; ++ goto done; + pthread_detach (t); + } + ++done: ++ if (err) ++ *out_requests = NULL; ++ else ++ *out_requests = requests; ++ + return err; + } ++ ++error_t ++pager_inhibit_workers (struct pager_requests *requests) ++{ ++ error_t err = 0; ++ ++ pthread_mutex_lock (&requests->lock); ++ ++ /* Check the workers are not already inhibited. */ ++ assert (requests->queue_out == requests->queue_in); ++ ++ /* Any new paging requests will go into a new queue. */ ++ struct queue *new_queue = malloc (sizeof *new_queue); ++ if (new_queue == NULL) ++ { ++ err = ENOMEM; ++ goto done_locked; ++ } ++ queue_init (new_queue); ++ requests->queue_in = new_queue; ++ ++ /* Wait until all the workers are asleep and the queue has been ++ drained. All individual worker queues must have been drained, as ++ they are populated while the relevant worker is still running, and ++ it will always drain its personal queue before sleeping. ++ Check that the queue is empty, since it's possible that a request ++ came in, was queued and a worker was signalled but the lock was ++ acquired here before the worker woke up. */ ++ while (requests->asleep < WORKER_COUNT || !queue_empty(requests->queue_out)) ++ pthread_cond_wait (&requests->inhibit_wakeup, &requests->lock); ++ ++done_locked: ++ pthread_mutex_unlock (&requests->lock); ++ return err; ++} ++ ++void ++pager_resume_workers (struct pager_requests *requests) ++{ ++ pthread_mutex_lock (&requests->lock); ++ ++ /* Check the workers are inhibited. */ ++ assert (requests->queue_out != requests->queue_in); ++ assert (requests->asleep == WORKER_COUNT); ++ assert (queue_empty(requests->queue_out)); ++ ++ /* The queue has been drained and will no longer be used. */ ++ free (requests->queue_out); ++ requests->queue_out = requests->queue_in; ++ ++ /* We need to wake up all workers, as there could be multiple requests ++ in the new queue. */ ++ pthread_cond_broadcast (&requests->wakeup); ++ ++ pthread_mutex_unlock (&requests->lock); ++} +diff --git a/libpager/pager.h b/libpager/pager.h +index fe34238..df4db68 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 +diff --git a/libpager/queue.h b/libpager/queue.h +index d3cf738..abcd3b9 100644 +--- a/libpager/queue.h ++++ b/libpager/queue.h +@@ -19,6 +19,8 @@ + 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/>. */ + ++#include <stdbool.h> ++ + /* A FIFO queue with constant-time enqueue and dequeue operations. */ + struct item { + struct item *next; +@@ -59,3 +61,9 @@ queue_dequeue (struct queue *q) + r->next = NULL; + return r; + } ++ ++static inline bool ++queue_empty (struct queue *q) ++{ ++ return q->head == NULL; ++} +diff --git a/storeio/pager.c b/storeio/pager.c +index c260d73..f8f59cd 100644 +--- a/storeio/pager.c ++++ b/storeio/pager.c +@@ -142,6 +142,7 @@ pager_clear_user_data (struct user_pager_info *upi) + } + + static struct port_bucket *pager_port_bucket = 0; ++static struct pager_requests *pager_requests; + + /* Initialize paging for this device. */ + static void +@@ -160,7 +161,7 @@ init_dev_paging () + pager_port_bucket = ports_create_bucket (); + + /* Start libpagers worker threads. */ +- err = pager_start_workers (pager_port_bucket); ++ err = pager_start_workers (pager_port_bucket, &pager_requests); + if (err) + { + errno = err; +-- +2.4.6 + + diff --git a/debian/patches/fix-remount0001-yyy-fix-remount.patch b/debian/patches/fix-remount0001-yyy-fix-remount.patch deleted file mode 100644 index 87bda76f..00000000 --- a/debian/patches/fix-remount0001-yyy-fix-remount.patch +++ /dev/null @@ -1,144 +0,0 @@ -From a56055334da0127cc3e88f1529704b80a61e93a2 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Tue, 14 Jul 2015 14:28:57 +0200 -Subject: [PATCH hurd] yyy fix remount - ---- - ext2fs/ext2fs.c | 1 - - ext2fs/hyper.c | 53 +++++++++++++++++++++++++++++------------------------ - 2 files changed, 29 insertions(+), 25 deletions(-) - -diff --git a/ext2fs/ext2fs.c b/ext2fs/ext2fs.c -index d0fdfe7..f1ec937 100644 ---- a/ext2fs/ext2fs.c -+++ b/ext2fs/ext2fs.c -@@ -209,7 +209,6 @@ diskfs_reload_global_state () - { - pokel_flush (&global_pokel); - pager_flush (diskfs_disk_pager, 1); -- sblock = NULL; - get_hypermetadata (); - map_hypermetadata (); - return 0; -diff --git a/ext2fs/hyper.c b/ext2fs/hyper.c -index 5f288bf..afbbbc2 100644 ---- a/ext2fs/hyper.c -+++ b/ext2fs/hyper.c -@@ -60,24 +60,22 @@ get_hypermetadata (void) - { - error_t err; - size_t read = 0; -- -- if (sblock != NULL) -- munmap (sblock, SBLOCK_SIZE); -+ struct ext2_super_block *old_sblock, *new_sblock; - - err = store_read (store, SBLOCK_OFFS >> store->log2_block_size, -- SBLOCK_SIZE, (void **)&sblock, &read); -+ SBLOCK_SIZE, (void **)&new_sblock, &read); - if (err || read != SBLOCK_SIZE) - ext2_panic ("Cannot read hypermetadata"); - -- if (sblock->s_magic != EXT2_SUPER_MAGIC -+ if (new_sblock->s_magic != EXT2_SUPER_MAGIC - #ifdef EXT2FS_PRE_02B_COMPAT -- && sblock->s_magic != EXT2_PRE_02B_MAGIC -+ && new_sblock->s_magic != EXT2_PRE_02B_MAGIC - #endif - ) - ext2_panic ("bad magic number %#x (should be %#x)", -- sblock->s_magic, EXT2_SUPER_MAGIC); -+ new_sblock->s_magic, EXT2_SUPER_MAGIC); - -- log2_block_size = EXT2_MIN_BLOCK_LOG_SIZE + sblock->s_log_block_size; -+ log2_block_size = EXT2_MIN_BLOCK_LOG_SIZE + new_sblock->s_log_block_size; - block_size = 1 << log2_block_size; - - if (block_size > EXT2_MAX_BLOCK_SIZE) -@@ -97,10 +95,10 @@ get_hypermetadata (void) - ext2_panic ("block size %d isn't a power-of-two multiple of 512!", - block_size); - -- if ((store->size >> log2_block_size) < sblock->s_blocks_count) -+ if ((store->size >> log2_block_size) < new_sblock->s_blocks_count) - ext2_panic ("disk size (%qd bytes) too small; superblock says we need %qd", - (long long int) store->size, -- (long long int) sblock->s_blocks_count << log2_block_size); -+ (long long int) new_sblock->s_blocks_count << log2_block_size); - if (log2_dev_blocks_per_fs_block != 0 - && (store->size & ((1 << log2_dev_blocks_per_fs_block) - 1)) != 0) - ext2_warning ("%Ld (%zd byte) device blocks " -@@ -109,42 +107,42 @@ get_hypermetadata (void) - store->block_size, block_size); - - /* Set these handy variables. */ -- inodes_per_block = block_size / EXT2_INODE_SIZE (sblock); -+ inodes_per_block = block_size / EXT2_INODE_SIZE (new_sblock); - -- frag_size = EXT2_MIN_FRAG_SIZE << sblock->s_log_frag_size; -+ frag_size = EXT2_MIN_FRAG_SIZE << new_sblock->s_log_frag_size; - if (frag_size) - frags_per_block = block_size / frag_size; - else - ext2_panic ("frag size is zero!"); - -- if (sblock->s_rev_level > EXT2_GOOD_OLD_REV) -+ if (new_sblock->s_rev_level > EXT2_GOOD_OLD_REV) - { -- if (sblock->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) -+ if (new_sblock->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) - ext2_panic ("could not mount because of unsupported optional features" - " (0x%x)", -- sblock->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP); -- if (sblock->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP) -+ new_sblock->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP); -+ if (new_sblock->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP) - { - ext2_warning ("mounted readonly because of" - " unsupported optional features (0x%x)", -- sblock->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP); -+ new_sblock->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP); - diskfs_readonly = 1; - } -- if (sblock->s_inode_size != EXT2_GOOD_OLD_INODE_SIZE) -- ext2_panic ("inode size %d isn't supported", sblock->s_inode_size); -+ if (new_sblock->s_inode_size != EXT2_GOOD_OLD_INODE_SIZE) -+ ext2_panic ("inode size %d isn't supported", new_sblock->s_inode_size); - } - - groups_count = -- ((sblock->s_blocks_count - sblock->s_first_data_block + -- sblock->s_blocks_per_group - 1) -- / sblock->s_blocks_per_group); -+ ((new_sblock->s_blocks_count - new_sblock->s_first_data_block + -+ new_sblock->s_blocks_per_group - 1) -+ / new_sblock->s_blocks_per_group); - -- itb_per_group = sblock->s_inodes_per_group / inodes_per_block; -+ itb_per_group = new_sblock->s_inodes_per_group / inodes_per_block; - desc_per_block = block_size / sizeof (struct ext2_group_desc); - addr_per_block = block_size / sizeof (block_t); - db_per_group = (groups_count + desc_per_block - 1) / desc_per_block; - -- ext2fs_clean = sblock->s_state & EXT2_VALID_FS; -+ ext2fs_clean = new_sblock->s_state & EXT2_VALID_FS; - if (! ext2fs_clean) - { - ext2_warning ("FILESYSTEM NOT UNMOUNTED CLEANLY; PLEASE fsck"); -@@ -163,6 +161,13 @@ get_hypermetadata (void) - zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0); - assert (zeroblock != (vm_address_t) MAP_FAILED); - } -+ -+ /* Switcherino! */ -+ old_sblock = sblock; -+ sblock = new_sblock; -+ __sync_synchronize (); -+ if (old_sblock != NULL) -+ munmap (old_sblock, SBLOCK_SIZE); - } - - static struct ext2_super_block *mapped_sblock; --- -2.1.4 - diff --git a/debian/patches/series b/debian/patches/series index 95122f1e..37f752f5 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,4 @@ +ext2fs-fix-remount.patch libexec.patch diskfs_no_inherit_dir_group.patch @@ -68,4 +69,3 @@ introspection0005-libdiskfs-annotate-objects-managed-by-libports.patch introspection0006-libpager-annotate-objects-managed-by-libports.patch introspection0007-ext2fs-annotate-objects-managed-by-libports.patch introspection0008-utils-rpctrace-support-attaching-to-servers.patch -fix-remount0001-yyy-fix-remount.patch |