diff options
Diffstat (limited to 'debian/patches/0010-libdiskfs-implement-a-node-cache.patch')
-rw-r--r-- | debian/patches/0010-libdiskfs-implement-a-node-cache.patch | 687 |
1 files changed, 0 insertions, 687 deletions
diff --git a/debian/patches/0010-libdiskfs-implement-a-node-cache.patch b/debian/patches/0010-libdiskfs-implement-a-node-cache.patch deleted file mode 100644 index c0c42926..00000000 --- a/debian/patches/0010-libdiskfs-implement-a-node-cache.patch +++ /dev/null @@ -1,687 +0,0 @@ -From 2bb8bfa49d35ab2f7b33587e59c4a9c635642ea0 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Wed, 15 Apr 2015 13:17:06 +0200 -Subject: [PATCH hurd 10/16] libdiskfs: implement a node cache - -xxx - -Move the node cache from ext2fs into libdiskfs. - -* ext2fs/dir.c -* ext2fs/ext2fs.c -* ext2fs/ext2fs.h -* ext2fs/inode.c -* libdiskfs/Makefile -* libdiskfs/diskfs.h -* libdiskfs/node-cache.c ---- - ext2fs/dir.c | 4 +- - ext2fs/ext2fs.c | 2 - - ext2fs/ext2fs.h | 9 -- - ext2fs/inode.c | 228 ++++---------------------------------------- - libdiskfs/Makefile | 2 +- - libdiskfs/diskfs.h | 17 ++++ - libdiskfs/node-cache.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++ - 7 files changed, 289 insertions(+), 222 deletions(-) - create mode 100644 libdiskfs/node-cache.c - -diff --git a/ext2fs/dir.c b/ext2fs/dir.c -index 2dfe1d7..6cdfba2 100644 ---- a/ext2fs/dir.c -+++ b/ext2fs/dir.c -@@ -306,7 +306,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type, - - /* Here below are the spec dotdot cases. */ - else if (type == RENAME || type == REMOVE) -- np = ifind (inum); -+ np = diskfs_cached_ifind (inum); - - else if (type == LOOKUP) - { -@@ -359,7 +359,7 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type, - diskfs_nput (np); - } - else if (type == RENAME || type == REMOVE) -- /* We just did ifind to get np; that allocates -+ /* We just did diskfs_cached_ifind to get np; that allocates - no new references, so we don't have anything to do */ - ; - else if (type == LOOKUP) -diff --git a/ext2fs/ext2fs.c b/ext2fs/ext2fs.c -index beb7cad..d0fdfe7 100644 ---- a/ext2fs/ext2fs.c -+++ b/ext2fs/ext2fs.c -@@ -185,8 +185,6 @@ main (int argc, char **argv) - - map_hypermetadata (); - -- inode_init (); -- - /* Set diskfs_root_node to the root inode. */ - err = diskfs_cached_lookup (EXT2_ROOT_INO, &diskfs_root_node); - if (err) -diff --git a/ext2fs/ext2fs.h b/ext2fs/ext2fs.h -index 9667b6f..96d8e9d 100644 ---- a/ext2fs/ext2fs.h -+++ b/ext2fs/ext2fs.h -@@ -159,9 +159,6 @@ struct disknode - each DIRBLKSIZE piece of the directory. */ - int *dirents; - -- /* Links on hash list. */ -- struct node *hnext, **hprevp; -- - /* Lock to lock while fiddling with this inode's block allocation info. */ - pthread_rwlock_t alloc_lock; - -@@ -419,12 +416,6 @@ dino_deref (struct ext2_inode *inode) - - /* Write all active disknodes into the inode pager. */ - void write_all_disknodes (); -- --/* Lookup node INUM (which must have a reference already) and return it -- without allocating any new references. */ --struct node *ifind (ino_t inum); -- --void inode_init (void); - - /* ---------------------------------------------------------------- */ - -diff --git a/ext2fs/inode.c b/ext2fs/inode.c -index 7af617c..22a0c8e 100644 ---- a/ext2fs/inode.c -+++ b/ext2fs/inode.c -@@ -39,144 +39,34 @@ - #define UF_IMMUTABLE 0 - #endif - --#define INOHSZ 8192 --#if ((INOHSZ&(INOHSZ-1)) == 0) --#define INOHASH(ino) ((ino)&(INOHSZ-1)) --#else --#define INOHASH(ino) (((unsigned)(ino))%INOHSZ) --#endif -- --/* The nodehash is a cache of nodes. -- -- Access to nodehash and nodehash_nr_items is protected by -- nodecache_lock. -- -- Every node in the nodehash carries a light reference. When we are -- asked to give up that light reference, we reacquire our lock -- momentarily to check whether someone else reacquired a reference -- through the nodehash. */ --static struct node *nodehash[INOHSZ]; --static size_t nodehash_nr_items; --static pthread_rwlock_t nodecache_lock = PTHREAD_RWLOCK_INITIALIZER; -- - static error_t read_node (struct node *np); - - pthread_spinlock_t generation_lock = PTHREAD_SPINLOCK_INITIALIZER; - --/* Initialize the inode hash table. */ --void --inode_init () --{ -- int n; -- for (n = 0; n < INOHSZ; n++) -- nodehash[n] = 0; --} -- --/* Lookup node with inode number INUM. Returns NULL if the node is -- not found in the node cache. */ --static struct node * --lookup (ino_t inum) --{ -- struct node *np; -- for (np = nodehash[INOHASH(inum)]; np; np = diskfs_node_disknode (np)->hnext) -- if (np->cache_id == inum) -- return np; -- return NULL; --} -- --/* Fetch inode INUM, set *NPP to the node structure; -- gain one user reference and lock the node. */ -+/* XXX */ - error_t --diskfs_cached_lookup (ino_t inum, struct node **npp) -+diskfs_user_make_node (struct node **npp) - { -- error_t err; -- struct node *np, *tmp; -+ struct node *np; - struct disknode *dn; - -- pthread_rwlock_rdlock (&nodecache_lock); -- np = lookup (inum); -- if (np) -- goto gotit; -- pthread_rwlock_unlock (&nodecache_lock); -- - /* Create the new node. */ - np = diskfs_make_node_alloc (sizeof *dn); -- dn = diskfs_node_disknode (np); -- np->cache_id = inum; -+ if (np == NULL) -+ return ENOMEM; - - /* Format specific data for the new node. */ -+ dn = diskfs_node_disknode (np); - dn->dirents = 0; - dn->dir_idx = 0; - dn->pager = 0; - pthread_rwlock_init (&dn->alloc_lock, NULL); - pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_cache); - -- pthread_mutex_lock (&np->lock); -- -- /* Put NP in NODEHASH. */ -- pthread_rwlock_wrlock (&nodecache_lock); -- tmp = lookup (inum); -- if (tmp) -- { -- /* We lost a race. */ -- diskfs_nput (np); -- np = tmp; -- goto gotit; -- } -- -- dn->hnext = nodehash[INOHASH(inum)]; -- if (dn->hnext) -- diskfs_node_disknode (dn->hnext)->hprevp = &dn->hnext; -- dn->hprevp = &nodehash[INOHASH(inum)]; -- nodehash[INOHASH(inum)] = np; -- diskfs_nref_light (np); -- nodehash_nr_items += 1; -- pthread_rwlock_unlock (&nodecache_lock); -- -- /* Get the contents of NP off disk. */ -- err = read_node (np); -- -- if (!diskfs_check_readonly () && !np->dn_stat.st_gen) -- { -- pthread_spin_lock (&generation_lock); -- if (++next_generation < diskfs_mtime->seconds) -- next_generation = diskfs_mtime->seconds; -- np->dn_stat.st_gen = next_generation; -- pthread_spin_unlock (&generation_lock); -- np->dn_set_ctime = 1; -- } -- -- if (err) -- return err; -- else -- { -- *npp = np; -- return 0; -- } -- -- gotit: -- diskfs_nref (np); -- pthread_rwlock_unlock (&nodecache_lock); -- pthread_mutex_lock (&np->lock); - *npp = np; - return 0; - } - --/* Lookup node INUM (which must have a reference already) and return it -- without allocating any new references. */ --struct node * --ifind (ino_t inum) --{ -- struct node *np; -- -- pthread_rwlock_rdlock (&nodecache_lock); -- np = lookup (inum); -- pthread_rwlock_unlock (&nodecache_lock); -- -- assert (np); -- return np; --} -- - /* The last reference to a node has gone away; drop - it from the hash table and clean all state in the dn structure. */ - void -@@ -196,35 +86,8 @@ diskfs_node_norefs (struct node *np) - /* The last hard reference to a node has gone away; arrange to have - all the weak references dropped that can be. */ - void --diskfs_try_dropping_softrefs (struct node *np) -+diskfs_user_try_dropping_softrefs (struct node *np) - { -- pthread_rwlock_wrlock (&nodecache_lock); -- if (diskfs_node_disknode (np)->hprevp != NULL) -- { -- /* Check if someone reacquired a reference through the -- nodehash. */ -- struct references result; -- refcounts_references (&np->refcounts, &result); -- -- if (result.hard > 0) -- { -- /* A reference was reacquired through a hash table lookup. -- It's fine, we didn't touch anything yet. */ -- pthread_rwlock_unlock (&nodecache_lock); -- return; -- } -- -- *diskfs_node_disknode (np)->hprevp = diskfs_node_disknode (np)->hnext; -- if (diskfs_node_disknode (np)->hnext) -- diskfs_node_disknode (diskfs_node_disknode (np)->hnext)->hprevp = -- diskfs_node_disknode (np)->hprevp; -- diskfs_node_disknode (np)->hnext = NULL; -- diskfs_node_disknode (np)->hprevp = NULL; -- nodehash_nr_items -= 1; -- diskfs_nrele_light (np); -- } -- pthread_rwlock_unlock (&nodecache_lock); -- - drop_pager_softrefs (np); - } - -@@ -243,8 +106,8 @@ diskfs_new_hardrefs (struct node *np) - } - - /* Read stat information out of the ext2_inode. */ --static error_t --read_node (struct node *np) -+error_t -+diskfs_user_read_node (struct node *np) - { - error_t err; - struct stat *st = &np->dn_stat; -@@ -384,6 +247,16 @@ read_node (struct node *np) - linux, some devices). */ - np->allocsize = 0; - -+ if (!diskfs_check_readonly () && !np->dn_stat.st_gen) -+ { -+ pthread_spin_lock (&generation_lock); -+ if (++next_generation < diskfs_mtime->seconds) -+ next_generation = diskfs_mtime->seconds; -+ np->dn_stat.st_gen = next_generation; -+ pthread_spin_unlock (&generation_lock); -+ np->dn_set_ctime = 1; -+ } -+ - return 0; - } - -@@ -585,72 +458,11 @@ diskfs_node_reload (struct node *node) - } - pokel_flush (&dn->indir_pokel); - flush_node_pager (node); -- read_node (node); -+ diskfs_user_read_node (node); - - return 0; - } - --/* For each active node, call FUN. The node is to be locked around the call -- to FUN. If FUN returns non-zero for any node, then immediately stop, and -- return that value. */ --error_t --diskfs_node_iterate (error_t (*fun)(struct node *)) --{ -- error_t err = 0; -- int n; -- size_t num_nodes; -- struct node *node, **node_list, **p; -- -- pthread_rwlock_rdlock (&nodecache_lock); -- -- /* We must copy everything from the hash table into another data structure -- to avoid running into any problems with the hash-table being modified -- during processing (normally we delegate access to hash-table with -- nodecache_lock, but we can't hold this while locking the -- individual node locks). */ -- num_nodes = nodehash_nr_items; -- -- /* TODO This method doesn't scale beyond a few dozen nodes and should be -- replaced. */ -- node_list = malloc (num_nodes * sizeof (struct node *)); -- if (node_list == NULL) -- { -- pthread_rwlock_unlock (&nodecache_lock); -- ext2_debug ("unable to allocate temporary node table"); -- return ENOMEM; -- } -- -- p = node_list; -- for (n = 0; n < INOHSZ; n++) -- for (node = nodehash[n]; node; node = diskfs_node_disknode (node)->hnext) -- { -- *p++ = node; -- -- /* We acquire a hard reference for node, but without using -- diskfs_nref. We do this so that diskfs_new_hardrefs will not -- get called. */ -- refcounts_ref (&node->refcounts, NULL); -- } -- -- pthread_rwlock_unlock (&nodecache_lock); -- -- p = node_list; -- while (num_nodes-- > 0) -- { -- node = *p++; -- if (!err) -- { -- pthread_mutex_lock (&node->lock); -- err = (*fun)(node); -- pthread_mutex_unlock (&node->lock); -- } -- diskfs_nrele (node); -- } -- -- free (node_list); -- return err; --} -- - /* Write all active disknodes into the ext2_inode pager. */ - void - write_all_disknodes () -diff --git a/libdiskfs/Makefile b/libdiskfs/Makefile -index 996e86a..47b9339 100644 ---- a/libdiskfs/Makefile -+++ b/libdiskfs/Makefile -@@ -41,7 +41,7 @@ OTHERSRCS = conch-fetch.c conch-set.c dir-clear.c dir-init.c dir-renamed.c \ - extern-inline.c \ - node-create.c node-drop.c node-make.c node-rdwr.c node-update.c \ - node-nref.c node-nput.c node-nrele.c node-nrefl.c node-nputl.c \ -- node-nrelel.c \ -+ node-nrelel.c node-cache.c \ - peropen-make.c peropen-rele.c protid-make.c protid-rele.c \ - init-init.c init-startup.c init-first.c init-main.c \ - rdwr-internal.c boot-start.c demuxer.c node-times.c shutdown.c \ -diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h -index 7a21dff..22c4aa6 100644 ---- a/libdiskfs/diskfs.h -+++ b/libdiskfs/diskfs.h -@@ -80,6 +80,9 @@ struct peropen - filesystem. */ - struct node - { -+ /* Links on hash list. */ -+ struct node *hnext, **hprevp; -+ - struct disknode *dn; - - io_statbuf_t dn_stat; -@@ -1102,4 +1105,18 @@ struct store *diskfs_init_main (struct argp *startup_argp, - /* Make errors go somewhere reasonable. */ - void diskfs_console_stdio (); - -+//XXX -+/* XXX */ -+error_t diskfs_user_make_node (struct node **npp); -+/* Read stat information out of the ext2_inode. */ -+error_t diskfs_user_read_node (struct node *np); -+/* The last hard reference to a node has gone away; arrange to have -+ all the weak references dropped that can be. */ -+void diskfs_user_try_dropping_softrefs (struct node *np); -+ -+/* Lookup node INUM (which must have a reference already) and return it -+ without allocating any new references. */ -+struct node *diskfs_cached_ifind (ino_t inum); -+ -+ - #endif /* hurd/diskfs.h */ -diff --git a/libdiskfs/node-cache.c b/libdiskfs/node-cache.c -new file mode 100644 -index 0000000..58249bf ---- /dev/null -+++ b/libdiskfs/node-cache.c -@@ -0,0 +1,249 @@ -+/* Inode cache. -+ -+ Copyright (C) 1994-2015 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 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ -+ -+#include "priv.h" -+ -+#define INOHSZ 8192 -+#if ((INOHSZ&(INOHSZ-1)) == 0) -+#define INOHASH(ino) ((ino)&(INOHSZ-1)) -+#else -+#define INOHASH(ino) (((unsigned)(ino))%INOHSZ) -+#endif -+ -+/* The nodehash is a cache of nodes. -+ -+ Access to nodehash and nodehash_nr_items is protected by -+ nodecache_lock. -+ -+ Every node in the nodehash carries a light reference. When we are -+ asked to give up that light reference, we reacquire our lock -+ momentarily to check whether someone else reacquired a reference -+ through the nodehash. */ -+static struct node *nodehash[INOHSZ]; -+static size_t nodehash_nr_items; -+static pthread_rwlock_t nodecache_lock = PTHREAD_RWLOCK_INITIALIZER; -+ -+/* Initialize the inode hash table. */ -+static void __attribute__ ((constructor)) -+nodecache_init () -+{ -+} -+ -+/* Lookup node with inode number INUM. Returns NULL if the node is -+ not found in the node cache. */ -+static struct node * -+lookup (ino_t inum) -+{ -+ struct node *np; -+ for (np = nodehash[INOHASH(inum)]; np; np = np->hnext) -+ if (np->cache_id == inum) -+ return np; -+ return NULL; -+} -+ -+/* Fetch inode INUM, set *NPP to the node structure; -+ gain one user reference and lock the node. */ -+error_t __attribute__ ((weak)) -+diskfs_cached_lookup (ino_t inum, struct node **npp) -+{ -+ error_t err; -+ struct node *np, *tmp; -+ -+ pthread_rwlock_rdlock (&nodecache_lock); -+ np = lookup (inum); -+ if (np) -+ goto gotit; -+ pthread_rwlock_unlock (&nodecache_lock); -+ -+ err = diskfs_user_make_node (&np); -+ if (err) -+ return err; -+ -+ np->cache_id = inum; -+ pthread_mutex_lock (&np->lock); -+ -+ /* Put NP in NODEHASH. */ -+ pthread_rwlock_wrlock (&nodecache_lock); -+ tmp = lookup (inum); -+ if (tmp) -+ { -+ /* We lost a race. */ -+ diskfs_nput (np); -+ np = tmp; -+ goto gotit; -+ } -+ -+ np->hnext = nodehash[INOHASH(inum)]; -+ if (np->hnext) -+ np->hnext->hprevp = &np->hnext; -+ np->hprevp = &nodehash[INOHASH(inum)]; -+ nodehash[INOHASH(inum)] = np; -+ diskfs_nref_light (np); -+ nodehash_nr_items += 1; -+ pthread_rwlock_unlock (&nodecache_lock); -+ -+ /* Get the contents of NP off disk. */ -+ err = diskfs_user_read_node (np); -+ if (err) -+ return err; -+ else -+ { -+ *npp = np; -+ return 0; -+ } -+ -+ gotit: -+ diskfs_nref (np); -+ pthread_rwlock_unlock (&nodecache_lock); -+ pthread_mutex_lock (&np->lock); -+ *npp = np; -+ return 0; -+} -+ -+/* Lookup node INUM (which must have a reference already) and return it -+ without allocating any new references. */ -+struct node * -+diskfs_cached_ifind (ino_t inum) -+{ -+ struct node *np; -+ -+ pthread_rwlock_rdlock (&nodecache_lock); -+ np = lookup (inum); -+ pthread_rwlock_unlock (&nodecache_lock); -+ -+ assert (np); -+ return np; -+} -+ -+void __attribute__ ((weak)) -+diskfs_try_dropping_softrefs (struct node *np) -+{ -+ pthread_rwlock_wrlock (&nodecache_lock); -+ if (np->hprevp != NULL) -+ { -+ /* Check if someone reacquired a reference through the -+ nodehash. */ -+ struct references result; -+ refcounts_references (&np->refcounts, &result); -+ -+ if (result.hard > 0) -+ { -+ /* A reference was reacquired through a hash table lookup. -+ It's fine, we didn't touch anything yet. */ -+ pthread_rwlock_unlock (&nodecache_lock); -+ return; -+ } -+ -+ *np->hprevp = np->hnext; -+ if (np->hnext) -+ np->hnext->hprevp = np->hprevp; -+ np->hnext = NULL; -+ np->hprevp = NULL; -+ nodehash_nr_items -= 1; -+ diskfs_nrele_light (np); -+ } -+ pthread_rwlock_unlock (&nodecache_lock); -+ -+ diskfs_user_try_dropping_softrefs (np); -+} -+ -+/* For each active node, call FUN. The node is to be locked around the call -+ to FUN. If FUN returns non-zero for any node, then immediately stop, and -+ return that value. */ -+error_t __attribute__ ((weak)) -+diskfs_node_iterate (error_t (*fun)(struct node *)) -+{ -+ error_t err = 0; -+ int n; -+ size_t num_nodes; -+ struct node *node, **node_list, **p; -+ -+ pthread_rwlock_rdlock (&nodecache_lock); -+ -+ /* We must copy everything from the hash table into another data structure -+ to avoid running into any problems with the hash-table being modified -+ during processing (normally we delegate access to hash-table with -+ nodecache_lock, but we can't hold this while locking the -+ individual node locks). */ -+ /* XXX: Can we? */ -+ num_nodes = nodehash_nr_items; -+ -+ /* TODO This method doesn't scale beyond a few dozen nodes and should be -+ replaced. */ -+ node_list = malloc (num_nodes * sizeof (struct node *)); -+ if (node_list == NULL) -+ { -+ pthread_rwlock_unlock (&nodecache_lock); -+ error (0, 0, "unable to allocate temporary node table"); -+ return ENOMEM; -+ } -+ -+ p = node_list; -+ for (n = 0; n < INOHSZ; n++) -+ for (node = nodehash[n]; node; node = node->hnext) -+ { -+ *p++ = node; -+ -+ /* We acquire a hard reference for node, but without using -+ diskfs_nref. We do this so that diskfs_new_hardrefs will not -+ get called. */ -+ refcounts_ref (&node->refcounts, NULL); -+ } -+ -+ pthread_rwlock_unlock (&nodecache_lock); -+ -+ p = node_list; -+ while (num_nodes-- > 0) -+ { -+ node = *p++; -+ if (!err) -+ { -+ pthread_mutex_lock (&node->lock); -+ err = (*fun)(node); -+ pthread_mutex_unlock (&node->lock); -+ } -+ diskfs_nrele (node); -+ } -+ -+ free (node_list); -+ return err; -+} -+ -+/* XXX */ -+error_t __attribute__ ((weak)) -+diskfs_user_make_node (struct node **npp) -+{ -+ assert (! "diskfs_user_make_node not implemented"); -+} -+ -+/* Read stat information out of the ext2_inode. */ -+error_t __attribute__ ((weak)) -+diskfs_user_read_node (struct node *np) -+{ -+ assert (! "diskfs_user_read_node not implemented"); -+} -+ -+/* The last hard reference to a node has gone away; arrange to have -+ all the weak references dropped that can be. */ -+void __attribute__ ((weak)) -+diskfs_user_try_dropping_softrefs (struct node *np) -+{ -+ assert (! "diskfs_user_try_dropping_softrefs not implemented"); -+} -+ --- -2.1.4 - |