diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-09-16 00:17:43 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-09-16 00:45:12 +0000 |
commit | cfcd7bc73ec91283b700d48b36b2ed68974d4376 (patch) | |
tree | 1ac294e44489eb70c77c09e45641ea07899cd6d3 /debian/patches | |
parent | f430f620dfa5ec76c9f751d99d249750fb78714e (diff) | |
parent | ebb437fb4b27fa565b9aebb05cda1e9db4ec17ff (diff) |
Merge branch 'upstream-merged'
Diffstat (limited to 'debian/patches')
-rw-r--r-- | debian/patches/exec_filename_exec.patch | 23 | ||||
-rw-r--r-- | debian/patches/exec_filename_fs.patch | 6 | ||||
-rw-r--r-- | debian/patches/ext2fs_large_stores.patch | 2274 | ||||
-rw-r--r-- | debian/patches/ext2fs_large_stores_pthread.patch | 344 | ||||
-rw-r--r-- | debian/patches/mount-f.patch | 88 | ||||
-rw-r--r-- | debian/patches/mount-ignore-mounted-all.patch | 32 | ||||
-rw-r--r-- | debian/patches/mount-n.patch | 37 | ||||
-rw-r--r-- | debian/patches/mount-remount.patch | 67 | ||||
-rw-r--r-- | debian/patches/mount-t-auto.patch | 86 | ||||
-rw-r--r-- | debian/patches/mount-test-opts.patch | 209 | ||||
-rw-r--r-- | debian/patches/procfs-default.patch | 48 | ||||
-rw-r--r-- | debian/patches/procfs-get-options.patch | 73 | ||||
-rw-r--r-- | debian/patches/procfs-update.patch | 143 | ||||
-rw-r--r-- | debian/patches/proxy-defpager.diff | 4 | ||||
-rw-r--r-- | debian/patches/series | 16 | ||||
-rw-r--r-- | debian/patches/sutils-multiple-none.patch | 40 | ||||
-rw-r--r-- | debian/patches/sutils-types.patch | 150 | ||||
-rw-r--r-- | debian/patches/umount.patch | 382 |
18 files changed, 16 insertions, 4006 deletions
diff --git a/debian/patches/exec_filename_exec.patch b/debian/patches/exec_filename_exec.patch index 41b66a82..1e937b45 100644 --- a/debian/patches/exec_filename_exec.patch +++ b/debian/patches/exec_filename_exec.patch @@ -134,15 +134,6 @@ Index: hurd-debian/exec/exec.c if (! protid) return EOPNOTSUPP; -@@ -2111,7 +2151,7 @@ - trivfs_protid_portclasses[0]); - if (protid) - { -- err = do_exec (file, oldtask, 0, -+ err = do_exec (file, oldtask, 0, filename, - argv, argvlen, argv_copy, - envp, envplen, envp_copy, - dtable, dtablesize, dtable_copy, @@ -2158,7 +2198,7 @@ /* There were no user-specified exec servers, or none of them could be found. */ @@ -304,14 +295,14 @@ Index: hurd-debian/exec/Makefile --- hurd-debian.orig/exec/Makefile 2012-06-03 17:08:36.000000000 +0000 +++ hurd-debian/exec/Makefile 2012-06-05 03:39:06.000000000 +0000 @@ -23,7 +23,7 @@ - SRCS = exec.c main.c hashexec.c hostarch.c \ - $(gzip-sources) $(bzip2-sources) + + SRCS = exec.c main.c hashexec.c hostarch.c OBJS = main.o hostarch.o exec.o hashexec.o \ -- execServer.o exec_startupServer.o \ -+ execServer.o exec_startupServer.o exec_experimentalServer.o \ - $(gzip-objects) $(bzip2-objects) - gzip-sources = unzip.c util.c inflate.c - gzip-objects = $(gzip-sources:%.c=%.o) +- execServer.o exec_startupServer.o ++ execServer.o exec_startupServer.o exec_experimentalServer.o + + target = exec + #targets = exec exec.static @@ -37,6 +37,7 @@ OTHERLIBS = -lpthread diff --git a/debian/patches/exec_filename_fs.patch b/debian/patches/exec_filename_fs.patch index a4b5589a..b92a13a5 100644 --- a/debian/patches/exec_filename_fs.patch +++ b/debian/patches/exec_filename_fs.patch @@ -218,8 +218,8 @@ Index: hurd-debian/init/init.c /* Start and maintain hurd core servers and system run state Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -- 2005, 2008 Free Software Foundation, Inc. -+ 2005, 2008, 2010 Free Software Foundation, Inc. +- 2005, 2008, 2013 Free Software Foundation, Inc. ++ 2005, 2008, 2010, 2013 Free Software Foundation, Inc. This file is part of the GNU Hurd. The GNU Hurd is free software; you can redistribute it and/or modify @@ -336,9 +336,9 @@ Index: hurd-debian/init/init.c + default_ints, INIT_INT_MAX, + NULL, 0, NULL, 0); + + proc_mark_important (default_ports[INIT_PORT_PROC]); mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]); mach_port_deallocate (mach_task_self (), file); - if (err) Index: hurd-debian/libdiskfs/boot-start.c =================================================================== --- hurd-debian.orig/libdiskfs/boot-start.c 2013-06-19 23:32:37.000000000 +0000 diff --git a/debian/patches/ext2fs_large_stores.patch b/debian/patches/ext2fs_large_stores.patch deleted file mode 100644 index f65ec760..00000000 --- a/debian/patches/ext2fs_large_stores.patch +++ /dev/null @@ -1,2274 +0,0 @@ -Support for >2GB volumes - -XXX: this adds a parameter to pager_create and diskfs_start_disk_pager ---- - console/pager.c | 10 - ext2fs/balloc.c | 57 +++-- - ext2fs/ext2_fs.h | 3 - ext2fs/ext2fs.c | 8 - ext2fs/ext2fs.h | 145 +++++++++++-- - ext2fs/getblk.c | 31 +- - ext2fs/hyper.c | 34 ++- - ext2fs/ialloc.c | 41 +++ - ext2fs/inode.c | 58 +++-- - ext2fs/pager.c | 497 +++++++++++++++++++++++++++++++++++++++++++---- - ext2fs/pokel.c | 41 +++ - ext2fs/truncate.c | 11 - - fatfs/pager.c | 11 - - isofs/pager.c | 12 - - libdiskfs/disk-pager.c | 6 - libdiskfs/diskfs-pager.h | 3 - libpager/data-request.c | 17 - - libpager/data-return.c | 78 +++++-- - libpager/pager-create.c | 4 - libpager/pager.h | 29 ++ - libpager/priv.h | 1 - storeio/pager.c | 9 - tmpfs/pager-stubs.c | 8 - ufs/pager.c | 11 - - 24 files changed, 940 insertions(+), 185 deletions(-) - -Index: hurd-debian/console/pager.c -=================================================================== ---- hurd-debian.orig/console/pager.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/console/pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -94,6 +94,14 @@ - } - - -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page) -+{ -+ assert (!"unrequested notification on eviction"); -+} -+ -+ - /* Tell how big the file is. */ - error_t - pager_report_extent (struct user_pager_info *upi, -@@ -159,7 +167,7 @@ - - /* XXX Are the values 1 and MEMORY_OBJECT_COPY_DELAY correct? */ - user_pager->pager = pager_create (upi, pager_bucket, -- 1, MEMORY_OBJECT_COPY_DELAY); -+ 1, MEMORY_OBJECT_COPY_DELAY, 0); - if (!user_pager->pager) - { - free (upi); -Index: hurd-debian/ext2fs/balloc.c -=================================================================== ---- hurd-debian.orig/ext2fs/balloc.c 2012-07-10 01:36:36.000000000 +0000 -+++ hurd-debian/ext2fs/balloc.c 2012-07-10 01:39:22.000000000 +0000 -@@ -92,7 +92,7 @@ - block, count); - } - gdp = group_desc (block_group); -- bh = bptr (gdp->bg_block_bitmap); -+ bh = disk_cache_block_ref (gdp->bg_block_bitmap); - - if (in_range (gdp->bg_block_bitmap, block, gcount) || - in_range (gdp->bg_inode_bitmap, block, gcount) || -@@ -114,6 +114,7 @@ - } - - record_global_poke (bh); -+ disk_cache_block_ref_ptr (gdp); - record_global_poke (gdp); - - block += gcount; -@@ -139,7 +140,7 @@ - block_t prealloc_goal, - block_t *prealloc_count, block_t *prealloc_block) - { -- char *bh; -+ char *bh = 0; - char *p, *r; - int i, j, k, tmp; - unsigned long lmap; -@@ -164,9 +165,10 @@ - - ext2_debug ("goal=%u", goal); - --repeat: -+ repeat: -+ assert (! bh); - /* -- * First, test whether the goal block is free. -+ * First, test whether the goal block is free. - */ - if (goal < sblock->s_first_data_block || goal >= sblock->s_blocks_count) - goal = sblock->s_first_data_block; -@@ -179,7 +181,7 @@ - if (j) - goal_attempts++; - #endif -- bh = bptr (gdp->bg_block_bitmap); -+ bh = disk_cache_block_ref (gdp->bg_block_bitmap); - - ext2_debug ("goal is at %d:%d", i, j); - -@@ -194,8 +196,8 @@ - if (j) - { - /* -- * The goal was occupied; search forward for a free -- * block within the next 32 blocks -+ * The goal was occupied; search forward for a free -+ * block within the next 32 blocks - */ - if ((j & 31) == 31) - lmap = 0; -@@ -245,13 +247,16 @@ - j = k; - goto got_block; - } -+ -+ disk_cache_block_deref (bh); -+ bh = 0; - } - - ext2_debug ("bit not found in block group %d", i); - - /* -- * Now search the rest of the groups. We assume that -- * i and gdp correctly point to the last group visited. -+ * Now search the rest of the groups. We assume that -+ * i and gdp correctly point to the last group visited. - */ - for (k = 0; k < groups_count; k++) - { -@@ -267,7 +272,8 @@ - pthread_spin_unlock (&global_lock); - return 0; - } -- bh = bptr (gdp->bg_block_bitmap); -+ assert (! bh); -+ bh = disk_cache_block_ref (gdp->bg_block_bitmap); - r = memscan (bh, 0, sblock->s_blocks_per_group >> 3); - j = (r - bh) << 3; - if (j < sblock->s_blocks_per_group) -@@ -277,21 +283,25 @@ - sblock->s_blocks_per_group); - if (j >= sblock->s_blocks_per_group) - { -+ disk_cache_block_deref (bh); -+ bh = 0; - ext2_error ("free blocks count corrupted for block group %d", i); - pthread_spin_unlock (&global_lock); - return 0; - } - --search_back: -+ search_back: -+ assert (bh); - /* -- * We have succeeded in finding a free byte in the block -- * bitmap. Now search backwards up to 7 bits to find the -- * start of this group of free blocks. -+ * We have succeeded in finding a free byte in the block -+ * bitmap. Now search backwards up to 7 bits to find the -+ * start of this group of free blocks. - */ - for (k = 0; k < 7 && j > 0 && !test_bit (j - 1, bh); k++, j--); - --got_block: -- -+ got_block: -+ assert (bh); -+ - ext2_debug ("using block group %d (%d)", i, gdp->bg_free_blocks_count); - - tmp = j + i * sblock->s_blocks_per_group + sblock->s_first_data_block; -@@ -304,6 +314,8 @@ - if (set_bit (j, bh)) - { - ext2_warning ("bit already set for block %d", j); -+ disk_cache_block_deref (bh); -+ bh = 0; - goto repeat; - } - -@@ -320,7 +332,7 @@ - ext2_debug ("found bit %d", j); - - /* -- * Do block preallocation now if required. -+ * Do block preallocation now if required. - */ - #ifdef EXT2_PREALLOCATE - if (prealloc_goal) -@@ -351,6 +363,7 @@ - j = tmp; - - record_global_poke (bh); -+ bh = 0; - - if (j >= sblock->s_blocks_count) - { -@@ -363,12 +376,14 @@ - j, goal_hits, goal_attempts); - - gdp->bg_free_blocks_count--; -+ disk_cache_block_ref_ptr (gdp); - record_global_poke (gdp); - - sblock->s_free_blocks_count--; - sblock_dirty = 1; - - sync_out: -+ assert (! bh); - pthread_spin_unlock (&global_lock); - alloc_sync (0); - -@@ -390,9 +405,12 @@ - gdp = NULL; - for (i = 0; i < groups_count; i++) - { -+ void *bh; - gdp = group_desc (i); - desc_count += gdp->bg_free_blocks_count; -- x = count_free (bptr (gdp->bg_block_bitmap), block_size); -+ bh = disk_cache_block_ref (gdp->bg_block_bitmap); -+ x = count_free (bh, block_size); -+ disk_cache_block_deref (bh); - printf ("group %d: stored = %d, counted = %lu", - i, gdp->bg_free_blocks_count, x); - bitmap_count += x; -@@ -453,7 +471,7 @@ - - gdp = group_desc (i); - desc_count += gdp->bg_free_blocks_count; -- bh = bptr (gdp->bg_block_bitmap); -+ bh = disk_cache_block_ref (gdp->bg_block_bitmap); - - if (!EXT2_HAS_RO_COMPAT_FEATURE (sblock, - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) -@@ -479,6 +497,7 @@ - ext2_error ("block #%d of the inode table in group %d is marked free", j, i); - - x = count_free (bh, block_size); -+ disk_cache_block_deref (bh); - if (gdp->bg_free_blocks_count != x) - ext2_error ("wrong free blocks count for group %d," - " stored = %d, counted = %lu", -Index: hurd-debian/ext2fs/ext2_fs.h -=================================================================== ---- hurd-debian.orig/ext2fs/ext2_fs.h 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/ext2_fs.h 2012-07-10 01:39:22.000000000 +0000 -@@ -25,7 +25,8 @@ - /* - * Define EXT2FS_DEBUG to produce debug messages - */ --#undef EXT2FS_DEBUG -+/* #undef EXT2FS_DEBUG */ -+#define EXT2FS_DEBUG - - /* - * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files -Index: hurd-debian/ext2fs/ext2fs.c -=================================================================== ---- hurd-debian.orig/ext2fs/ext2fs.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/ext2fs.c 2012-07-10 01:39:22.000000000 +0000 -@@ -106,7 +106,7 @@ - if (values == 0) - return ENOMEM; - state->hook = values; -- bzero (values, sizeof *values); -+ memset (values, 0, sizeof *values); - values->sb_block = SBLOCK_BLOCK; - break; - -@@ -181,9 +181,9 @@ - /* Map the entire disk. */ - create_disk_pager (); - -- pokel_init (&global_pokel, diskfs_disk_pager, disk_image); -+ pokel_init (&global_pokel, diskfs_disk_pager, disk_cache); - -- get_hypermetadata(); -+ map_hypermetadata (); - - inode_init (); - -@@ -211,6 +211,8 @@ - { - pokel_flush (&global_pokel); - pager_flush (diskfs_disk_pager, 1); -+ sblock = 0; - get_hypermetadata (); -+ map_hypermetadata (); - return 0; - } -Index: hurd-debian/ext2fs/ext2fs.h -=================================================================== ---- hurd-debian.orig/ext2fs/ext2fs.h 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/ext2fs.h 2012-07-10 01:39:22.000000000 +0000 -@@ -23,7 +23,9 @@ - #include <hurd/pager.h> - #include <hurd/fshelp.h> - #include <hurd/iohelp.h> -+#include <hurd/store.h> - #include <hurd/diskfs.h> -+#include <hurd/ihash.h> - #include <assert.h> - #include <pthread.h> - #include <sys/mman.h> -@@ -195,6 +197,8 @@ - /* ---------------------------------------------------------------- */ - /* pager.c */ - -+#define DISK_CACHE_BLOCKS 65536 -+ - #include <hurd/diskfs-pager.h> - - /* Set up the disk pager. */ -@@ -218,10 +222,54 @@ - /* What the user specified. */ - extern struct store_parsed *store_parsed; - --/* Mapped image of the disk. */ --extern void *disk_image; -+/* Mapped image of cached blocks of the disk. */ -+extern void *disk_cache; -+extern store_offset_t disk_cache_size; -+extern int disk_cache_blocks; -+ -+#define DC_INCORE 0x01 /* Not in core. */ -+#define DC_UNTOUCHED 0x02 /* Not touched by disk_pager_read_paged -+ or disk_cache_block_ref. */ -+#define DC_FIXED 0x04 /* Must not be re-associated. */ -+ -+/* Flags that forbid re-association of page. DC_UNTOUCHED is included -+ because this flag is used only when page is already to be -+ re-associated, so it's not good candidate for another -+ remapping. */ -+#define DC_DONT_REUSE (DC_INCORE | DC_UNTOUCHED | DC_FIXED) -+ -+#define DC_NO_BLOCK ((block_t) -1L) -+ -+#ifndef NDEBUG -+#define DISK_CACHE_LAST_READ_XOR 0xDEADBEEF -+#endif - --/* Our in-core copy of the super-block (pointer into the disk_image). */ -+/* Disk cache blocks' meta info. */ -+struct disk_cache_info -+{ -+ block_t block; -+ uint16_t flags; -+ uint16_t ref_count; -+#ifndef NDEBUG -+ block_t last_read, last_read_xor; -+#endif -+}; -+ -+/* block num --> pointer to in-memory block */ -+extern hurd_ihash_t disk_cache_bptr; -+/* Metadata about cached block. */ -+extern struct disk_cache_info *disk_cache_info; -+/* Lock for these mappings */ -+extern struct mutex disk_cache_lock; -+/* Fired when a re-association is done. */ -+extern struct condition disk_cache_reassociation; -+ -+void *disk_cache_block_ref (block_t block); -+void disk_cache_block_ref_ptr (void *ptr); -+void disk_cache_block_deref (void *ptr); -+int disk_cache_block_is_ref (block_t block); -+ -+/* Our in-core copy of the super-block (pointer into the disk_cache). */ - struct ext2_super_block *sblock; - /* True if sblock has been modified. */ - int sblock_dirty; -@@ -251,6 +299,9 @@ - - /* Get the superblock from the disk, & setup various global info from it. */ - void get_hypermetadata (); -+ -+/* Map `sblock' and `group_desc_image' pointers to disk cache. */ -+void map_hypermetadata (); - - /* ---------------------------------------------------------------- */ - /* Random stuff calculated from the super block. */ -@@ -274,21 +325,51 @@ - unsigned long next_generation; - - /* ---------------------------------------------------------------- */ --/* Functions for looking inside disk_image */ -+/* Functions for looking inside disk_cache */ - --#define trunc_block(offs) (((offs) >> log2_block_size) << log2_block_size) -+#define trunc_block(offs) \ -+ ((off_t) ((offs) >> log2_block_size) << log2_block_size) - #define round_block(offs) \ -- ((((offs) + block_size - 1) >> log2_block_size) << log2_block_size) -+ ((off_t) (((offs) + block_size - 1) >> log2_block_size) << log2_block_size) - - /* block num --> byte offset on disk */ --#define boffs(block) ((block) << log2_block_size) -+#define boffs(block) ((off_t) (block) << log2_block_size) - /* byte offset on disk --> block num */ - #define boffs_block(offs) ((offs) >> log2_block_size) - -+/* pointer to in-memory block -> index in disk_cache_info */ -+#define bptr_index(ptr) (((char *)ptr - (char *)disk_cache) >> log2_block_size) -+ - /* byte offset on disk --> pointer to in-memory block */ --#define boffs_ptr(offs) (((char *)disk_image) + (offs)) -+EXT2FS_EI char * -+boffs_ptr (off_t offset) -+{ -+ block_t block = boffs_block (offset); -+ mutex_lock (&disk_cache_lock); -+ char *ptr = hurd_ihash_find (disk_cache_bptr, block); -+ mutex_unlock (&disk_cache_lock); -+ assert (ptr); -+ ptr += offset % block_size; -+ ext2_debug ("(%Ld) = %p", offset, ptr); -+ return ptr; -+} -+ - /* pointer to in-memory block --> byte offset on disk */ --#define bptr_offs(ptr) ((char *)(ptr) - ((char *)disk_image)) -+EXT2FS_EI off_t -+bptr_offs (void *ptr) -+{ -+ vm_offset_t mem_offset = (char *)ptr - (char *)disk_cache; -+ off_t offset; -+ assert (mem_offset < disk_cache_size); -+ mutex_lock (&disk_cache_lock); -+ offset = (off_t) disk_cache_info[boffs_block (mem_offset)].block -+ << log2_block_size; -+ assert (offset || mem_offset < block_size); -+ offset += mem_offset % block_size; -+ mutex_unlock (&disk_cache_lock); -+ ext2_debug ("(%p) = %Ld", ptr, offset); -+ return offset; -+} - - /* block num --> pointer to in-memory block */ - #define bptr(block) boffs_ptr(boffs(block)) -@@ -308,14 +389,24 @@ - #if defined(__USE_EXTERN_INLINES) || defined(EXT2FS_DEFINE_EI) - /* Convert an inode number to the dinode on disk. */ - EXT2FS_EI struct ext2_inode * --dino (ino_t inum) -+dino_ref (ino_t inum) - { - unsigned long inodes_per_group = sblock->s_inodes_per_group; - unsigned long bg_num = (inum - 1) / inodes_per_group; - unsigned long group_inum = (inum - 1) % inodes_per_group; -- struct ext2_group_desc *bg = group_desc(bg_num); -+ struct ext2_group_desc *bg = group_desc (bg_num); - block_t block = bg->bg_inode_table + (group_inum / inodes_per_block); -- return ((struct ext2_inode *)bptr(block)) + group_inum % inodes_per_block; -+ struct ext2_inode *inode = disk_cache_block_ref (block); -+ inode += group_inum % inodes_per_block; -+ ext2_debug ("(%qd) = %p", inum, inode); -+ return inode; -+} -+ -+EXT2FS_EI void -+dino_deref (struct ext2_inode *inode) -+{ -+ ext2_debug ("(%p)", inode); -+ disk_cache_block_deref (inode); - } - #endif /* Use extern inlines. */ - -@@ -377,27 +468,38 @@ - EXT2FS_EI void - record_global_poke (void *ptr) - { -- int boffs = trunc_block (bptr_offs (ptr)); -- global_block_modified (boffs_block (boffs)); -- pokel_add (&global_pokel, boffs_ptr(boffs), block_size); -+ block_t block = boffs_block (bptr_offs (ptr)); -+ void *block_ptr = bptr (block); -+ ext2_debug ("(%p = %p)", ptr, block_ptr); -+ assert (disk_cache_block_is_ref (block)); -+ global_block_modified (block); -+ pokel_add (&global_pokel, block_ptr, block_size); - } - - /* This syncs a modification to a non-file block. */ - EXT2FS_EI void - sync_global_ptr (void *bptr, int wait) - { -- vm_offset_t boffs = trunc_block (bptr_offs (bptr)); -- global_block_modified (boffs_block (boffs)); -- pager_sync_some (diskfs_disk_pager, trunc_page (boffs), vm_page_size, wait); -+ block_t block = boffs_block (bptr_offs (bptr)); -+ void *block_ptr = bptr (block); -+ ext2_debug ("(%p -> %u)", bptr, (block_t)block); -+ global_block_modified (block); -+ disk_cache_block_deref (block_ptr); -+ pager_sync_some (diskfs_disk_pager, -+ block_ptr - disk_cache, block_size, wait); -+ - } - - /* This records a modification to one of a file's indirect blocks. */ - EXT2FS_EI void - record_indir_poke (struct node *node, void *ptr) - { -- int boffs = trunc_block (bptr_offs (ptr)); -- global_block_modified (boffs_block (boffs)); -- pokel_add (&node->dn->indir_pokel, boffs_ptr(boffs), block_size); -+ block_t block = boffs_block (bptr_offs (ptr)); -+ void *block_ptr = bptr (block); -+ ext2_debug ("(%d, %p)", (int)node->cache_id, ptr); -+ assert (disk_cache_block_is_ref (block)); -+ global_block_modified (block); -+ pokel_add (&node->dn->indir_pokel, block_ptr, block_size); - } - - /* ---------------------------------------------------------------- */ -@@ -405,6 +507,7 @@ - EXT2FS_EI void - sync_global (int wait) - { -+ ext2_debug ("%d", wait); - pokel_sync (&global_pokel, wait); - } - -Index: hurd-debian/ext2fs/getblk.c -=================================================================== ---- hurd-debian.orig/ext2fs/getblk.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/getblk.c 2012-07-10 01:39:22.000000000 +0000 -@@ -52,7 +52,7 @@ - if (node->dn->info.i_prealloc_count) - { - int i = node->dn->info.i_prealloc_count; -- ext2_debug ("discarding %d prealloced blocks for inode %d", -+ ext2_debug ("discarding %d prealloced blocks for inode %Ld", - i, node->cache_id); - node->dn->info.i_prealloc_count = 0; - ext2_free_blocks (node->dn->info.i_prealloc_block, i); -@@ -104,8 +104,8 @@ - - if (result && zero) - { -- char *bh = bptr (result); -- bzero (bh, block_size); -+ char *bh = disk_cache_block_ref (result); -+ memset (bh, 0, block_size); - record_indir_poke (node, bh); - } - -@@ -122,6 +122,8 @@ - block_t hint; - #endif - -+ assert (0 <= nr && nr < EXT2_N_BLOCKS); -+ - *result = node->dn->info.i_data[nr]; - if (*result) - return 0; -@@ -180,14 +182,20 @@ - { - int i; - block_t goal = 0; -- block_t *bh = (block_t *)bptr (block); -+ block_t *bh = (block_t *)disk_cache_block_ref (block); - - *result = bh[nr]; - if (*result) -- return 0; -+ { -+ disk_cache_block_deref (bh); -+ return 0; -+ } - - if (!create) -- return EINVAL; -+ { -+ disk_cache_block_deref (bh); -+ return EINVAL; -+ } - - if (node->dn->info.i_next_alloc_block == new_block) - goal = node->dn->info.i_next_alloc_goal; -@@ -207,7 +215,10 @@ - - *result = ext2_alloc_block (node, goal, zero); - if (!*result) -- return ENOSPC; -+ { -+ disk_cache_block_deref (bh); -+ return ENOSPC; -+ } - - bh[nr] = *result; - -@@ -243,9 +254,9 @@ - return EIO; - } - /* -- * If this is a sequential block allocation, set the next_alloc_block -- * to this block now so that all the indblock and data block -- * allocations use the same goal zone -+ * If this is a sequential block allocation, set the next_alloc_block -+ * to this block now so that all the indblock and data block -+ * allocations use the same goal zone - */ - - ext2_debug ("block = %u, next = %u, goal = %u", block, -Index: hurd-debian/ext2fs/hyper.c -=================================================================== ---- hurd-debian.orig/ext2fs/hyper.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/hyper.c 2012-07-10 01:39:22.000000000 +0000 -@@ -58,12 +58,15 @@ - void - get_hypermetadata (void) - { -- error_t err = diskfs_catch_exception (); -- if (err) -- ext2_panic ("can't read superblock: %s", strerror (err)); -- -- sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS); -+ error_t err; -+ size_t read = 0; - -+ assert (! sblock); -+ err = store_read (store, SBLOCK_OFFS >> store->log2_block_size, -+ SBLOCK_SIZE, (void **)&sblock, &read); -+ if (err || read != SBLOCK_SIZE) -+ ext2_panic ("Cannot read hypermetadata"); -+ - if (sblock->s_magic != EXT2_SUPER_MAGIC - #ifdef EXT2FS_PRE_02B_COMPAT - && sblock->s_magic != EXT2_PRE_02B_MAGIC -@@ -152,15 +155,22 @@ - - allocate_mod_map (); - -- diskfs_end_catch_exception (); -+ /* A handy source of page-aligned zeros. */ -+ if (zeroblock == 0) -+ zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0); -+ -+ munmap (sblock, SBLOCK_SIZE); -+ sblock = NULL; -+} -+ -+void -+map_hypermetadata (void) -+{ -+ sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS); - - /* Cache a convenient pointer to the block group descriptors for allocation. - These are stored in the filesystem blocks following the superblock. */ - group_desc_image = (struct ext2_group_desc *) bptr (bptr_block (sblock) + 1); -- -- /* A handy source of page-aligned zeros. */ -- if (zeroblock == 0) -- zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0); - } - - error_t -@@ -183,6 +193,7 @@ - if (sblock_dirty) - { - sblock_dirty = 0; -+ disk_cache_block_ref_ptr (sblock); - record_global_poke (sblock); - } - -@@ -199,7 +210,8 @@ - - (*(readonly ? store_set_flags : store_clear_flags)) (store, STORE_READONLY); - -- mprotect (disk_image, store->size, PROT_READ | (readonly ? 0 : PROT_WRITE)); -+ mprotect (disk_cache, disk_cache_size, -+ PROT_READ | (readonly ? 0 : PROT_WRITE)); - - if (!readonly && !(sblock->s_state & EXT2_VALID_FS)) - ext2_warning ("UNCLEANED FILESYSTEM NOW WRITABLE"); -Index: hurd-debian/ext2fs/ialloc.c -=================================================================== ---- hurd-debian.orig/ext2fs/ialloc.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/ialloc.c 2012-07-10 01:39:22.000000000 +0000 -@@ -60,7 +60,7 @@ - - assert (!diskfs_readonly); - -- ext2_debug ("freeing inode %u", inum); -+ ext2_debug ("freeing inode %Lu", inum); - - pthread_spin_lock (&global_lock); - -@@ -75,22 +75,25 @@ - bit = (inum - 1) % sblock->s_inodes_per_group; - - gdp = group_desc (block_group); -- bh = bptr (gdp->bg_inode_bitmap); -+ bh = disk_cache_block_ref (gdp->bg_inode_bitmap); - - if (!clear_bit (bit, bh)) - ext2_warning ("bit already cleared for inode %Ld", inum); - else - { -+ disk_cache_block_ref_ptr (bh); - record_global_poke (bh); - - gdp->bg_free_inodes_count++; - if (S_ISDIR (old_mode)) - gdp->bg_used_dirs_count--; -+ disk_cache_block_ref_ptr (gdp); - record_global_poke (gdp); - - sblock->s_free_inodes_count++; - } - -+ disk_cache_block_deref (bh); - sblock_dirty = 1; - pthread_spin_unlock (&global_lock); - alloc_sync(0); -@@ -111,14 +114,15 @@ - ino_t - ext2_alloc_inode (ino_t dir_inum, mode_t mode) - { -- char *bh; -+ char *bh = 0; - int i, j, inum, avefreei; - struct ext2_group_desc *gdp; - struct ext2_group_desc *tmp; - - pthread_spin_lock (&global_lock); - --repeat: -+ repeat: -+ assert (! bh); - gdp = NULL; - i = 0; - -@@ -213,7 +217,7 @@ - return 0; - } - -- bh = bptr (gdp->bg_inode_bitmap); -+ bh = disk_cache_block_ref (gdp->bg_inode_bitmap); - if ((inum = - find_first_zero_bit ((unsigned long *) bh, sblock->s_inodes_per_group)) - < sblock->s_inodes_per_group) -@@ -221,12 +225,17 @@ - if (set_bit (inum, bh)) - { - ext2_warning ("bit already set for inode %d", inum); -+ disk_cache_block_deref (bh); -+ bh = 0; - goto repeat; - } - record_global_poke (bh); -+ bh = 0; - } - else - { -+ disk_cache_block_deref (bh); -+ bh = 0; - if (gdp->bg_free_inodes_count != 0) - { - ext2_error ("free inodes count corrupted in group %d", i); -@@ -248,15 +257,25 @@ - gdp->bg_free_inodes_count--; - if (S_ISDIR (mode)) - gdp->bg_used_dirs_count++; -+ disk_cache_block_ref_ptr (gdp); - record_global_poke (gdp); - - sblock->s_free_inodes_count--; - sblock_dirty = 1; - - sync_out: -+ assert (! bh); - pthread_spin_unlock (&global_lock); - alloc_sync (0); - -+ /* Make sure the coming read_node won't complain about bad -+ fields. */ -+ { -+ struct ext2_inode *di = dino_ref (inum); -+ memset (di, 0, sizeof *di); -+ dino_deref (di); -+ } -+ - return inum; - } - -@@ -353,10 +372,12 @@ - gdp = NULL; - for (i = 0; i < groups_count; i++) - { -+ void *bh; - gdp = group_desc (i); - desc_count += gdp->bg_free_inodes_count; -- x = count_free (bptr (gdp->bg_inode_bitmap), -- sblock->s_inodes_per_group / 8); -+ bh = disk_cache_block_ref (gdp->bg_inode_bitmap); -+ x = count_free (bh, sblock->s_inodes_per_group / 8); -+ disk_cache_block_deref (bh); - ext2_debug ("group %d: stored = %d, counted = %lu", - i, gdp->bg_free_inodes_count, x); - bitmap_count += x; -@@ -386,10 +407,12 @@ - gdp = NULL; - for (i = 0; i < groups_count; i++) - { -+ void *bh; - gdp = group_desc (i); - desc_count += gdp->bg_free_inodes_count; -- x = count_free (bptr (gdp->bg_inode_bitmap), -- sblock->s_inodes_per_group / 8); -+ bh = disk_cache_block_ref (gdp->bg_inode_bitmap); -+ x = count_free (bh, sblock->s_inodes_per_group / 8); -+ disk_cache_block_deref (bh); - if (gdp->bg_free_inodes_count != x) - ext2_error ("wrong free inodes count in group %d, " - "stored = %d, counted = %lu", -Index: hurd-debian/ext2fs/inode.c -=================================================================== ---- hurd-debian.orig/ext2fs/inode.c 2012-11-26 00:23:28.000000000 +0000 -+++ hurd-debian/ext2fs/inode.c 2012-11-26 00:24:49.000000000 +0000 -@@ -92,7 +92,7 @@ - dn->dir_idx = 0; - dn->pager = 0; - pthread_rwlock_init (&dn->alloc_lock, NULL); -- pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_image); -+ pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_cache); - - /* Create the new node. */ - np = diskfs_make_node (dn); -@@ -201,13 +201,17 @@ - error_t err; - struct stat *st = &np->dn_stat; - struct disknode *dn = np->dn; -- struct ext2_inode *di = dino (np->cache_id); -+ struct ext2_inode *di; - struct ext2_inode_info *info = &dn->info; - -+ ext2_debug ("(%d)", np->cache_id); -+ - err = diskfs_catch_exception (); - if (err) - return err; - -+ di = dino_ref (np->cache_id); -+ - st->st_fstype = FSTYPE_EXT2FS; - st->st_fsid = getpid (); /* This call is very cheap. */ - st->st_ino = np->cache_id; -@@ -285,7 +289,9 @@ - info->i_high_size = di->i_size_high; - if (info->i_high_size) /* XXX */ - { -+ dino_deref (di); - ext2_warning ("cannot handle large file inode %Ld", np->cache_id); -+ diskfs_end_catch_exception (); - return EFBIG; - } - } -@@ -307,20 +313,12 @@ - } - dn->info_i_translator = di->i_translator; - -+ dino_deref (di); - diskfs_end_catch_exception (); - - if (S_ISREG (st->st_mode) || S_ISDIR (st->st_mode) - || (S_ISLNK (st->st_mode) && st->st_blocks)) -- { -- unsigned offset; -- -- np->allocsize = np->dn_stat.st_size; -- -- /* Round up to a block multiple. */ -- offset = np->allocsize & ((1 << log2_block_size) - 1); -- if (offset > 0) -- np->allocsize += block_size - offset; -- } -+ np->allocsize = round_block (np->dn_stat.st_size); - else - /* Allocsize should be zero for anything except directories, files, and - long symlinks. These are the only things allowed to have any blocks -@@ -408,7 +406,9 @@ - { - error_t err; - struct stat *st = &np->dn_stat; -- struct ext2_inode *di = dino (np->cache_id); -+ struct ext2_inode *di; -+ -+ ext2_debug ("(%d)", np->cache_id); - - if (np->dn->info.i_prealloc_count) - ext2_discard_prealloc (np); -@@ -419,12 +419,14 @@ - - assert (!diskfs_readonly); - -- ext2_debug ("writing inode %d to disk", np->cache_id); -+ ext2_debug ("writing inode %Ld to disk", np->cache_id); - - err = diskfs_catch_exception (); - if (err) - return NULL; - -+ di = dino_ref (np->cache_id); -+ - di->i_generation = st->st_gen; - - /* We happen to know that the stat mode bits are the same -@@ -505,6 +507,7 @@ - diskfs_end_catch_exception (); - np->dn_stat_dirty = 0; - -+ /* Leave invoking dino_deref (di) to the caller. */ - return di; - } - else -@@ -674,7 +677,7 @@ - if (err) - return err; - -- di = dino (np->cache_id); -+ di = dino_ref (np->cache_id); - blkno = di->i_translator; - - if (namelen && !blkno) -@@ -687,6 +690,7 @@ - 0, 0, 0); - if (blkno == 0) - { -+ dino_deref (di); - diskfs_end_catch_exception (); - return ENOSPC; - } -@@ -710,15 +714,20 @@ - np->dn_stat.st_mode &= ~S_IPTRANS; - np->dn_set_ctime = 1; - } -+ else -+ dino_deref (di); - - if (namelen) - { -+ void *blkptr; -+ - buf[0] = namelen & 0xFF; - buf[1] = (namelen >> 8) & 0xFF; -- bcopy (name, buf + 2, namelen); -+ memcpy (buf + 2, name, namelen); - -- bcopy (buf, bptr (blkno), block_size); -- record_global_poke (bptr (blkno)); -+ blkptr = disk_cache_block_ref (blkno); -+ memcpy (blkptr, buf, block_size); -+ record_global_poke (blkptr); - - np->dn_stat.st_mode |= S_IPTRANS; - np->dn_set_ctime = 1; -@@ -736,7 +745,7 @@ - error_t err = 0; - daddr_t blkno; - unsigned datalen; -- const void *transloc; -+ void *transloc; - - assert (sblock->s_creator_os == EXT2_OS_HURD); - -@@ -744,9 +753,11 @@ - if (err) - return err; - -- blkno = (dino (np->cache_id))->i_translator; -+ struct ext2_inode *di = dino_ref (np->cache_id); -+ blkno = di->i_translator; -+ dino_deref (di); - assert (blkno); -- transloc = bptr (blkno); -+ transloc = disk_cache_block_ref (blkno); - - datalen = - ((unsigned char *)transloc)[0] + (((unsigned char *)transloc)[1] << 8); -@@ -761,6 +772,7 @@ - memcpy (*namep, transloc + 2, datalen); - } - -+ disk_cache_block_deref (transloc); - diskfs_end_catch_exception (); - - *namelen = datalen; -@@ -782,7 +794,7 @@ - - assert (node->dn_stat.st_blocks == 0); - -- bcopy (target, node->dn->info.i_data, len); -+ memcpy (node->dn->info.i_data, target, len); - node->dn_stat.st_size = len - 1; - node->dn_set_ctime = 1; - node->dn_set_mtime = 1; -@@ -799,7 +811,7 @@ - - assert (node->dn_stat.st_size < MAX_INODE_SYMLINK); - -- bcopy (node->dn->info.i_data, target, node->dn_stat.st_size); -+ memcpy (target, node->dn->info.i_data, node->dn_stat.st_size); - return 0; - } - -Index: hurd-debian/ext2fs/pager.c -=================================================================== ---- hurd-debian.orig/ext2fs/pager.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -18,17 +18,18 @@ - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -+#include <unistd.h> - #include <string.h> - #include <errno.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; - --/* Mapped image of the disk. */ --void *disk_image; -- - pthread_spinlock_t node_to_page_lock = PTHREAD_SPINLOCK_INITIALIZER; - - -@@ -165,6 +166,9 @@ - block_t pending_blocks = 0; - int num_pending_blocks = 0; - -+ ext2_debug ("reading inode %Ld page %u[%d]", -+ node->cache_id, page, vm_page_size); -+ - /* Read the NUM_PENDING_BLOCKS blocks in PENDING_BLOCKS, into the buffer - pointed to by BUF (allocating it if necessary) at offset OFFS. OFFS in - adjusted by the amount read, and NUM_PENDING_BLOCKS is zeroed. Any read -@@ -171,7 +175,8 @@ - { - if (num_pending_blocks > 0) - { -- block_t dev_block = pending_blocks << log2_dev_blocks_per_fs_block; -+ store_offset_t dev_block = (store_offset_t) pending_blocks -+ << log2_dev_blocks_per_fs_block; - size_t amount = num_pending_blocks << log2_block_size; - /* The buffer we try to read into; on the first read, we pass in a - size of zero, so that the read is guaranteed to allocate a new -@@ -198,7 +203,7 @@ - else - /* We've already got some buffer, so copy into it. */ - { -- bcopy (new_buf, *buf + offs, new_len); -+ memcpy (*buf + offs, new_buf, new_len); - free_page_buf (new_buf); /* Return NEW_BUF to our pool. */ - STAT_INC (file_pagein_freed_bufs); - } -@@ -254,7 +259,7 @@ - break; - STAT_INC (file_pagein_alloced_bufs); - } -- bzero (*buf + offs, block_size); -+ memset (*buf + offs, 0, block_size); - offs += block_size; - } - else -@@ -295,16 +300,17 @@ - if (pb->num > 0) - { - error_t err; -- block_t dev_block = pb->block << log2_dev_blocks_per_fs_block; -+ store_offset_t dev_block = (store_offset_t) pb->block -+ << log2_dev_blocks_per_fs_block; - size_t length = pb->num << log2_block_size, amount; - -- ext2_debug ("writing block %u[%ld]", pb->block, pb->num); -+ ext2_debug ("writing block %u[%Ld]", pb->block, pb->num); - - if (pb->offs > 0) - /* Put what we're going to write into a page-aligned buffer. */ - { - void *page_buf = get_page_buf (); -- bcopy (pb->buf + pb->offs, (void *)page_buf, length); -+ memcpy ((void *)page_buf, pb->buf + pb->offs, length); - err = store_write (store, dev_block, page_buf, length, &amount); - free_page_buf (page_buf); - } -@@ -357,7 +363,7 @@ - return 0; - } - --/* Write one page for the pager backing NODE, at offset PAGE, into BUF. This -+/* Write one page for the pager backing NODE, at OFFSET, into BUF. This - may need to write several filesystem blocks to satisfy one page, and tries - to consolidate the i/o if possible. */ - static error_t -@@ -381,7 +387,7 @@ - else if (offset + left > node->allocsize) - left = node->allocsize - offset; - -- ext2_debug ("writing inode %d page %d[%d]", node->cache_id, offset, left); -+ ext2_debug ("writing inode %Ld page %u[%d]", node->cache_id, offset, left); - - STAT_INC (file_pageouts); - -@@ -409,16 +415,31 @@ - { - error_t err; - size_t length = vm_page_size, read = 0; -- vm_size_t dev_end = store->size; -+ store_offset_t offset = page, dev_end = store->size; - -- if (page + vm_page_size > dev_end) -- length = dev_end - page; -+ mutex_lock (&disk_cache_lock); -+ int index = offset >> log2_block_size; -+ offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size) -+ + offset % block_size; -+ disk_cache_info[index].flags |= DC_INCORE; -+ disk_cache_info[index].flags &=~ DC_UNTOUCHED; -+#ifndef NDEBUG -+ disk_cache_info[index].last_read = disk_cache_info[index].block; -+ disk_cache_info[index].last_read_xor -+ = disk_cache_info[index].block ^ DISK_CACHE_LAST_READ_XOR; -+#endif -+ ext2_debug ("(%Ld)", offset >> log2_block_size); -+ mutex_unlock (&disk_cache_lock); -+ -+ if (offset + vm_page_size > dev_end) -+ length = dev_end - offset; - -- err = store_read (store, page >> store->log2_block_size, length, buf, &read); -+ err = store_read (store, offset >> store->log2_block_size, length, -+ buf, &read); - if (read != length) - return EIO; - if (!err && length != vm_page_size) -- bzero ((void *)(*buf + length), vm_page_size - length); -+ memset ((void *)(*buf + length), 0, vm_page_size - length); - - *writelock = 0; - -@@ -430,26 +451,38 @@ - { - error_t err = 0; - size_t length = vm_page_size, amount; -- vm_size_t dev_end = store->size; -+ store_offset_t offset = page, dev_end = store->size; -+ -+ mutex_lock (&disk_cache_lock); -+ int index = offset >> log2_block_size; -+ assert (disk_cache_info[index].block != DC_NO_BLOCK); -+ offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size) -+ + offset % block_size; -+#ifndef NDEBUG /* Not strictly needed. */ -+ assert ((disk_cache_info[index].last_read ^ DISK_CACHE_LAST_READ_XOR) -+ == disk_cache_info[index].last_read_xor); -+ assert (disk_cache_info[index].last_read -+ == disk_cache_info[index].block); -+#endif -+ mutex_unlock (&disk_cache_lock); - -- if (page + vm_page_size > dev_end) -- length = dev_end - page; -+ if (offset + vm_page_size > dev_end) -+ length = dev_end - offset; - -- ext2_debug ("writing disk page %d[%d]", page, length); -+ ext2_debug ("writing disk page %Ld[%d]", offset, length); - - STAT_INC (disk_pageouts); - - if (modified_global_blocks) - /* Be picky about which blocks in a page that we write. */ - { -- vm_offset_t offs = page; - struct pending_blocks pb; - - pending_blocks_init (&pb, buf); - - while (length > 0 && !err) - { -- block_t block = boffs_block (offs); -+ block_t block = boffs_block (offset); - - /* We don't clear the block modified bit here because this paging - write request may not be the same one that actually set the bit, -@@ -467,7 +500,7 @@ - /* Otherwise just skip it. */ - err = pending_blocks_skip (&pb); - -- offs += block_size; -+ offset += block_size; - length -= block_size; - } - -@@ -476,7 +509,7 @@ - } - else - { -- err = store_write (store, page >> store->log2_block_size, -+ err = store_write (store, offset >> store->log2_block_size, - buf, length, &amount); - if (!err && length != amount) - err = EIO; -@@ -484,6 +517,18 @@ - - return err; - } -+ -+static void -+disk_pager_notify_evict (vm_offset_t page) -+{ -+ int index = page >> log2_block_size; -+ -+ ext2_debug ("(block %u)", index); -+ -+ mutex_lock (&disk_cache_lock); -+ disk_cache_info[index].flags &= ~DC_INCORE; -+ mutex_unlock (&disk_cache_lock); -+} - - /* Satisfy a pager read request for either the disk pager or file pager - PAGER, to the page at offset PAGE into BUF. WRITELOCK should be set if -@@ -493,9 +538,11 @@ - vm_address_t *buf, int *writelock) - { - if (pager->type == DISK) -- return disk_pager_read_page (page, (void **)buf, writelock); -+ return disk_pager_read_page (page, (void **)buf, -+ writelock); - else -- return file_pager_read_page (pager->node, page, (void **)buf, writelock); -+ return file_pager_read_page (pager->node, page, (void **)buf, -+ writelock); - } - - /* Satisfy a pager write request for either the disk pager or file pager -@@ -509,6 +556,14 @@ - else - return file_pager_write_page (pager->node, page, (void *)buf); - } -+ -+void -+pager_notify_evict (struct user_pager_info *pager, vm_offset_t page) -+{ -+ if (pager->type == DISK) -+ disk_pager_notify_evict (page); -+} -+ - - /* Make page PAGE writable, at least up to ALLOCSIZE. This function and - diskfs_grow are the only places that blocks are actually added to the -@@ -558,10 +613,10 @@ - - #ifdef EXT2FS_DEBUG - if (dn->last_page_partially_writable) -- ext2_debug ("made page %u[%lu] in inode %d partially writable", -+ ext2_debug ("made page %u[%Lu] in inode %Ld partially writable", - page, node->allocsize - page, node->cache_id); - else -- ext2_debug ("made page %u[%u] in inode %d writable", -+ ext2_debug ("made page %u[%u] in inode %Ld writable", - page, vm_page_size, node->cache_id); - #endif - -@@ -619,8 +674,8 @@ - block_t old_page_end_block = - round_page (old_size) >> log2_block_size; - -- ext2_debug ("growing inode %d to %lu bytes (from %lu)", node->cache_id, -- new_size, old_size); -+ ext2_debug ("growing inode %Ld to %Lu bytes (from %Lu)", -+ node->cache_id, new_size, old_size); - - if (dn->last_page_partially_writable - && old_page_end_block > end_block) -@@ -656,11 +711,11 @@ - - STAT_INC (file_grows); - -- ext2_debug ("new size: %ld%s.", new_size, -+ ext2_debug ("new size: %Lu%s.", new_size, - dn->last_page_partially_writable - ? " (last page writable)": ""); - if (err) -- ext2_warning ("inode=%Ld, target=%Ld: %s", -+ ext2_warning ("inode=%Ld, target=%Lu: %s", - node->cache_id, new_size, strerror (err)); - - node->allocsize = new_size; -@@ -765,6 +820,374 @@ - { - } - -+/* Cached blocks from disk. */ -+void *disk_cache; -+ -+/* DISK_CACHE size in bytes and blocks. */ -+store_offset_t disk_cache_size; -+int disk_cache_blocks; -+ -+/* block num --> pointer to in-memory block */ -+hurd_ihash_t disk_cache_bptr; -+/* Cached blocks' info. */ -+struct disk_cache_info *disk_cache_info; -+/* Hint index for which cache block to reuse next. */ -+int disk_cache_hint; -+/* Lock for these structures. */ -+struct mutex disk_cache_lock; -+/* Fired when a re-association is done. */ -+struct condition disk_cache_reassociation; -+ -+/* Finish mapping initialization. */ -+static void -+disk_cache_init (void) -+{ -+ if (block_size != vm_page_size) -+ ext2_panic ("Block size %d != vm_page_size %d", -+ block_size, vm_page_size); -+ -+ mutex_init (&disk_cache_lock); -+ condition_init (&disk_cache_reassociation); -+ -+ /* Allocate space for block num -> in-memory pointer mapping. */ -+ if (hurd_ihash_create (&disk_cache_bptr, HURD_IHASH_NO_LOCP)) -+ ext2_panic ("Can't allocate memory for disk_pager_bptr"); -+ -+ /* Allocate space for disk cache blocks' info. */ -+ disk_cache_info = malloc ((sizeof *disk_cache_info) * disk_cache_blocks); -+ if (!disk_cache_info) -+ ext2_panic ("Cannot allocate space for disk cache info"); -+ -+ /* Initialize disk_cache_info. */ -+ for (int i = 0; i < disk_cache_blocks; i++) -+ { -+ disk_cache_info[i].block = DC_NO_BLOCK; -+ disk_cache_info[i].flags = 0; -+ disk_cache_info[i].ref_count = 0; -+#ifndef NDEBUG -+ disk_cache_info[i].last_read = DC_NO_BLOCK; -+ disk_cache_info[i].last_read_xor -+ = DC_NO_BLOCK ^ DISK_CACHE_LAST_READ_XOR; -+#endif -+ } -+ disk_cache_hint = 0; -+ -+ /* Map the superblock and the block group descriptors. */ -+ block_t fixed_first = boffs_block (SBLOCK_OFFS); -+ block_t fixed_last = fixed_first -+ + (round_block ((sizeof *group_desc_image) * groups_count) -+ >> log2_block_size); -+ ext2_debug ("%d-%d\n", fixed_first, fixed_last); -+ assert (fixed_last - fixed_first + 1 <= (block_t)disk_cache_blocks + 3); -+ for (block_t i = fixed_first; i <= fixed_last; i++) -+ { -+ disk_cache_block_ref (i); -+ assert (disk_cache_info[i-fixed_first].block == i); -+ disk_cache_info[i-fixed_first].flags |= DC_FIXED; -+ } -+} -+ -+static void -+disk_cache_return_unused (void) -+{ -+ int index; -+ -+ /* XXX: Touch all pages. It seems that sometimes GNU Mach "forgets" -+ to notify us about evicted pages. Disk cache must be -+ unlocked. */ -+ for (vm_offset_t i = 0; i < disk_cache_size; i += vm_page_size) -+ *(volatile char *)(disk_cache + i); -+ -+ /* Release some references to cached blocks. */ -+ pokel_sync (&global_pokel, 1); -+ -+ /* Return unused pages that are in core. */ -+ int pending_begin = -1, pending_end = -1; -+ mutex_lock (&disk_cache_lock); -+ for (index = 0; index < disk_cache_blocks; index++) -+ if (! (disk_cache_info[index].flags & (DC_DONT_REUSE & ~DC_INCORE)) -+ && ! disk_cache_info[index].ref_count) -+ { -+ ext2_debug ("return %u -> %d", -+ disk_cache_info[index].block, index); -+ if (index != pending_end) -+ { -+ /* Return previous region, if there is such, ... */ -+ if (pending_end >= 0) -+ { -+ mutex_unlock (&disk_cache_lock); -+ pager_return_some (diskfs_disk_pager, -+ pending_begin * vm_page_size, -+ (pending_end - pending_begin) -+ * vm_page_size, -+ 1); -+ mutex_lock (&disk_cache_lock); -+ } -+ /* ... and start new region. */ -+ pending_begin = index; -+ } -+ pending_end = index + 1; -+ } -+ -+ mutex_unlock (&disk_cache_lock); -+ -+ /* Return last region, if there is such. */ -+ if (pending_end >= 0) -+ pager_return_some (diskfs_disk_pager, -+ pending_begin * vm_page_size, -+ (pending_end - pending_begin) * vm_page_size, -+ 1); -+ else -+ { -+ printf ("ext2fs: disk cache is starving\n"); -+ -+ /* Give it some time. This should happen rarely. */ -+ sleep (1); -+ } -+} -+ -+/* Map block and return pointer to it. */ -+void * -+disk_cache_block_ref (block_t block) -+{ -+ int index; -+ void *bptr; -+ -+ assert (0 <= block && block < store->size >> log2_block_size); -+ -+ ext2_debug ("(%u)", block); -+ -+ mutex_lock (&disk_cache_lock); -+ -+ bptr = hurd_ihash_find (disk_cache_bptr, block); -+ if (bptr) -+ /* Already mapped. */ -+ { -+ index = bptr_index (bptr); -+ -+ /* In process of re-associating? */ -+ if (disk_cache_info[index].flags & DC_UNTOUCHED) -+ { -+ /* Wait re-association to finish. */ -+ condition_wait (&disk_cache_reassociation, &disk_cache_lock); -+ mutex_unlock (&disk_cache_lock); -+ -+#if 0 -+ printf ("Re-association -- wait finished.\n"); -+#endif -+ -+ /* Try again. */ -+ return disk_cache_block_ref (block); /* tail recursion */ -+ } -+ -+ /* Just increment reference and return. */ -+ assert (disk_cache_info[index].ref_count + 1 -+ > disk_cache_info[index].ref_count); -+ disk_cache_info[index].ref_count++; -+ -+ ext2_debug ("cached %u -> %d (ref_count = %d, flags = 0x%x, ptr = %p)", -+ disk_cache_info[index].block, index, -+ disk_cache_info[index].ref_count, -+ disk_cache_info[index].flags, bptr); -+ -+ mutex_unlock (&disk_cache_lock); -+ -+ return bptr; -+ } -+ -+ /* Search for a block that is not in core and is not referenced. */ -+ index = disk_cache_hint; -+ while ((disk_cache_info[index].flags & DC_DONT_REUSE) -+ || (disk_cache_info[index].ref_count)) -+ { -+ ext2_debug ("reject %u -> %d (ref_count = %d, flags = 0x%x)", -+ disk_cache_info[index].block, index, -+ disk_cache_info[index].ref_count, -+ disk_cache_info[index].flags); -+ -+ /* Just move to next block. */ -+ index++; -+ if (index >= disk_cache_blocks) -+ index -= disk_cache_blocks; -+ -+ /* If we return to where we started, than there is no suitable -+ block. */ -+ if (index == disk_cache_hint) -+ break; -+ } -+ -+ /* The next place in the disk cache becomes the current hint. */ -+ disk_cache_hint = index + 1; -+ if (disk_cache_hint >= disk_cache_blocks) -+ disk_cache_hint -= disk_cache_blocks; -+ -+ /* Is suitable place found? */ -+ if ((disk_cache_info[index].flags & DC_DONT_REUSE) -+ || disk_cache_info[index].ref_count) -+ /* No place is found. Try to release some blocks and try -+ again. */ -+ { -+ ext2_debug ("flush %u -> %d", disk_cache_info[index].block, index); -+ -+ mutex_unlock (&disk_cache_lock); -+ -+ disk_cache_return_unused (); -+ -+ return disk_cache_block_ref (block); /* tail recursion */ -+ } -+ -+ /* Suitable place is found. */ -+ -+ /* Calculate pointer to data. */ -+ bptr = (char *)disk_cache + (index << log2_block_size); -+ ext2_debug ("map %u -> %d (%p)", block, index, bptr); -+ -+ /* This pager_return_some is used only to set PM_FORCEREAD for the -+ page. DC_UNTOUCHED is set so that we catch if someone has -+ referenced the block while we didn't hold disk_cache_lock. */ -+ disk_cache_info[index].flags |= DC_UNTOUCHED; -+ -+#if 0 /* XXX: Let's see if this is needed at all. */ -+ -+ mutex_unlock (&disk_cache_lock); -+ pager_return_some (diskfs_disk_pager, bptr - disk_cache, vm_page_size, 1); -+ mutex_lock (&disk_cache_lock); -+ -+ /* Has someone used our bptr? Has someone mapped requested block -+ while we have unlocked disk_cache_lock? If so, environment has -+ changed and we have to restart operation. */ -+ if ((! (disk_cache_info[index].flags & DC_UNTOUCHED)) -+ || hurd_ihash_find (disk_cache_bptr, block)) -+ { -+ mutex_unlock (&disk_cache_lock); -+ return disk_cache_block_ref (block); /* tail recursion */ -+ } -+ -+#elif 0 -+ -+ /* XXX: Use libpager internals. */ -+ -+ mutex_lock (&diskfs_disk_pager->interlock); -+ int page = (bptr - disk_cache) / vm_page_size; -+ assert (page >= 0); -+ int is_incore = (page < diskfs_disk_pager->pagemapsize -+ && (diskfs_disk_pager->pagemap[page] & PM_INCORE)); -+ mutex_unlock (&diskfs_disk_pager->interlock); -+ if (is_incore) -+ { -+ mutex_unlock (&disk_cache_lock); -+ printf ("INCORE\n"); -+ return disk_cache_block_ref (block); /* tail recursion */ -+ } -+ -+#endif -+ -+ /* Re-associate. */ -+ if (disk_cache_info[index].block != DC_NO_BLOCK) -+ /* Remove old association. */ -+ hurd_ihash_remove (disk_cache_bptr, disk_cache_info[index].block); -+ /* New association. */ -+ if (hurd_ihash_add (disk_cache_bptr, block, bptr)) -+ ext2_panic ("Couldn't hurd_ihash_add new disk block"); -+ assert (! (disk_cache_info[index].flags & DC_DONT_REUSE & ~DC_UNTOUCHED)); -+ disk_cache_info[index].block = block; -+ assert (! disk_cache_info[index].ref_count); -+ disk_cache_info[index].ref_count = 1; -+ -+ /* All data structures are set up. */ -+ mutex_unlock (&disk_cache_lock); -+ -+ /* Try to read page. */ -+ *(volatile char *) bptr; -+ -+ /* Check if it's actually read. */ -+ mutex_lock (&disk_cache_lock); -+ if (disk_cache_info[index].flags & DC_UNTOUCHED) -+ /* It's not read. */ -+ { -+ /* Remove newly created association. */ -+ hurd_ihash_remove (disk_cache_bptr, block); -+ disk_cache_info[index].block = DC_NO_BLOCK; -+ disk_cache_info[index].flags &=~ DC_UNTOUCHED; -+ disk_cache_info[index].ref_count = 0; -+ mutex_unlock (&disk_cache_lock); -+ -+ /* Prepare next time association of this page to succeed. */ -+ pager_flush_some (diskfs_disk_pager, bptr - disk_cache, -+ vm_page_size, 0); -+ -+#if 0 -+ printf ("Re-association failed.\n"); -+#endif -+ -+ /* Try again. */ -+ return disk_cache_block_ref (block); /* tail recursion */ -+ } -+ mutex_unlock (&disk_cache_lock); -+ -+ /* Re-association was successful. */ -+ condition_broadcast (&disk_cache_reassociation); -+ -+ ext2_debug ("(%u) = %p", block, bptr); -+ return bptr; -+} -+ -+void -+disk_cache_block_ref_ptr (void *ptr) -+{ -+ int index; -+ -+ mutex_lock (&disk_cache_lock); -+ index = bptr_index (ptr); -+ assert (disk_cache_info[index].ref_count >= 1); -+ assert (disk_cache_info[index].ref_count + 1 -+ > disk_cache_info[index].ref_count); -+ disk_cache_info[index].ref_count++; -+ assert (! (disk_cache_info[index].flags & DC_UNTOUCHED)); -+ ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)", -+ ptr, -+ disk_cache_info[index].ref_count, -+ disk_cache_info[index].flags); -+ mutex_unlock (&disk_cache_lock); -+} -+ -+void -+disk_cache_block_deref (void *ptr) -+{ -+ int index; -+ -+ assert (disk_cache <= ptr && ptr <= disk_cache + disk_cache_size); -+ -+ mutex_lock (&disk_cache_lock); -+ index = bptr_index (ptr); -+ ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)", -+ ptr, -+ disk_cache_info[index].ref_count - 1, -+ disk_cache_info[index].flags); -+ assert (! (disk_cache_info[index].flags & DC_UNTOUCHED)); -+ assert (disk_cache_info[index].ref_count >= 1); -+ disk_cache_info[index].ref_count--; -+ mutex_unlock (&disk_cache_lock); -+} -+ -+/* Not used. */ -+int -+disk_cache_block_is_ref (block_t block) -+{ -+ int ref; -+ void *ptr; -+ -+ mutex_lock (&disk_cache_lock); -+ ptr = hurd_ihash_find (disk_cache_bptr, block); -+ if (! ptr) -+ ref = 0; -+ else /* XXX: Should check for DC_UNTOUCHED too. */ -+ ref = disk_cache_info[bptr_index (ptr)].ref_count; -+ mutex_unlock (&disk_cache_lock); -+ -+ return ref; -+} -+ - /* Create the DISK pager. */ - void - create_disk_pager (void) -@@ -774,8 +1197,12 @@ - ext2_panic ("can't create disk pager: %s", strerror (errno)); - upi->type = DISK; - pager_bucket = ports_create_bucket (); -- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size, -- &disk_image); -+ 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, -+ disk_cache_size, &disk_cache); -+ disk_cache_init (); - } - - /* Call this to create a FILE_DATA pager and return a send right. -@@ -815,7 +1242,7 @@ - diskfs_nref_light (node); - node->dn->pager = - pager_create (upi, pager_bucket, MAY_CACHE, -- MEMORY_OBJECT_COPY_DELAY); -+ MEMORY_OBJECT_COPY_DELAY, 0); - if (node->dn->pager == 0) - { - diskfs_nrele_light (node); -Index: hurd-debian/ext2fs/pokel.c -=================================================================== ---- hurd-debian.orig/ext2fs/pokel.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/pokel.c 2012-07-10 01:39:22.000000000 +0000 -@@ -67,12 +67,27 @@ - vm_offset_t p_offs = pl->offset; - vm_size_t p_end = p_offs + pl->length; - -- if (p_offs == offset && p_end == end) -- break; -+ if (p_offs <= offset && end <= p_end) -+ { -+ if (pokel->image == disk_cache) -+ for (vm_offset_t i = offset; i < end; i += block_size) -+ disk_cache_block_deref (disk_cache + i); -+ -+ break; -+ } - else if (p_end >= offset && end >= p_offs) - { - pl->offset = offset < p_offs ? offset : p_offs; - pl->length = (end > p_end ? end : p_end) - pl->offset; -+ -+ if (pokel->image == disk_cache) -+ { -+ vm_offset_t i_begin = p_offs > offset ? p_offs : offset; -+ vm_offset_t i_end = p_end < end ? p_end : end; -+ for (vm_offset_t i = i_begin; i < i_end; i += block_size) -+ disk_cache_block_deref (disk_cache + i); -+ } -+ - ext2_debug ("extended 0x%x[%ul] to 0x%x[%ul]", - p_offs, p_end - p_offs, pl->offset, pl->length); - break; -@@ -106,18 +121,28 @@ - _pokel_exec (struct pokel *pokel, int sync, int wait) - { - struct poke *pl, *pokes, *last = NULL; -- -+ - pthread_spin_lock (&pokel->lock); - pokes = pokel->pokes; - pokel->pokes = NULL; - pthread_spin_unlock (&pokel->lock); - - for (pl = pokes; pl; last = pl, pl = pl->next) -- if (sync) -- { -- ext2_debug ("syncing 0x%x[%ul]", pl->offset, pl->length); -- pager_sync_some (pokel->pager, pl->offset, pl->length, wait); -- } -+ { -+ if (sync) -+ { -+ ext2_debug ("syncing 0x%x[%ul]", pl->offset, pl->length); -+ pager_sync_some (pokel->pager, pl->offset, pl->length, wait); -+ } -+ -+ if (pokel->image == disk_cache) -+ { -+ vm_offset_t begin = trunc_block (pl->offset); -+ vm_offset_t end = round_block (pl->offset + pl->length); -+ for (vm_offset_t i = begin; i != end; i += block_size) -+ disk_cache_block_deref (pokel->image + i); -+ } -+ } - - if (last) - { -Index: hurd-debian/ext2fs/truncate.c -=================================================================== ---- hurd-debian.orig/ext2fs/truncate.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/ext2fs/truncate.c 2012-07-10 01:39:22.000000000 +0000 -@@ -124,7 +124,7 @@ - { - unsigned index; - int modified = 0, all_freed = 1; -- block_t *ind_bh = (block_t *)bptr (*p); -+ block_t *ind_bh = (block_t *)disk_cache_block_ref (*p); - unsigned first = end < offset ? 0 : end - offset; - - for (index = first; index < addr_per_block; index++) -@@ -139,11 +139,16 @@ - - if (first == 0 && all_freed) - { -- pager_flush_some (diskfs_disk_pager, boffs (*p), block_size, 1); -+ pager_flush_some (diskfs_disk_pager, -+ bptr_index (ind_bh) << log2_block_size, -+ block_size, 1); - free_block_run_free_ptr (fbr, p); -+ disk_cache_block_deref (ind_bh); - } - else if (modified) - record_indir_poke (node, ind_bh); -+ else -+ disk_cache_block_deref (ind_bh); - } - } - -@@ -218,7 +223,7 @@ - /* Flush all the data past the new size from the kernel. Also force any - delayed copies of this data to take place immediately. (We are implicitly - changing the data to zeros and doing it without the kernel's immediate -- knowledge; accordingl we must help out the kernel thusly.) */ -+ knowledge; accordingly we must help out the kernel thusly.) */ - static void - force_delayed_copies (struct node *node, off_t length) - { -Index: hurd-debian/fatfs/pager.c -=================================================================== ---- hurd-debian.orig/fatfs/pager.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/fatfs/pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -596,6 +596,13 @@ - return 0; - } - -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page) -+{ -+ assert (!"unrequested notification on eviction"); -+} -+ - /* Grow the disk allocated to locked node NODE to be at least SIZE - bytes, and set NODE->allocsize to the actual allocated size. (If - the allocated size is already SIZE bytes, do nothing.) CRED -@@ -752,7 +759,7 @@ - struct user_pager_info *upi = malloc (sizeof (struct user_pager_info)); - upi->type = FAT; - pager_bucket = ports_create_bucket (); -- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, -+ diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0, - bytes_per_sector * sectors_per_fat, - &fat_image); - } -@@ -794,7 +801,7 @@ - diskfs_nref_light (node); - node->dn->pager = - pager_create (upi, pager_bucket, MAY_CACHE, -- MEMORY_OBJECT_COPY_DELAY); -+ MEMORY_OBJECT_COPY_DELAY, 0); - if (node->dn->pager == 0) - { - diskfs_nrele_light (node); -Index: hurd-debian/isofs/pager.c -=================================================================== ---- hurd-debian.orig/isofs/pager.c 2012-07-10 01:33:10.000000000 +0000 -+++ hurd-debian/isofs/pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -94,6 +94,13 @@ - return EROFS; - } - -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page) -+{ -+ assert (!"unrequested notification on eviction"); -+} -+ - /* Tell how big the file is. */ - error_t - pager_report_extent (struct user_pager_info *pager, -@@ -137,7 +144,7 @@ - upi->type = DISK; - upi->np = 0; - pager_bucket = ports_create_bucket (); -- diskfs_start_disk_pager (upi, pager_bucket, 1, store->size, &disk_image); -+ diskfs_start_disk_pager (upi, pager_bucket, 1, 0, store->size, &disk_image); - upi->p = diskfs_disk_pager; - } - -@@ -168,7 +175,8 @@ - upi->type = FILE_DATA; - upi->np = np; - diskfs_nref_light (np); -- upi->p = pager_create (upi, pager_bucket, 1, MEMORY_OBJECT_COPY_DELAY); -+ upi->p = pager_create (upi, pager_bucket, 1, -+ MEMORY_OBJECT_COPY_DELAY, 0); - if (upi->p == 0) - { - diskfs_nrele_light (np); -Index: hurd-debian/libdiskfs/disk-pager.c -=================================================================== ---- hurd-debian.orig/libdiskfs/disk-pager.c 2012-07-10 01:33:11.000000000 +0000 -+++ hurd-debian/libdiskfs/disk-pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -46,7 +46,8 @@ - - void - diskfs_start_disk_pager (struct user_pager_info *upi, -- struct port_bucket *pager_bucket, int may_cache, -+ struct port_bucket *pager_bucket, -+ int may_cache, int notify_on_evict, - size_t size, void **image) - { - pthread_t thread; -@@ -68,7 +69,8 @@ - - /* Create the pager. */ - diskfs_disk_pager = pager_create (upi, pager_bucket, -- may_cache, MEMORY_OBJECT_COPY_NONE); -+ may_cache, MEMORY_OBJECT_COPY_NONE, -+ notify_on_evict); - assert (diskfs_disk_pager); - - /* Get a port to the disk pager. */ -Index: hurd-debian/libdiskfs/diskfs-pager.h -=================================================================== ---- hurd-debian.orig/libdiskfs/diskfs-pager.h 2012-07-10 01:33:11.000000000 +0000 -+++ hurd-debian/libdiskfs/diskfs-pager.h 2012-07-10 01:39:22.000000000 +0000 -@@ -33,7 +33,8 @@ - mapped is returned in IMAGE. INFO, PAGER_BUCKET, & MAY_CACHE are passed - to `pager_create'. */ - extern void diskfs_start_disk_pager (struct user_pager_info *info, -- struct port_bucket *pager_bucket, int may_cache, -+ struct port_bucket *pager_bucket, -+ int may_cache, int notify_on_evict, - size_t size, void **image); - - extern struct pager *diskfs_disk_pager; -Index: hurd-debian/libpager/data-request.c -=================================================================== ---- hurd-debian.orig/libpager/data-request.c 2012-11-26 00:23:28.000000000 +0000 -+++ hurd-debian/libpager/data-request.c 2012-11-26 00:24:49.000000000 +0000 -@@ -40,11 +40,11 @@ - if (!p) - return EOPNOTSUPP; - -- /* Acquire the right to meddle with the pagemap */ -+ /* Acquire the right to meddle with the pagemap. */ - pthread_mutex_lock (&p->interlock); - _pager_wait_for_seqno (p, seqno); - -- /* sanity checks -- we don't do multi-page requests yet. */ -+ /* Sanity checks -- we don't do multi-page requests yet. */ - if (control != p->memobjcntl) - { - printf ("incg data request: wrong control port\n"); -@@ -119,7 +119,8 @@ - goto error_read; - - memory_object_data_supply (p->memobjcntl, offset, page, length, 1, -- write_lock ? VM_PROT_WRITE : VM_PROT_NONE, 0, -+ write_lock ? VM_PROT_WRITE : VM_PROT_NONE, -+ p->notify_on_evict ? 1 : 0, - MACH_PORT_NULL); - pthread_mutex_lock (&p->interlock); - _pager_mark_object_error (p, offset, length, 0); -Index: hurd-debian/libpager/data-return.c -=================================================================== ---- hurd-debian.orig/libpager/data-return.c 2012-11-26 00:23:28.000000000 +0000 -+++ hurd-debian/libpager/data-return.c 2012-11-26 00:24:49.000000000 +0000 -@@ -39,6 +39,7 @@ - struct pager *p; - short *pm_entries; - int npages, i; -+ char *notified; - error_t *pagerrs; - struct lock_request *lr; - struct lock_list {struct lock_request *lr; -@@ -71,9 +72,6 @@ - goto release_out; - } - -- if (! dirty) -- goto release_out; -- - if (p->pager_state != NORMAL) - { - printf ("pager in wrong state for write\n"); -@@ -83,6 +81,11 @@ - npages = length / __vm_page_size; - pagerrs = alloca (npages * sizeof (error_t)); - -+ notified = alloca (npages * (sizeof *notified)); -+#ifndef NDEBUG -+ memset (notified, -1, npages * (sizeof *notified)); -+#endif -+ - _pager_block_termination (p); /* until we are done with the pagemap - when the write completes. */ - -@@ -90,6 +93,24 @@ - - pm_entries = &p->pagemap[offset / __vm_page_size]; - -+ if (! dirty) -+ { -+ munmap ((caddr_t) data, length); -+ if (!kcopy) { -+ /* Prepare notified array. */ -+ for (i = 0; i < npages; i++) -+ notified[i] = (p->notify_on_evict -+ && ! (pm_entries[i] & PM_PAGEINWAIT)); -+ -+ _pager_release_seqno (p, seqno); -+ goto notify; -+ } -+ else { -+ _pager_allow_termination (p); -+ goto release_out; -+ } -+ } -+ - /* Make sure there are no other in-progress writes for any of these - pages before we begin. This imposes a little more serialization - than we really have to require (because *all* future writes on -@@ -120,10 +141,6 @@ - for (i = 0; i < npages; i++) - pm_entries[i] |= PM_PAGINGOUT | PM_INIT; - -- if (!kcopy) -- for (i = 0; i < npages; i++) -- pm_entries[i] &= ~PM_INCORE; -- - /* If this write occurs while a lock is pending, record - it. We have to keep this list because a lock request - might come in while we do the I/O; in that case there -@@ -163,7 +180,10 @@ - for (i = 0; i < npages; i++) - { - if (omitdata & (1 << i)) -- continue; -+ { -+ notified[i] = 0; -+ continue; -+ } - - if (pm_entries[i] & PM_WRITEWAIT) - wakeup = 1; -@@ -179,14 +199,22 @@ - pm_entries[i] |= PM_INVALID; - - if (pm_entries[i] & PM_PAGEINWAIT) -- memory_object_data_supply (p->memobjcntl, -- offset + (vm_page_size * i), -- data + (vm_page_size * i), -- vm_page_size, 1, -- VM_PROT_NONE, 0, MACH_PORT_NULL); -+ { -+ memory_object_data_supply (p->memobjcntl, -+ offset + (vm_page_size * i), -+ data + (vm_page_size * i), -+ vm_page_size, 1, -+ VM_PROT_NONE, 0, MACH_PORT_NULL); -+ notified[i] = 0; -+ } - else -- munmap ((caddr_t) (data + (vm_page_size * i)), -- vm_page_size); -+ { -+ munmap ((caddr_t) (data + (vm_page_size * i)), -+ vm_page_size); -+ notified[i] = (! kcopy && p->notify_on_evict); -+ if (! kcopy) -+ pm_entries[i] &= ~PM_INCORE; -+ } - - pm_entries[i] &= ~(PM_PAGINGOUT | PM_PAGEINWAIT | PM_WRITEWAIT); - } -@@ -198,10 +226,29 @@ - if (wakeup) - pthread_cond_broadcast (&p->wakeup); - -+ notify: - _pager_allow_termination (p); -- - pthread_mutex_unlock (&p->interlock); - -+ for (i = 0; i < npages; i++) -+ { -+ assert (notified[i] == 0 || notified[i] == 1); -+ if (notified[i]) -+ { -+ short *pm_entry = &pm_entries[i]; -+ -+ /* Do notify user. */ -+ pager_notify_evict (p->upi, offset + (i * vm_page_size)); -+ -+ /* Clear any error that is left. Notification on eviction -+ is used only to change association of page, so any -+ error may no longer be valid. */ -+ mutex_lock (&p->interlock); -+ *pm_entry = SET_PM_ERROR (SET_PM_NEXTERROR (*pm_entry, 0), 0); -+ mutex_unlock (&p->interlock); -+ } -+ } -+ - ports_port_deref (p); - return 0; - -Index: hurd-debian/libpager/pager-create.c -=================================================================== ---- hurd-debian.orig/libpager/pager-create.c 2012-07-10 01:33:11.000000000 +0000 -+++ hurd-debian/libpager/pager-create.c 2012-07-10 01:39:22.000000000 +0000 -@@ -22,7 +22,8 @@ - pager_create (struct user_pager_info *upi, - struct port_bucket *bucket, - boolean_t may_cache, -- memory_object_copy_strategy_t copy_strategy) -+ memory_object_copy_strategy_t copy_strategy, -+ boolean_t notify_on_evict) - { - struct pager *p; - -@@ -38,6 +39,7 @@ - p->attribute_requests = 0; - p->may_cache = may_cache; - p->copy_strategy = copy_strategy; -+ p->notify_on_evict = notify_on_evict; - p->memobjcntl = MACH_PORT_NULL; - p->memobjname = MACH_PORT_NULL; - p->seqno = -1; -Index: hurd-debian/libpager/pager.h -=================================================================== ---- hurd-debian.orig/libpager/pager.h 2012-07-10 01:33:11.000000000 +0000 -+++ hurd-debian/libpager/pager.h 2012-07-10 01:39:22.000000000 +0000 -@@ -32,18 +32,21 @@ - mach_msg_header_t *outp); - - /* Create a new pager. The pager will have a port created for it -- (using libports, in BUCKET) and will be immediately ready -- to receive requests. U_PAGER will be provided to later calls to -+ (using libports, in BUCKET) and will be immediately ready to -+ receive requests. U_PAGER will be provided to later calls to - pager_find_address. The pager will have one user reference - created. MAY_CACHE and COPY_STRATEGY are the original values of -- those attributes as for memory_object_ready. Users may create -- references to pagers by use of the relevant ports library -- functions. On errors, return null and set errno. */ -+ those attributes as for memory_object_ready. If NOTIFY_ON_EVICT is -+ non-zero, pager_notify_evict user callback will be called when page -+ is evicted. Users may create references to pagers by use of the -+ relevant ports library functions. On errors, return null and set -+ errno. */ - struct pager * - pager_create (struct user_pager_info *u_pager, - struct port_bucket *bucket, - boolean_t may_cache, -- memory_object_copy_strategy_t copy_strategy); -+ memory_object_copy_strategy_t copy_strategy, -+ boolean_t notify_on_evict); - - /* Return the user_pager_info struct associated with a pager. */ - struct user_pager_info * -@@ -110,7 +113,7 @@ - /* Change the attributes of the memory object underlying pager PAGER. - Args MAY_CACHE and COPY_STRATEGY are as for - memory_object_change_atributes. Wait for the kernel to report completion -- off WAIT is set.*/ -+ iff WAIT is set. */ - void - pager_change_attributes (struct pager *pager, - boolean_t may_cache, -@@ -172,6 +175,18 @@ - pager_unlock_page (struct user_pager_info *pager, - vm_offset_t address); - -+/* The user must define this function. It is used when you want be -+ able to change association of pages to backing store. To use it, -+ pass non-zero value in NOTIFY_ON_EVICT when pager is created with -+ pager_create. You can change association of page only when -+ pager_notify_evict has been called and you haven't touched page -+ content after that. Note there is a possibility that a page is -+ evicted, but user is not notified about that. The user should be -+ able to handle this case. */ -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page); -+ - /* The user must define this function. It should report back (in - *OFFSET and *SIZE the minimum valid address the pager will accept - and the size of the object. */ -Index: hurd-debian/libpager/priv.h -=================================================================== ---- hurd-debian.orig/libpager/priv.h 2012-07-10 01:33:11.000000000 +0000 -+++ hurd-debian/libpager/priv.h 2012-07-10 01:39:22.000000000 +0000 -@@ -48,6 +48,7 @@ - - boolean_t may_cache; - memory_object_copy_strategy_t copy_strategy; -+ boolean_t notify_on_evict; - - /* Interface ports */ - memory_object_control_t memobjcntl; -Index: hurd-debian/storeio/pager.c -=================================================================== ---- hurd-debian.orig/storeio/pager.c 2012-07-10 01:33:12.000000000 +0000 -+++ hurd-debian/storeio/pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -109,6 +109,13 @@ - return 0; - } - -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page) -+{ -+ assert (!"unrequested notification on eviction"); -+} -+ - /* The user must define this function. It should report back (in - *OFFSET and *SIZE the minimum valid address the pager will accept - and the size of the object. */ -@@ -232,7 +239,7 @@ - { - dev->pager = - pager_create ((struct user_pager_info *)dev, pager_port_bucket, -- 1, MEMORY_OBJECT_COPY_DELAY); -+ 1, MEMORY_OBJECT_COPY_DELAY, 0); - if (dev->pager == NULL) - { - pthread_mutex_unlock (&dev->pager_lock); -Index: hurd-debian/tmpfs/pager-stubs.c -=================================================================== ---- hurd-debian.orig/tmpfs/pager-stubs.c 2012-11-26 00:23:28.000000000 +0000 -+++ hurd-debian/tmpfs/pager-stubs.c 2012-11-26 00:24:49.000000000 +0000 -@@ -57,6 +57,14 @@ - return EIEIO; - } - -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page) -+{ -+ abort(); -+} -+ -+ - /* The user must define this function. It should report back (in - *OFFSET and *SIZE the minimum valid address the pager will accept - and the size of the object. */ -Index: hurd-debian/ufs/pager.c -=================================================================== ---- hurd-debian.orig/ufs/pager.c 2012-07-10 01:33:12.000000000 +0000 -+++ hurd-debian/ufs/pager.c 2012-07-10 01:39:22.000000000 +0000 -@@ -425,6 +425,13 @@ - return err; - } - -+void -+pager_notify_evict (struct user_pager_info *pager, -+ vm_offset_t page) -+{ -+ assert (!"unrequested notification on eviction"); -+} -+ - /* Implement the pager_report_extent callback from the pager library. See - <hurd/pager.h> for the interface description. */ - inline error_t -@@ -477,7 +484,7 @@ - upi->type = DISK; - upi->np = 0; - pager_bucket = ports_create_bucket (); -- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size, -+ diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0, store->size, - &disk_image); - upi->p = diskfs_disk_pager; - } -@@ -570,7 +577,7 @@ - upi->unlocked_pagein_length = 0; - diskfs_nref_light (np); - upi->p = pager_create (upi, pager_bucket, -- MAY_CACHE, MEMORY_OBJECT_COPY_DELAY); -+ MAY_CACHE, MEMORY_OBJECT_COPY_DELAY, 0); - if (upi->p == 0) - { - diskfs_nrele_light (np); diff --git a/debian/patches/ext2fs_large_stores_pthread.patch b/debian/patches/ext2fs_large_stores_pthread.patch deleted file mode 100644 index 71f76a34..00000000 --- a/debian/patches/ext2fs_large_stores_pthread.patch +++ /dev/null @@ -1,344 +0,0 @@ -commit 93691ae1ae88c2d66d240b50e3ea5827f8a96c22 -Author: Richard Braun <rbraun@sceen.net> -Date: Mon Sep 3 22:19:16 2012 +0200 - - Move large storage patch to pthreads - -TODO: merge into ext2fs_large_stores.patch. - -Index: hurd-debian/ext2fs/ext2fs.h -=================================================================== ---- hurd-debian.orig/ext2fs/ext2fs.h 2012-11-26 00:24:49.000000000 +0000 -+++ hurd-debian/ext2fs/ext2fs.h 2012-11-26 00:24:58.000000000 +0000 -@@ -260,9 +260,9 @@ - /* Metadata about cached block. */ - extern struct disk_cache_info *disk_cache_info; - /* Lock for these mappings */ --extern struct mutex disk_cache_lock; -+extern pthread_mutex_t disk_cache_lock; - /* Fired when a re-association is done. */ --extern struct condition disk_cache_reassociation; -+extern pthread_cond_t disk_cache_reassociation; - - void *disk_cache_block_ref (block_t block); - void disk_cache_block_ref_ptr (void *ptr); -@@ -345,9 +345,9 @@ - boffs_ptr (off_t offset) - { - block_t block = boffs_block (offset); -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - char *ptr = hurd_ihash_find (disk_cache_bptr, block); -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - assert (ptr); - ptr += offset % block_size; - ext2_debug ("(%Ld) = %p", offset, ptr); -@@ -361,12 +361,12 @@ bptr_offs (void *ptr) - vm_offset_t mem_offset = (char *)ptr - (char *)disk_cache; - off_t offset; - assert (mem_offset < disk_cache_size); -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - offset = (off_t) disk_cache_info[boffs_block (mem_offset)].block - << log2_block_size; - assert (offset || mem_offset < block_size); - offset += mem_offset % block_size; -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - ext2_debug ("(%p) = %Ld", ptr, offset); - return offset; - } -diff --git a/ext2fs/pager.c b/ext2fs/pager.c -index 2bec88d..67c9922 100644 ---- a/ext2fs/pager.c -+++ b/ext2fs/pager.c -@@ -418,7 +418,7 @@ disk_pager_read_page (vm_offset_t page, void **buf, int *writelock) - size_t length = vm_page_size, read = 0; - store_offset_t offset = page, dev_end = store->size; - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - int index = offset >> log2_block_size; - offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size) - + offset % block_size; -@@ -430,7 +430,7 @@ disk_pager_read_page (vm_offset_t page, void **buf, int *writelock) - = disk_cache_info[index].block ^ DISK_CACHE_LAST_READ_XOR; - #endif - ext2_debug ("(%Ld)", offset >> log2_block_size); -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - if (offset + vm_page_size > dev_end) - length = dev_end - offset; -@@ -454,7 +454,7 @@ disk_pager_write_page (vm_offset_t page, void *buf) - size_t length = vm_page_size, amount; - store_offset_t offset = page, dev_end = store->size; - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - int index = offset >> log2_block_size; - assert (disk_cache_info[index].block != DC_NO_BLOCK); - offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size) -@@ -465,7 +465,7 @@ disk_pager_write_page (vm_offset_t page, void *buf) - assert (disk_cache_info[index].last_read - == disk_cache_info[index].block); - #endif -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - if (offset + vm_page_size > dev_end) - length = dev_end - offset; -@@ -526,9 +526,9 @@ disk_pager_notify_evict (vm_offset_t page) - - ext2_debug ("(block %u)", index); - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - disk_cache_info[index].flags &= ~DC_INCORE; -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - } - - /* Satisfy a pager read request for either the disk pager or file pager -@@ -836,9 +836,9 @@ - /* Hint index for which cache block to reuse next. */ - int disk_cache_hint; - /* Lock for these structures. */ --struct mutex disk_cache_lock; -+pthread_mutex_t disk_cache_lock; - /* Fired when a re-association is done. */ --struct condition disk_cache_reassociation; -+pthread_cond_t disk_cache_reassociation; - - /* Finish mapping initialization. */ - static void -@@ -848,8 +848,8 @@ - ext2_panic ("Block size %d != vm_page_size %d", - block_size, vm_page_size); - -- mutex_init (&disk_cache_lock); -- condition_init (&disk_cache_reassociation); -+ pthread_mutex_init (&disk_cache_lock, NULL); -+ pthread_cond_init (&disk_cache_reassociation, NULL); - - /* Allocate space for block num -> in-memory pointer mapping. */ - if (hurd_ihash_create (&disk_cache_bptr, HURD_IHASH_NO_LOCP)) -@@ -905,7 +905,7 @@ - - /* Return unused pages that are in core. */ - int pending_begin = -1, pending_end = -1; -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - for (index = 0; index < disk_cache_blocks; index++) - if (! (disk_cache_info[index].flags & (DC_DONT_REUSE & ~DC_INCORE)) - && ! disk_cache_info[index].ref_count) -@@ -916,13 +916,13 @@ disk_cache_return_unused (void) - /* Return previous region, if there is such, ... */ - if (pending_end >= 0) - { -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - pager_return_some (diskfs_disk_pager, - pending_begin * vm_page_size, - (pending_end - pending_begin) - * vm_page_size, - 1); -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - } - /* ... and start new region. */ - pending_begin = index; -@@ -930,7 +930,7 @@ disk_cache_return_unused (void) - pending_end = index + 1; - } - -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - /* Return last region, if there is such. */ - if (pending_end >= 0) -@@ -958,7 +958,7 @@ disk_cache_block_ref (block_t block) - - ext2_debug ("(%u)", block); - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - - bptr = hurd_ihash_find (disk_cache_bptr, block); - if (bptr) -@@ -971,8 +971,8 @@ - if (disk_cache_info[index].flags & DC_UNTOUCHED) - { - /* Wait re-association to finish. */ -- condition_wait (&disk_cache_reassociation, &disk_cache_lock); -- mutex_unlock (&disk_cache_lock); -+ pthread_cond_wait (&disk_cache_reassociation, &disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - #if 0 - printf ("Re-association -- wait finished.\n"); -@@ -992,7 +992,7 @@ - disk_cache_info[index].ref_count, - disk_cache_info[index].flags, bptr); - -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - return bptr; - } -@@ -1030,7 +1030,7 @@ disk_cache_block_ref (block_t block) - { - ext2_debug ("flush %u -> %d", disk_cache_info[index].block, index); - -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - disk_cache_return_unused (); - -@@ -1050,9 +1050,9 @@ disk_cache_block_ref (block_t block) - - #if 0 /* XXX: Let's see if this is needed at all. */ - -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - pager_return_some (diskfs_disk_pager, bptr - disk_cache, vm_page_size, 1); -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - - /* Has someone used our bptr? Has someone mapped requested block - while we have unlocked disk_cache_lock? If so, environment has -@@ -1060,7 +1060,7 @@ disk_cache_block_ref (block_t block) - if ((! (disk_cache_info[index].flags & DC_UNTOUCHED)) - || hurd_ihash_find (disk_cache_bptr, block)) - { -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - return disk_cache_block_ref (block); /* tail recursion */ - } - -@@ -1068,15 +1068,15 @@ disk_cache_block_ref (block_t block) - - /* XXX: Use libpager internals. */ - -- mutex_lock (&diskfs_disk_pager->interlock); -+ pthread_mutex_lock (&diskfs_disk_pager->interlock); - int page = (bptr - disk_cache) / vm_page_size; - assert (page >= 0); - int is_incore = (page < diskfs_disk_pager->pagemapsize - && (diskfs_disk_pager->pagemap[page] & PM_INCORE)); -- mutex_unlock (&diskfs_disk_pager->interlock); -+ pthread_mutex_unlock (&diskfs_disk_pager->interlock); - if (is_incore) - { -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - printf ("INCORE\n"); - return disk_cache_block_ref (block); /* tail recursion */ - } -@@ -1096,13 +1096,13 @@ disk_cache_block_ref (block_t block) - disk_cache_info[index].ref_count = 1; - - /* All data structures are set up. */ -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - /* Try to read page. */ - *(volatile char *) bptr; - - /* Check if it's actually read. */ -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - if (disk_cache_info[index].flags & DC_UNTOUCHED) - /* It's not read. */ - { -@@ -1111,7 +1111,7 @@ disk_cache_block_ref (block_t block) - disk_cache_info[index].block = DC_NO_BLOCK; - disk_cache_info[index].flags &=~ DC_UNTOUCHED; - disk_cache_info[index].ref_count = 0; -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - /* Prepare next time association of this page to succeed. */ - pager_flush_some (diskfs_disk_pager, bptr - disk_cache, -@@ -1124,10 +1124,10 @@ disk_cache_block_ref (block_t block) - /* Try again. */ - return disk_cache_block_ref (block); /* tail recursion */ - } -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - /* Re-association was successful. */ -- condition_broadcast (&disk_cache_reassociation); -+ pthread_cond_broadcast (&disk_cache_reassociation); - - ext2_debug ("(%u) = %p", block, bptr); - return bptr; -@@ -1139,7 +1139,7 @@ - { - int index; - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - index = bptr_index (ptr); - assert (disk_cache_info[index].ref_count >= 1); - assert (disk_cache_info[index].ref_count + 1 -@@ -1149,7 +1149,7 @@ disk_cache_block_ref_ptr (void *ptr) - ptr, - disk_cache_info[index].ref_count, - disk_cache_info[index].flags); -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - } - - void -@@ -1159,7 +1159,7 @@ disk_cache_block_deref (void *ptr) - - assert (disk_cache <= ptr && ptr <= disk_cache + disk_cache_size); - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - index = bptr_index (ptr); - ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)", - ptr, -@@ -1168,7 +1168,7 @@ disk_cache_block_deref (void *ptr) - assert (! (disk_cache_info[index].flags & DC_UNTOUCHED)); - assert (disk_cache_info[index].ref_count >= 1); - disk_cache_info[index].ref_count--; -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - } - - /* Not used. */ -@@ -1179,13 +1179,13 @@ disk_cache_block_is_ref (block_t block) - int ref; - void *ptr; - -- mutex_lock (&disk_cache_lock); -+ pthread_mutex_lock (&disk_cache_lock); - ptr = hurd_ihash_find (disk_cache_bptr, block); - if (! ptr) - ref = 0; - else /* XXX: Should check for DC_UNTOUCHED too. */ - ref = disk_cache_info[bptr_index (ptr)].ref_count; -- mutex_unlock (&disk_cache_lock); -+ pthread_mutex_unlock (&disk_cache_lock); - - return ref; - } -diff --git a/libpager/data-return.c b/libpager/data-return.c -index 24533e7..0d71db7 100644 ---- a/libpager/data-return.c -+++ b/libpager/data-return.c -@@ -243,9 +243,9 @@ _pager_do_write_request (mach_port_t object, - /* Clear any error that is left. Notification on eviction - is used only to change association of page, so any - error may no longer be valid. */ -- mutex_lock (&p->interlock); -+ pthread_mutex_lock (&p->interlock); - *pm_entry = SET_PM_ERROR (SET_PM_NEXTERROR (*pm_entry, 0), 0); -- mutex_unlock (&p->interlock); -+ pthread_mutex_unlock (&p->interlock); - } - } - diff --git a/debian/patches/mount-f.patch b/debian/patches/mount-f.patch deleted file mode 100644 index aabc47b7..00000000 --- a/debian/patches/mount-f.patch +++ /dev/null @@ -1,88 +0,0 @@ -Add -f and --fake arguments. This makes our mount more compatible with -Linux mount. - -* utils/mount.c (argp_opts): Add -f and --fake. -(do_mount): Fake the translator startup if --fake is given. ---- - utils/mount.c | 29 ++++++++++++++++++++++++++++- - 1 file changed, 28 insertions(+), 1 deletion(-) - -diff --git a/utils/mount.c b/utils/mount.c -index f1d5750..f8928f1 100644 ---- a/utils/mount.c -+++ b/utils/mount.c -@@ -24,6 +24,7 @@ - #include <error.h> - #include <stdlib.h> - #include <fcntl.h> -+#include <unistd.h> - #include <hurd/fsys.h> - #include <hurd/fshelp.h> - #include <hurd/paths.h> -@@ -34,6 +35,7 @@ - static char *fstype = DEFAULT_FSTYPE; - static char *device, *mountpoint; - static int verbose; -+static int fake; - static char *options; - static size_t options_len; - static mach_msg_timeout_t timeout; -@@ -55,6 +57,7 @@ static const struct argp_option argp_opts[] = - {"remount", 0, 0, OPTION_ALIAS}, - {"verbose", 'v', 0, 0, "Give more detailed information"}, - {"no-mtab", 'n', 0, 0, "Do not update /etc/mtab"}, -+ {"fake", 'f', 0, 0, "Do not actually mount, just pretend"}, - {0, 0} - }; - -@@ -115,6 +118,10 @@ parse_opt (int key, char *arg, struct argp_state *state) - /* do nothing */ - break; - -+ case 'f': -+ fake = 1; -+ break; -+ - case ARGP_KEY_ARG: - if (mountpoint == 0) /* One arg: mountpoint */ - mountpoint = arg; -@@ -312,7 +319,10 @@ do_mount (struct fs *fs, int remount) - return 0; - } - -- if (mounted != MACH_PORT_NULL) -+ /* Do not fail if there is an active translator if --fake is -+ given. This mimics Linux mount utility more closely which -+ just looks into the mtab file. */ -+ if (mounted != MACH_PORT_NULL && !fake) - { - error (0, 0, "%s already mounted", fs->mntent.mnt_fsname); - return EBUSY; -@@ -342,6 +352,23 @@ do_mount (struct fs *fs, int remount) - - /* Now we have a translator command line argz in FSOPTS. */ - -+ if (fake) { -+ /* Fake the translator startup. */ -+ mach_port_t underlying; -+ mach_msg_type_name_t underlying_type; -+ err = open_node (O_READ, &underlying, &underlying_type, 0, NULL); -+ if (err) -+ error (1, errno, "cannot mount on %s", fs->mntent.mnt_dir); -+ -+ mach_port_deallocate (mach_task_self (), underlying); -+ -+ /* See if the translator is at least executable. */ -+ if (access(type->program, X_OK) == -1) -+ error (1, errno, "can not execute %s", type->program); -+ -+ return 0; -+ } -+ - explain ("settrans -a"); - err = fshelp_start_translator (open_node, NULL, fsopts, - fsopts, fsopts_len, timeout, --- -1.7.10.4 - - diff --git a/debian/patches/mount-ignore-mounted-all.patch b/debian/patches/mount-ignore-mounted-all.patch deleted file mode 100644 index b3890d4a..00000000 --- a/debian/patches/mount-ignore-mounted-all.patch +++ /dev/null @@ -1,32 +0,0 @@ -Linux' mount utility ignores mounted filesystems if mount --all is -invoked. This patch makes our mount do the same. - -utils/mount.c (main): Ignore mounted filesystems if --all is given. ---- - utils/mount.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/utils/mount.c b/utils/mount.c -index 73a7539..77b2138 100644 ---- a/utils/mount.c -+++ b/utils/mount.c -@@ -631,6 +631,15 @@ main (int argc, char **argv) - - if (! match_options (&fs->mntent)) - continue; -+ -+ fsys_t mounted; -+ err = fs_fsys (fs, &mounted); -+ if (err) -+ error (0, err, "cannot determine if %s is already mounted", -+ fs->mntent.mnt_fsname); -+ -+ if (mounted != MACH_PORT_NULL) -+ continue; - } - err |= do_mount (fs, remount); - } --- -1.7.10.4 - - diff --git a/debian/patches/mount-n.patch b/debian/patches/mount-n.patch deleted file mode 100644 index 9b860877..00000000 --- a/debian/patches/mount-n.patch +++ /dev/null @@ -1,37 +0,0 @@ -Add -n and --no-mtab arguments. As we do not write an mtab file, this -is a trivial patch that just ignores this argument to be more -compatible with Linux mount. - -* utils/mount.c (argp_opts): Add -n and --no-mtab. -(parse_opt): Do nothing on 'n'. ---- - utils/mount.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/utils/mount.c b/utils/mount.c -index 8b059c2..ea30f7a 100644 ---- a/utils/mount.c -+++ b/utils/mount.c -@@ -54,6 +54,7 @@ static const struct argp_option argp_opts[] = - {"update", 'u', 0, 0, "Flush any meta-data cached in core"}, - {"remount", 0, 0, OPTION_ALIAS}, - {"verbose", 'v', 0, 0, "Give more detailed information"}, -+ {"no-mtab", 'n', 0, 0, "Do not update /etc/mtab"}, - {0, 0} - }; - -@@ -110,6 +111,10 @@ parse_opt (int key, char *arg, struct argp_state *state) - } - break; - -+ case 'n': -+ /* do nothing */ -+ break; -+ - case ARGP_KEY_ARG: - if (mountpoint == 0) /* One arg: mountpoint */ - mountpoint = arg; --- -1.7.10.4 - - diff --git a/debian/patches/mount-remount.patch b/debian/patches/mount-remount.patch deleted file mode 100644 index 53eccb2b..00000000 --- a/debian/patches/mount-remount.patch +++ /dev/null @@ -1,67 +0,0 @@ -This fixes mount -oremount when just given the mountpoint, e. g.: - - % mount -oremount,ro /tmp - -* util/mount.c (main): Add a one-argument form for remount. ---- - utils/mount.c | 29 +++++++++++++++++++++++------ - 1 file changed, 23 insertions(+), 6 deletions(-) - -diff --git a/utils/mount.c b/utils/mount.c -index ea30f7a..f1d5750 100644 ---- a/utils/mount.c -+++ b/utils/mount.c -@@ -526,6 +526,12 @@ main (int argc, char **argv) - - fstab = fstab_argp_create (&fstab_params, SEARCH_FMTS, sizeof SEARCH_FMTS); - -+ /* This is a convenient way of checking for any `remount' options. */ -+ remount = 0; -+ err = argz_replace (&options, &options_len, "remount", "update", &remount); -+ if (err) -+ error (3, ENOMEM, "collecting mount options"); -+ - if (device) /* two-argument form */ - { - struct mntent m = -@@ -548,6 +554,23 @@ main (int argc, char **argv) - if (err) - error (2, err, "%s", mountpoint); - } -+ else if (mountpoint && remount) /* one-argument remount */ -+ { -+ struct mntent m = -+ { -+ mnt_fsname: mountpoint, /* since we cannot know the device, -+ using mountpoint here leads to more -+ helpful error messages */ -+ mnt_dir: mountpoint, -+ mnt_type: fstype, -+ mnt_opts: 0, -+ mnt_freq: 0, mnt_passno: 0 -+ }; -+ -+ err = fstab_add_mntent (fstab, &m, &fs); -+ if (err) -+ error (2, err, "%s", mountpoint); -+ } - else if (mountpoint) /* one-argument form */ - { - fs = fstab_find (fstab, mountpoint); -@@ -557,12 +580,6 @@ main (int argc, char **argv) - else - fs = 0; - -- /* This is a convenient way of checking for any `remount' options. */ -- remount = 0; -- err = argz_replace (&options, &options_len, "remount", "update", &remount); -- if (err) -- error (3, ENOMEM, "collecting mount options"); -- - if (fs != 0) - err = do_mount (fs, remount); - else --- -1.7.10.4 - - diff --git a/debian/patches/mount-t-auto.patch b/debian/patches/mount-t-auto.patch deleted file mode 100644 index 5f800f41..00000000 --- a/debian/patches/mount-t-auto.patch +++ /dev/null @@ -1,86 +0,0 @@ -Use libblkid to detect the filesystem type if "auto" is given as -type. Remove the translator localization from main, this is also done -in do_mount and any errors are propagated properly. This way "auto" is -handled correctly if given on the command line or used as filesystem -type in the fstab. - -* utils/mount.c (DEFAULT_FSTYPE): Use "auto" as default type. -(do_mount): Detect type using libblkid. -(main): Drop translator localization. ---- - utils/Makefile | 1 + - utils/mount.c | 27 +++++++++++++++++++-------- - 2 files changed, 20 insertions(+), 8 deletions(-) - -diff --git a/utils/Makefile b/utils/Makefile -index 6975fb5..207c904 100644 ---- a/utils/Makefile -+++ b/utils/Makefile -@@ -37,6 +37,7 @@ LDLIBS += -lpthread - login-LDLIBS = -lutil $(LIBCRYPT) - addauth-LDLIBS = $(LIBCRYPT) - setauth-LDLIBS = $(LIBCRYPT) -+mount-LDLIBS = -lblkid - - INSTALL-login-ops = -o root -m 4755 - INSTALL-ids-ops = -o root -m 4755 -diff --git a/utils/mount.c b/utils/mount.c -index 77b2138..5863f96 100644 ---- a/utils/mount.c -+++ b/utils/mount.c -@@ -28,11 +28,12 @@ - #include <hurd/fsys.h> - #include <hurd/fshelp.h> - #include <hurd/paths.h> -+#include <blkid/blkid.h> - - #include "match-options.h" - - #define SEARCH_FMTS _HURD "%sfs\0" _HURD "%s" --#define DEFAULT_FSTYPE "ext2" -+#define DEFAULT_FSTYPE "auto" - - static char *fstype = DEFAULT_FSTYPE; - static char *device, *mountpoint; -@@ -338,6 +339,23 @@ do_mount (struct fs *fs, int remount) - return EBUSY; - } - -+ if (strcmp (fs->mntent.mnt_type, "auto") == 0) -+ { -+ char *type = -+ blkid_get_tag_value (NULL, "TYPE", fs->mntent.mnt_fsname); -+ if (! type) -+ { -+ error (0, 0, "failed to detect file system type"); -+ return EFTYPE; -+ } -+ else -+ { -+ fs->mntent.mnt_type = strdup (type); -+ if (! fs->mntent.mnt_type) -+ error (3, ENOMEM, "failed to allocate memory"); -+ } -+ } -+ - err = fs_type (fs, &type); - if (err) - { -@@ -579,13 +597,6 @@ main (int argc, char **argv) - mnt_opts: 0, - mnt_freq: 0, mnt_passno: 0 - }; -- struct fstype *fst; -- -- err = fstypes_get (fstab->types, fstype, &fst); -- if (err) -- error (106, err, "cannot initialize type %s", fstype); -- if (fst->program == 0) -- error (2, 0, "filesystem type %s not recognized", fstype); - - err = fstab_add_mntent (fstab, &m, &fs); - if (err) --- -1.7.10.4 - - diff --git a/debian/patches/mount-test-opts.patch b/debian/patches/mount-test-opts.patch index e694b69f..d2e0f0e1 100644 --- a/debian/patches/mount-test-opts.patch +++ b/debian/patches/mount-test-opts.patch @@ -1,214 +1,13 @@ ---test-opts in combination with --all mounts only those filesystems -with options matching the given set of options. - -Note that the semantic of the inverting "no" prefix differs from ---types: While --types=nonfs,ufs means neither nfs nor ufs, ---test-opts=nofoo,bar means not foo, but bar. - -* utils/match-options.h: New file. -* utils/match-options.c: Likewise. -(test_opts): New variable. -(test_opts_len): Likewise. -(match_options): New function. -* utils/mount.c (parse_opt): Handle -O, --test-opts. -(main): Use match_options as filter. ---- - utils/Makefile | 5 ++-- - utils/match-options.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ - utils/match-options.h | 33 ++++++++++++++++++++++++ - utils/mount.c | 19 ++++++++++++-- - 4 files changed, 121 insertions(+), 4 deletions(-) - create mode 100644 utils/match-options.c - create mode 100644 utils/match-options.h - diff --git a/utils/Makefile b/utils/Makefile index e3bed0b..6975fb5 100644 --- a/utils/Makefile +++ b/utils/Makefile -@@ -28,7 +28,8 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ - uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \ +@@ -28,7 +28,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ -- rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh -+ rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ -+ match-options.c + rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ +- nullauth.c ++ nullauth.c match-options.c OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc -@@ -72,7 +73,7 @@ fakeauth-CPPFLAGS = -I$(srcdir)/../auth - authServer-CPPFLAGS = -I$(srcdir)/../auth - auth_requestUser-CPPFLAGS = -I$(srcdir)/../auth - --mount: ../sutils/fstab.o ../sutils/clookup.o \ -+mount: ../sutils/fstab.o ../sutils/clookup.o match-options.o \ - $(foreach L,fshelp ports,../lib$L/lib$L.a) - ../sutils/fstab.o ../sutils/clookup.o: FORCE - $(MAKE) -C $(@D) $(@F) -diff --git a/utils/match-options.c b/utils/match-options.c -new file mode 100644 -index 0000000..11fc9dc ---- /dev/null -+++ b/utils/match-options.c -@@ -0,0 +1,68 @@ -+/* Common functionality for the --test-opts flag of mount and umount. -+ -+ Copyright (C) 2013 Free Software Foundation, Inc. -+ Written by Justus Winter <4winter@informatik.uni-hamburg.de> -+ -+ 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 this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -+ -+#include <argz.h> -+#include <error.h> -+#include <stdlib.h> -+#include <string.h> -+ -+#include "match-options.h" -+ -+char *test_opts; -+size_t test_opts_len; -+ -+int -+match_options (struct mntent *mntent) -+{ -+ char *opts; -+ size_t opts_len; -+ -+ error_t err = argz_create_sep (mntent->mnt_opts, ',', &opts, &opts_len); -+ if (err) -+ error (3, err, "parsing mount options failed"); -+ -+ for (char *test = test_opts; -+ test; test = argz_next (test_opts, test_opts_len, test)) -+ { -+ char *needle = test; -+ int inverse = strncmp("no", needle, 2) == 0; -+ if (inverse) -+ needle += 2; -+ -+ int match = 0; -+ for (char *opt = opts; opt; opt = argz_next (opts, opts_len, opt)) -+ { -+ if (strcmp (opt, needle) == 0) { -+ if (inverse) -+ return 0; /* foo in opts, nofoo in test_opts. */ -+ -+ /* foo in opts, foo in test_opts, record match. */ -+ match = 1; -+ } -+ } -+ -+ if (! inverse && ! match) -+ return 0; /* No foo in opts, but foo in test_opts. */ -+ } -+ -+ /* If no conflicting test_opt was encountered, return success. */ -+ return 1; -+} -diff --git a/utils/match-options.h b/utils/match-options.h -new file mode 100644 -index 0000000..ea7ae70 ---- /dev/null -+++ b/utils/match-options.h -@@ -0,0 +1,33 @@ -+/* Common functionality for the --test-opts flag of mount and umount. -+ -+ Copyright (C) 2013 Free Software Foundation, Inc. -+ Written by Justus Winter <4winter@informatik.uni-hamburg.de> -+ -+ 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 this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -+ -+#include <mntent.h> -+ -+extern char *test_opts; -+extern size_t test_opts_len; -+ -+/* Check whether the given mount entry matches the given set of -+ options. -+ -+ Returns 0 if foo is in the options vector but nofoo is in test_opts. -+ Returns 0 if foo is in test_opts but foo is not in the options vector. */ -+int -+match_options (struct mntent *mntent); -diff --git a/utils/mount.c b/utils/mount.c -index f8928f1..73a7539 100644 ---- a/utils/mount.c -+++ b/utils/mount.c -@@ -29,6 +29,8 @@ - #include <hurd/fshelp.h> - #include <hurd/paths.h> - -+#include "match-options.h" -+ - #define SEARCH_FMTS _HURD "%sfs\0" _HURD "%s" - #define DEFAULT_FSTYPE "ext2" - -@@ -57,6 +59,8 @@ static const struct argp_option argp_opts[] = - {"remount", 0, 0, OPTION_ALIAS}, - {"verbose", 'v', 0, 0, "Give more detailed information"}, - {"no-mtab", 'n', 0, 0, "Do not update /etc/mtab"}, -+ {"test-opts", 'O', "OPTIONS", 0, -+ "Only mount fstab entries matching the given set of options"}, - {"fake", 'f', 0, 0, "Do not actually mount, just pretend"}, - {0, 0} - }; -@@ -122,6 +126,12 @@ parse_opt (int key, char *arg, struct argp_state *state) - fake = 1; - break; - -+ case 'O': -+ err = argz_create_sep (arg, ',', &test_opts, &test_opts_len); -+ if (err) -+ argp_failure (state, 100, ENOMEM, "%s", arg); -+ break; -+ - case ARGP_KEY_ARG: - if (mountpoint == 0) /* One arg: mountpoint */ - mountpoint = arg; -@@ -615,8 +625,13 @@ main (int argc, char **argv) - case mount: - for (fs = fstab->entries; fs; fs = fs->next) - { -- if (fstab_params.do_all && hasmntopt (&fs->mntent, MNTOPT_NOAUTO)) -- continue; -+ if (fstab_params.do_all) { -+ if (hasmntopt (&fs->mntent, MNTOPT_NOAUTO)) -+ continue; -+ -+ if (! match_options (&fs->mntent)) -+ continue; -+ } - err |= do_mount (fs, remount); - } - break; --- -1.7.10.4 - - diff --git a/debian/patches/procfs-default.patch b/debian/patches/procfs-default.patch deleted file mode 100644 index 023ab9d5..00000000 --- a/debian/patches/procfs-default.patch +++ /dev/null @@ -1,48 +0,0 @@ -Define a macro for the default value of each command line -parameter. This allows one to generate a minimal response to -fsys_get_options requests. - -* procfs/main.c: New macro definitions for default values. ---- - procfs/main.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/procfs/main.c b/procfs/main.c -index ba74e87..3e53307 100644 ---- a/procfs/main.c -+++ b/procfs/main.c -@@ -37,6 +37,13 @@ pid_t opt_fake_self; - #define NOEXEC_KEY -2 /* Likewise. */ - #define NOSUID_KEY -3 /* Likewise. */ - -+/* Default values */ -+#define OPT_CLK_TCK sysconf(_SC_CLK_TCK) -+#define OPT_STAT_MODE 0400 -+#define OPT_FAKE_SELF -1 -+#define OPT_KERNEL_PID 2 -+#define OPT_ANON_OWNER 0 -+ - static error_t - argp_parser (int key, char *arg, struct argp_state *state) - { -@@ -211,11 +218,11 @@ int main (int argc, char **argv) - mach_port_t bootstrap; - error_t err; - -- opt_clk_tck = sysconf(_SC_CLK_TCK); -- opt_stat_mode = 0400; -- opt_fake_self = -1; -- opt_kernel_pid = 2; -- opt_anon_owner = 0; -+ opt_clk_tck = OPT_CLK_TCK; -+ opt_stat_mode = OPT_STAT_MODE; -+ opt_fake_self = OPT_FAKE_SELF; -+ opt_kernel_pid = OPT_KERNEL_PID; -+ opt_anon_owner = OPT_ANON_OWNER; - err = argp_parse (&argp, argc, argv, 0, 0, 0); - if (err) - error (1, err, "Could not parse command line"); --- -1.7.10.4 - - diff --git a/debian/patches/procfs-get-options.patch b/debian/patches/procfs-get-options.patch deleted file mode 100644 index 99104177..00000000 --- a/debian/patches/procfs-get-options.patch +++ /dev/null @@ -1,73 +0,0 @@ -Implement our own netfs_append_args function that provides the -appropriate command line flags if the current values differ from the -default values. - -* procfs/main.c (netfs_append_args): New function. ---- - procfs/main.c | 42 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 42 insertions(+) - -diff --git a/procfs/main.c b/procfs/main.c -index 3e53307..bcf9590 100644 ---- a/procfs/main.c -+++ b/procfs/main.c -@@ -22,6 +22,7 @@ - #include <unistd.h> - #include <error.h> - #include <argp.h> -+#include <argz.h> - #include <hurd/netfs.h> - #include <ps.h> - #include "procfs.h" -@@ -193,6 +194,47 @@ struct argp netfs_runtime_argp_ = { - /* Used by netfs_set_options to handle runtime option parsing. */ - struct argp *netfs_runtime_argp = &netfs_runtime_argp_; - -+/* Return an argz string describing the current options. Fill *ARGZ -+ with a pointer to newly malloced storage holding the list and *LEN -+ to the length of that storage. */ -+error_t -+netfs_append_args (char **argz, size_t *argz_len) -+{ -+ char buf[80]; -+ error_t err = 0; -+ -+#define FOPT(opt, default, fmt, args...) \ -+ do { \ -+ if (! err && opt != default) \ -+ { \ -+ snprintf (buf, sizeof buf, fmt, ## args); \ -+ err = argz_add (argz, argz_len, buf); \ -+ } \ -+ } while (0) -+ -+ FOPT (opt_clk_tck, OPT_CLK_TCK, -+ "--clk-tck=%d", opt_clk_tck); -+ -+ FOPT (opt_stat_mode, OPT_STAT_MODE, -+ "--stat-mode=%o", opt_stat_mode); -+ -+ FOPT (opt_fake_self, OPT_FAKE_SELF, -+ "--fake-self=%d", opt_fake_self); -+ -+ FOPT (opt_anon_owner, OPT_ANON_OWNER, -+ "--anonymous-owner=%d", opt_anon_owner); -+ -+ FOPT (opt_kernel_pid, OPT_KERNEL_PID, -+ "--kernel-process=%d", opt_kernel_pid); -+ -+#undef FOPT -+ -+ if (! err) -+ err = netfs_append_std_options (argz, argz_len); -+ -+ return err; -+} -+ - error_t - root_make_node (struct ps_context *pc, struct node **np) - { --- -1.7.10.4 - - diff --git a/debian/patches/procfs-update.patch b/debian/patches/procfs-update.patch deleted file mode 100644 index 67b415ca..00000000 --- a/debian/patches/procfs-update.patch +++ /dev/null @@ -1,143 +0,0 @@ -Split the argument handling into a common part and one for -fsys_update_options. Handle the --update parameter; for procfs this is -a no-op. - -* procfs/main.c (common_options): New variable. -(runtime_argp_parser): Handle --update. -(startup_argp): New variable. -(netfs_runtime_argp_): New variable. ---- - procfs/main.c | 93 ++++++++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 65 insertions(+), 28 deletions(-) - -diff --git a/procfs/main.c b/procfs/main.c -index 1b19c01..ba74e87 100644 ---- a/procfs/main.c -+++ b/procfs/main.c -@@ -109,51 +109,88 @@ argp_parser (int key, char *arg, struct argp_state *state) - return 0; - } - -+struct argp_option common_options[] = { -+ { "clk-tck", 'h', "HZ", 0, -+ "Unit used for the values expressed in system clock ticks " -+ "(default: sysconf(_SC_CLK_TCK))" }, -+ { "stat-mode", 's', "MODE", 0, -+ "The [pid]/stat file publishes information which on Hurd is only " -+ "available to the process owner. " -+ "You can use this option to override its mode to be more permissive " -+ "for compatibility purposes. " -+ "(default: 0400)" }, -+ { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL, -+ "Provide a fake \"self\" symlink to the given PID, for compatibility " -+ "purposes. If PID is omitted, \"self\" will point to init. " -+ "(default: no self link)" }, -+ { "kernel-process", 'k', "PID", 0, -+ "Process identifier for the kernel, used to retreive its command " -+ "line, as well as the global up and idle times. " -+ "(default: 2)" }, -+ { "compatible", 'c', NULL, 0, -+ "Try to be compatible with the Linux procps utilities. " -+ "Currently equivalent to -h 100 -s 0444 -S 1." }, -+ { "anonymous-owner", 'a', "USER", 0, -+ "Make USER the owner of files related to processes without one. " -+ "Be aware that USER will be granted access to the environment and " -+ "other sensitive information about the processes in question. " -+ "(default: use uid 0)" }, -+ { "nodev", NODEV_KEY, NULL, 0, -+ "Ignored for compatibility with Linux' procfs." }, -+ { "noexec", NOEXEC_KEY, NULL, 0, -+ "Ignored for compatibility with Linux' procfs." }, -+ { "nosuid", NOSUID_KEY, NULL, 0, -+ "Ignored for compatibility with Linux' procfs." }, -+ {} -+}; -+ - struct argp argp = { -- .options = (struct argp_option []) { -- { "clk-tck", 'h', "HZ", 0, -- "Unit used for the values expressed in system clock ticks " -- "(default: sysconf(_SC_CLK_TCK))" }, -- { "stat-mode", 's', "MODE", 0, -- "The [pid]/stat file publishes information which on Hurd is only " -- "available to the process owner. " -- "You can use this option to override its mode to be more permissive " -- "for compatibility purposes. " -- "(default: 0400)" }, -- { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL, -- "Provide a fake \"self\" symlink to the given PID, for compatibility " -- "purposes. If PID is omitted, \"self\" will point to init. " -- "(default: no self link)" }, -- { "kernel-process", 'k', "PID", 0, -- "Process identifier for the kernel, used to retreive its command " -- "line, as well as the global up and idle times. " -- "(default: 2)" }, -- { "compatible", 'c', NULL, 0, -- "Try to be compatible with the Linux procps utilities. " -- "Currently equivalent to -h 100 -s 0444 -S 1." }, -- { "anonymous-owner", 'a', "USER", 0, -- "Make USER the owner of files related to processes without one. " -- "Be aware that USER will be granted access to the environment and " -- "other sensitive information about the processes in question. " -- "(default: use uid 0)" }, -- { "nodev", NODEV_KEY, NULL, 0, -- "Ignored for compatibility with Linux' procfs." }, -- { "noexec", NOEXEC_KEY, NULL, 0, -- "Ignored for compatibility with Linux' procfs." }, -- { "nosuid", NOSUID_KEY, NULL, 0, -- "Ignored for compatibility with Linux' procfs." }, -+ .options = common_options, -+ .parser = argp_parser, -+ .doc = "A virtual filesystem emulating the Linux procfs.", -+ .children = (struct argp_child []) { -+ { &netfs_std_startup_argp, }, - {} - }, -+}; -+ -+static error_t -+runtime_argp_parser (int key, char *arg, struct argp_state *state) -+{ -+ switch (key) -+ { -+ case 'u': -+ /* do nothing */ -+ break; -+ -+ default: -+ return ARGP_ERR_UNKNOWN; -+ } -+ -+ return 0; -+} -+ -+struct argp runtime_argp = { -+ .options = (struct argp_option []) { -+ { "update", 'u', NULL, 0, "remount; for procfs this does nothing" }, -+ {}, -+ }, -+ .parser = runtime_argp_parser, -+}; -+ -+struct argp netfs_runtime_argp_ = { -+ .options = common_options, - .parser = argp_parser, - .doc = "A virtual filesystem emulating the Linux procfs.", - .children = (struct argp_child []) { -- { &netfs_std_startup_argp, }, -+ { &runtime_argp, }, -+ { &netfs_std_runtime_argp, }, - {} - }, - }; - - /* Used by netfs_set_options to handle runtime option parsing. */ --struct argp *netfs_runtime_argp = &argp; -+struct argp *netfs_runtime_argp = &netfs_runtime_argp_; - - error_t - root_make_node (struct ps_context *pc, struct node **np) --- -1.7.10.4 - - diff --git a/debian/patches/proxy-defpager.diff b/debian/patches/proxy-defpager.diff index db9604ad..a83939c6 100644 --- a/debian/patches/proxy-defpager.diff +++ b/debian/patches/proxy-defpager.diff @@ -16,12 +16,12 @@ Index: hurd-debian/trans/Makefile --- hurd-debian.orig/trans/Makefile 2012-11-26 00:23:22.000000000 +0000 +++ hurd-debian/trans/Makefile 2012-11-26 00:25:32.000000000 +0000 @@ -26,7 +26,7 @@ - fakeroot.c proxy-defpager.c remap.c + fakeroot.c proxy-defpager.c remap.c mtab.c OBJS = $(SRCS:.c=.o) fsysServer.o ifsockServer.o passwordServer.o \ crashServer.o crash_replyUser.o msgServer.o \ - default_pagerServer.o default_pagerUser.o \ + ourdefault_pagerServer.o ourdefault_pagerUser.o \ - device_replyServer.o elfcore.o + device_replyServer.o elfcore.o fsysUser.o HURDLIBS = ports netfs trivfs iohelp fshelp pipe ihash shouldbeinlibc LDLIBS += -lpthread @@ -34,6 +34,9 @@ diff --git a/debian/patches/series b/debian/patches/series index 2e80be7b..f86b2a38 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,7 +1,4 @@ diskfs_no_inherit_dir_group.patch -ext2fs_large_stores.patch -ext2fs_large_stores_pthread.patch -hurd_console_startup.patch init_try_runsystem.gnu.patch makedev.diff pfinet_dhcp.patch @@ -41,18 +38,5 @@ libmachdev.patch exec_filename_exec.patch exec_filename_fs.patch exec_filename_use.patch - -# Justus Winter's work, to be pushed -mount-n.patch -mount-f.patch -mount-remount.patch mount-loop.patch -procfs-update.patch -procfs-default.patch -procfs-get-options.patch -sutils-types.patch mount-test-opts.patch -mount-ignore-mounted-all.patch -mount-t-auto.patch -sutils-multiple-none.patch -umount.patch diff --git a/debian/patches/sutils-multiple-none.patch b/debian/patches/sutils-multiple-none.patch deleted file mode 100644 index c787b5a7..00000000 --- a/debian/patches/sutils-multiple-none.patch +++ /dev/null @@ -1,40 +0,0 @@ -Previously it was not possible to add two mount entries with the same -device information to an fstab structure. This is easily fixed by -breaking the assumption, that there is only one possible mount entry -for the "none" device as used by many purely virtual file systems. - -* utils/fstab.c (fstab_find_device): Return NULL if name is "none". ---- - sutils/fstab.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/sutils/fstab.c b/sutils/fstab.c -index e241de6..d3b8b6f 100644 ---- a/sutils/fstab.c -+++ b/sutils/fstab.c -@@ -457,11 +457,19 @@ fs_remount (struct fs *fs) - return err; - } - --/* Returns the FS entry in FSTAB with the device field NAME (there can only -- be one such entry). */ -+/* Returns the FS entry in FSTAB with the device field NAME. -+ -+ In general there can only be one such entry. This holds not true -+ for virtual file systems that use "none" as device name. -+ -+ If name is "none", NULL is returned. This also makes it possible to -+ add more than one entry for the device "none". */ - inline struct fs * - fstab_find_device (const struct fstab *fstab, const char *name) - { -+ if (strcmp (name, "none") == 0) -+ return NULL; -+ - struct fs *fs; - for (fs = fstab->entries; fs; fs = fs->next) - if (strcmp (fs->mntent.mnt_fsname, name) == 0) --- -1.7.10.4 - - diff --git a/debian/patches/sutils-types.patch b/debian/patches/sutils-types.patch deleted file mode 100644 index d2a21e94..00000000 --- a/debian/patches/sutils-types.patch +++ /dev/null @@ -1,150 +0,0 @@ -The mount utility on both Linux and FreeBSD allows one to either -specify a whitelist or a blacklist of filesystem types to consider for ---all. Prefixing the list with "no" indicates that the list is a -blacklist. Furthermore, Linux' mount utility ignores a "no" prefix on -any entry in the given list. - -Previously the Hurd variant first applied whitelist containing all -positive values given and then filtered the resulting list using all -negative values. But this makes little sense because each entry only -has one value for the filesystem type (mnt_type) and all values are -mutually exclusive. - -This patch adjusts the fstab handling code so that our mount utility -behaves like the Linux mount utility. This code is used by both mount -and fsck. The same argumentation applies to fsck as well. - -Like implemented in Linux mount, any "no" prefix is ignored to retain -compatibility with the old behavior. - -* sutils/fstab.c (fstab_argp_create): Fix semantic of --types. ---- - sutils/fstab.c | 103 +++++++++++++++----------------------------------------- - 1 file changed, 27 insertions(+), 76 deletions(-) - -diff --git a/sutils/fstab.c b/sutils/fstab.c -index b66e519..e241de6 100644 ---- a/sutils/fstab.c -+++ b/sutils/fstab.c -@@ -880,90 +880,41 @@ fstab_argp_create (struct fstab_argp_params *params, - check = fstab; - else - { -- struct fs *fs; -- const char *tn; -- unsigned int nonexclude_types; -- - err = fstab_create (types, &check); - if (err) - error (105, err, "fstab_create"); - -- /* For each excluded type (i.e. `-t notype'), clobber the -- fstype entry's program with an empty string to mark it. */ -- nonexclude_types = 0; -- for (tn = params->types; tn; -- tn = argz_next (params->types, params->types_len, tn)) -- { -- if (!strncasecmp (tn, "no", 2)) -- { -- struct fstype *type; -- err = fstypes_get (types, &tn[2], &type); -- if (err) -- error (106, err, "fstypes_get"); -- free (type->program); -- type->program = strdup (""); -- } -- else -- ++nonexclude_types; -- } -- -- if (nonexclude_types != 0) -- { -- const char *tn; -- struct fstypes *wanttypes; -- -- /* We will copy the types we want to include into a fresh -- list in WANTTYPES. Since we specify no search formats, -- `fstypes_get' applied to WANTTYPES can only create -- elements with a null `program' field. */ -- err = fstypes_create (0, 0, &wanttypes); -- if (err) -- error (102, err, "fstypes_create"); -- -- for (tn = params->types; tn; -- tn = argz_next (params->types, params->types_len, tn)) -- if (strncasecmp (tn, "no", 2)) -- { -- struct fstype *type; -- err = fstypes_get (types, tn, &type); -- if (err) -- error (106, err, "fstypes_get"); -- if (type->program == 0) -- error (0, 0, -- "requested filesystem type `%s' unknown", tn); -- else -- { -- struct fstype *newtype = malloc (sizeof *newtype); -- newtype->name = strdup (type->name); -- newtype->program = strdup (type->program); -- newtype->next = wanttypes->entries; -- wanttypes->entries = newtype; -- } -- } -- -- /* fstypes_free (types); */ -- types = wanttypes; -- } -+ int blacklist = strncasecmp (params->types, "no", 2) == 0; -+ if (blacklist) -+ params->types += 2; /* Skip no. */ - -+ struct fs *fs; - for (fs = fstab->entries; fs; fs = fs->next) - { -- const char *ptn; -- struct fstype *type; -- -- err = fs_type (fs, &type); -- if (err || nonexclude_types) -- { -- err = fstypes_get (types, fs->mntent.mnt_type, &type); -- if (err) -- error (106, err, "fstypes_get"); -- if (params->types != 0) -- continue; -- } -- if (nonexclude_types && type->program == 0) -- continue; /* Freshly created, was not in WANTTYPES. */ -- if (type->program != 0 && type->program[0] == '\0') -- continue; /* This type is marked as excluded. */ -+ if (strcmp (fs->mntent.mnt_type, MNTTYPE_SWAP) == 0) -+ continue; /* Ignore swap entries. */ -+ -+ const char *tn; -+ int matched = 0; -+ for (tn = params->types; tn; -+ tn = argz_next (params->types, params->types_len, tn)) -+ { -+ const char *type = fs->mntent.mnt_type; -+ if (strcmp (type, tn) == 0 -+ /* Skip no for compatibility. */ -+ || ((strncasecmp (type, "no", 2) == 0) -+ && strcmp (type, tn) == 0)) -+ { -+ matched = 1; -+ break; -+ } -+ } -+ -+ if (matched == blacklist) -+ continue; /* Either matched and types is a blacklist -+ or not matched and types is a whitelist */ - -+ const char *ptn; - for (ptn = params->exclude; ptn; - ptn = argz_next (params->exclude, params->exclude_len, ptn)) - if (fnmatch (ptn, fs->mntent.mnt_dir, 0) == 0) --- -1.7.10.4 - - diff --git a/debian/patches/umount.patch b/debian/patches/umount.patch deleted file mode 100644 index b2f1cafa..00000000 --- a/debian/patches/umount.patch +++ /dev/null @@ -1,382 +0,0 @@ -This adds a umount utility that implements most of the functions that -the Linux umount utility provides, especially that subset that is used -by the Debian package initscripts. - -* utils/umount.c: New file. ---- - utils/Makefile | 10 +- - utils/umount.c | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 325 insertions(+), 4 deletions(-) - create mode 100644 utils/umount.c - -diff --git a/utils/Makefile b/utils/Makefile -index 207c904..4fe2dc2 100644 ---- a/utils/Makefile -+++ b/utils/Makefile -@@ -21,7 +21,9 @@ makemode := utilities - targets = shd ps settrans showtrans syncfs fsysopts \ - storeinfo login w uptime ids loginpr sush vmstat portinfo \ - devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \ -- storeread msgport rpctrace mount gcore fakeauth fakeroot remap -+ storeread msgport rpctrace mount gcore fakeauth fakeroot remap \ -+ umount -+ - special-targets = loginpr sush uptime fakeroot remap - SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ - fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \ -@@ -29,7 +31,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ - parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ - unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ - rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ -- match-options.c -+ match-options.c umount.c - - OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) - HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc -@@ -58,7 +60,7 @@ ftpcp ftpdir: ../libftpconn/libftpconn.a - settrans: ../libfshelp/libfshelp.a ../libports/libports.a - ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ - devprobe vminfo addauth rmauth setauth unsu ftpcp ftpdir storeread \ -- storecat msgport mount: \ -+ storecat msgport mount umount: \ - ../libshouldbeinlibc/libshouldbeinlibc.a - - $(filter-out $(special-targets), $(targets)): %: %.o -@@ -74,7 +76,7 @@ fakeauth-CPPFLAGS = -I$(srcdir)/../auth - authServer-CPPFLAGS = -I$(srcdir)/../auth - auth_requestUser-CPPFLAGS = -I$(srcdir)/../auth - --mount: ../sutils/fstab.o ../sutils/clookup.o match-options.o \ -+mount umount: ../sutils/fstab.o ../sutils/clookup.o match-options.o \ - $(foreach L,fshelp ports,../lib$L/lib$L.a) - ../sutils/fstab.o ../sutils/clookup.o: FORCE - $(MAKE) -C $(@D) $(@F) -diff --git a/utils/umount.c b/utils/umount.c -new file mode 100644 -index 0000000..64e6ee2 ---- /dev/null -+++ b/utils/umount.c -@@ -0,0 +1,319 @@ -+/* Roughly Unix/Linux-compatible `umount' frontend for Hurd translators. -+ -+ Copyright (C) 2013 Free Software Foundation, Inc. -+ Written by Justus Winter <4winter@informatik.uni-hamburg.de> -+ -+ 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 this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -+ -+#include "../sutils/fstab.h" -+#include <argp.h> -+#include <argz.h> -+#include <blkid/blkid.h> -+#include <error.h> -+#include <fcntl.h> -+#include <hurd/fshelp.h> -+#include <hurd/fsys.h> -+#include <hurd/paths.h> -+#include <hurd/process.h> -+#include <stdlib.h> -+#include <unistd.h> -+ -+#include "match-options.h" -+ -+/* XXX fix libc */ -+#undef _PATH_MOUNTED -+#define _PATH_MOUNTED "/etc/mtab" -+ -+static char *targets; -+static size_t targets_len; -+static int readonly; -+static int verbose; -+static int passive_flags = FS_TRANS_SET; -+static int active_flags = FS_TRANS_SET; -+static int goaway_flags; -+static int fake; -+ -+static struct fstab_argp_params fstab_params; -+ -+#define FAKE_KEY 0x80 /* !isascii (FAKE_KEY), so no short option. */ -+ -+static const struct argp_option argp_opts[] = -+{ -+ {"fake", FAKE_KEY, 0, 0, "Do not actually umount, just pretend"}, -+ {"force", 'f', 0, 0, "Force umount by killing the translator"}, -+ {"no-mtab", 'n', 0, 0, "Do not update /etc/mtab"}, -+ {"read-only", 'r', 0, 0, "If unmounting fails, try to remount read-only"}, -+ {"nosync", 'S', 0, 0, "Don't sync a translator before killing it"}, -+ {"test-opts", 'O', "OPTIONS", 0, -+ "Only mount fstab entries matching the given set of options"}, -+ {"verbose", 'v', 0, 0, "Give more detailed information"}, -+ {}, -+}; -+ -+static error_t -+parse_opt (int key, char *arg, struct argp_state *state) -+{ -+ struct fstab_argp_params *params = state->input; -+ error_t err; -+ switch (key) -+ { -+ case ARGP_KEY_INIT: -+ state->child_inputs[0] = params; /* pass down to fstab_argp parser */ -+ break; -+ -+ case FAKE_KEY: -+ fake = 1; -+ break; -+ -+ case 'f': -+ goaway_flags |= FSYS_GOAWAY_FORCE; -+ break; -+ -+ case 'n': -+ /* do nothing */ -+ break; -+ -+ case 'r': -+ readonly = 1; -+ break; -+ -+ case 'S': -+ goaway_flags |= FSYS_GOAWAY_NOSYNC; -+ break; -+ -+ case 'O': -+ err = argz_create_sep (arg, ',', &test_opts, &test_opts_len); -+ if (err) -+ argp_failure (state, 100, ENOMEM, "%s", arg); -+ break; -+ -+ case 'v': -+ verbose += 1; -+ break; -+ -+ case ARGP_KEY_ARG: -+ err = argz_add (&targets, &targets_len, arg); -+ if (err) -+ argp_failure (state, 100, ENOMEM, "%s", arg); -+ break; -+ -+ case ARGP_KEY_NO_ARGS: -+ if (! params->do_all) -+ { -+ argp_error (state, -+ "filesystem argument required if --all is not given"); -+ return EINVAL; -+ } -+ break; -+ -+ case ARGP_KEY_END: -+ if (params->do_all && targets) -+ { -+ argp_error (state, "filesystem argument not allowed with --all"); -+ return EINVAL; -+ } -+ break; -+ -+ default: -+ return ARGP_ERR_UNKNOWN; -+ } -+ -+ return 0; -+} -+ -+static const char doc[] = "Stop active and remove passive translators"; -+static const char args_doc[] = "DEVICE|DIRECTORY [DEVICE|DIRECTORY ...]"; -+ -+static struct argp fstab_argp_mtab; /* Slightly modified version. */ -+ -+static const struct argp_child argp_kids[] = -+{ -+ {&fstab_argp_mtab, 0, -+ "Filesystem selection (if no explicit filesystem arguments given):", 2}, -+ {}, -+}; -+static struct argp argp = -+{ -+ options: argp_opts, -+ parser: parse_opt, -+ args_doc: args_doc, -+ doc: doc, -+ children: argp_kids, -+}; -+ -+/* This is a trimmed and slightly modified version of -+ fstab_argp.options which uses _PATH_MOUNTED instead of _PATH_MNTTAB -+ in the doc strings. */ -+static const struct argp_option fstab_argp_mtab_opts[] = -+{ -+ {"all", 'a', 0, 0, "Do all filesystems in " _PATH_MOUNTED}, -+ {0, 'A', 0, OPTION_ALIAS }, -+ {"fstab", 'F', "FILE", 0, "File to use instead of " _PATH_MOUNTED}, -+ {"fstype", 't', "TYPE", 0, "Do only filesystems of given type(s)"}, -+ {"exclude-root",'R',0, 0, -+ "Exclude root (/) filesystem from " _PATH_MOUNTED " list"}, -+ {"exclude", 'X', "PATTERN", 0, "Exclude directories matching PATTERN"}, -+ {} -+}; -+ -+static error_t -+fstab_argp_mtab_parse_opt (int key, char *arg, struct argp_state *state) -+{ -+ return fstab_argp.parser (key, arg, state); -+} -+ -+static struct argp fstab_argp_mtab = -+{ -+ options: fstab_argp_mtab_opts, -+ parser: fstab_argp_mtab_parse_opt, -+}; -+ -+/* Unmount one filesystem. */ -+static error_t -+do_umount (struct fs *fs) -+{ -+ error_t err = 0; -+ -+ file_t node = file_name_lookup(fs->mntent.mnt_dir, O_NOTRANS, 0666); -+ if (node == MACH_PORT_NULL) -+ { -+ error(0, errno, "%s", fs->mntent.mnt_dir); -+ return errno; -+ } -+ -+ if (verbose) -+ printf ("settrans -pg%s%s %s\n", -+ goaway_flags & FSYS_GOAWAY_NOSYNC? "S": "", -+ goaway_flags & FSYS_GOAWAY_FORCE? "f": "", -+ fs->mntent.mnt_dir); -+ -+ if (! fake) -+ { -+ err = file_set_translator (node, -+ passive_flags, active_flags, goaway_flags, -+ NULL, 0, -+ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); -+ if (err) -+ { -+ error (0, err, "%s", fs->mntent.mnt_dir); -+ -+ /* Try remounting readonly instead if requested. */ -+ if (readonly) -+ { -+ if (verbose) -+ printf ("fsysopts %s --readonly\n", fs->mntent.mnt_dir); -+ -+ error_t e = fs_set_readonly (fs, TRUE); -+ if (e) -+ error (0, e, "%s", fs->mntent.mnt_dir); -+ } -+ } -+ } -+ -+ /* Deallocate the reference so that unmounting nested translators -+ works properly. */ -+ mach_port_deallocate (mach_task_self (), node); -+ return err; -+} -+ -+int -+main (int argc, char **argv) -+{ -+ error_t err; -+ -+ err = argp_parse (&argp, argc, argv, 0, 0, &fstab_params); -+ if (err) -+ error (3, err, "parsing arguments"); -+ -+ /* Read the mtab file by default. */ -+ if (! fstab_params.fstab_path) -+ fstab_params.fstab_path = _PATH_MOUNTED; -+ -+ struct fstab *fstab = fstab_argp_create (&fstab_params, NULL, 0); -+ if (! fstab) -+ error (3, ENOMEM, "fstab creation"); -+ -+ if (targets) -+ for (char *t = targets; t; t = argz_next (targets, targets_len, t)) -+ { -+ /* Figure out if t is the device or the mountpoint. */ -+ struct fs *fs = fstab_find_mount (fstab, t); -+ if (! fs) -+ { -+ fs = fstab_find_device (fstab, t); -+ if (! fs) -+ { -+ error (0, 0, "could not find entry for: %s", t); -+ -+ /* As last resort, just assume it is the mountpoint. */ -+ struct mntent m = -+ { -+ mnt_fsname: "", -+ mnt_dir: t, -+ mnt_type: "", -+ mnt_opts: 0, -+ mnt_freq: 0, -+ mnt_passno: 0, -+ }; -+ -+ err = fstab_add_mntent (fstab, &m, &fs); -+ if (err) -+ error (2, err, "%s", t); -+ } -+ } -+ -+ if (fs) -+ err |= do_umount (fs); -+ } -+ else -+ { -+ /* Sort entries. */ -+ size_t count = 0; -+ for (struct fs *fs = fstab->entries; fs; fs = fs->next) -+ count += 1; -+ -+ char **entries = malloc (count * sizeof (char *)); -+ if (! entries) -+ error (3, ENOMEM, "allocating entries array"); -+ -+ char **p = entries; -+ for (struct fs *fs = fstab->entries; fs; fs = fs->next) -+ *p++ = fs->mntent.mnt_dir; -+ -+ /* Reverse lexicographical order. */ -+ int compare_entries (const void *a, const void *b) -+ { -+ return -strcmp ((char *) a, (char *) b); -+ } -+ -+ qsort (entries, count, sizeof (char *), compare_entries); -+ -+ for (int i = 0; i < count; i++) -+ { -+ struct fs *fs = fstab_find_mount (fstab, entries[i]); -+ if (! fs) -+ error (4, 0, "could not find entry for: %s", entries[i]); -+ -+ if (! match_options (&fs->mntent)) -+ continue; -+ -+ err |= do_umount (fs); -+ } -+ } -+ -+ return err? EXIT_FAILURE: EXIT_SUCCESS; -+} --- -1.7.10.4 - - |