diff options
| author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-18 14:20:17 +0200 |
|---|---|---|
| committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-18 14:20:17 +0200 |
| commit | f902a475b6252a91c77e7f77b6e1eccc2ee781ec (patch) | |
| tree | 43a3c131a66a150bbbf9dee954d18537abcef54c /debian/patches/0016-ext2fs-use-librbtree-for-the-nodehash.patch | |
| parent | 84e6742d184b1ac41df1b00ac666e63a41632a98 (diff) | |
add patch series
Diffstat (limited to 'debian/patches/0016-ext2fs-use-librbtree-for-the-nodehash.patch')
| -rw-r--r-- | debian/patches/0016-ext2fs-use-librbtree-for-the-nodehash.patch | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/debian/patches/0016-ext2fs-use-librbtree-for-the-nodehash.patch b/debian/patches/0016-ext2fs-use-librbtree-for-the-nodehash.patch new file mode 100644 index 00000000..fee4854f --- /dev/null +++ b/debian/patches/0016-ext2fs-use-librbtree-for-the-nodehash.patch @@ -0,0 +1,314 @@ +From 54e3e8084aad34ddcd74aea215d83eb3f641d248 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Wed, 14 May 2014 15:30:19 +0200 +Subject: [PATCH 16/16] ext2fs: use librbtree for the nodehash + +Previously, a lookup of a node through nodehash took O(N / INOHSZ). +With INOHSZ being a constant (512) this is linear in N. Use a +red-black tree instead, which guarantees a lookup performance in +O(log N) time. + +* ext2fs/inode.c (INOHSZ, INOHASH): Remove. +(nodehash): Use a red-black tree. +(node_cmp_lookup, node_cmp_insert, node_get_np): New functions. +(inode_init): Remove. +(diskfs_cached_lookup): Adjust accordingly. +(ifind, diskfs_try_dropping_softrefs, diskfs_node_iterate): Likewise. +* ext2fs/ext2fs.h (struct disknode): Remove list pointers, add +red-black tree node. Because we store disknode objects in the tree, +we also need a pointer to the node object, and the cache_id for +efficient operations on the rb tree. +* ext2fs/ext2fs.c (main): Drop inode_init. +--- + ext2fs/Makefile | 2 +- + ext2fs/ext2fs.c | 2 - + ext2fs/ext2fs.h | 7 ++-- + ext2fs/inode.c | 124 +++++++++++++++++++++++++++++--------------------------- + 4 files changed, 70 insertions(+), 65 deletions(-) + +diff --git a/ext2fs/Makefile b/ext2fs/Makefile +index 8d2e68c..b075dc0 100644 +--- a/ext2fs/Makefile ++++ b/ext2fs/Makefile +@@ -23,7 +23,7 @@ target = ext2fs + SRCS = balloc.c dir.c ext2fs.c getblk.c hyper.c ialloc.c \ + inode.c pager.c pokel.c truncate.c storeinfo.c msg.c xinl.c + OBJS = $(SRCS:.c=.o) +-HURDLIBS = diskfs pager iohelp fshelp store ports ihash shouldbeinlibc ++HURDLIBS = diskfs pager iohelp fshelp store ports ihash rbtree shouldbeinlibc + OTHERLIBS = -lpthread $(and $(HAVE_LIBBZ2),-lbz2) $(and $(HAVE_LIBZ),-lz) + + include ../Makeconf +diff --git a/ext2fs/ext2fs.c b/ext2fs/ext2fs.c +index 128b6ed..0409dfb 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 3422af2..3505bb7 100644 +--- a/ext2fs/ext2fs.h ++++ b/ext2fs/ext2fs.h +@@ -26,6 +26,7 @@ + #include <hurd/store.h> + #include <hurd/diskfs.h> + #include <hurd/ihash.h> ++#include <hurd/rbtree.h> + #include <assert.h> + #include <pthread.h> + #include <sys/mman.h> +@@ -155,13 +156,13 @@ clear_bit (unsigned num, char *bitmap) + /* ext2fs specific per-file data. */ + struct disknode + { ++ /* Red-black-tree node for the node cache. */ ++ struct rbtree_node tree_node; ++ + /* For a directory, this array holds the number of directory entries in + 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; + +diff --git a/ext2fs/inode.c b/ext2fs/inode.c +index 7ec343f..0142bf6 100644 +--- a/ext2fs/inode.c ++++ b/ext2fs/inode.c +@@ -20,6 +20,7 @@ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + #include "ext2fs.h" ++#include <stddef.h> + #include <string.h> + #include <unistd.h> + #include <stdio.h> +@@ -39,13 +40,6 @@ + #define UF_IMMUTABLE 0 + #endif + +-#define INOHSZ 512 +-#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 +@@ -55,23 +49,45 @@ + 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 struct rbtree nodehash = RBTREE_INITIALIZER; + static size_t nodehash_nr_items; + static pthread_mutex_t nodehash_lock = PTHREAD_MUTEX_INITIALIZER; + +-static error_t read_node (struct node *np); ++static inline struct node * ++node_get_np (const struct rbtree_node *node) ++{ ++ struct disknode *dn; + +-pthread_spinlock_t generation_lock = PTHREAD_SPINLOCK_INITIALIZER; ++ dn = rbtree_entry (node, struct disknode, tree_node); + +-/* Initialize the inode hash table. */ +-void +-inode_init () ++ return diskfs_disknode_node (dn); ++} ++ ++static inline int ++node_cmp_lookup (const ino_t inum, ++ const struct rbtree_node *node) + { +- int n; +- for (n = 0; n < INOHSZ; n++) +- nodehash[n] = 0; ++ struct node *np = node_get_np (node); ++ ++ if (inum == np->cache_id) ++ return 0; ++ else if (inum < np->cache_id) ++ return -1; ++ else ++ return 1; + } + ++static inline int ++node_cmp_insert (const struct rbtree_node *a, ++ const struct rbtree_node *b) ++{ ++ return node_cmp_lookup (node_get_np (a)->cache_id, b); ++} ++ ++static error_t read_node (struct node *np); ++ ++pthread_spinlock_t generation_lock = PTHREAD_SPINLOCK_INITIALIZER; ++ + /* Fetch inode INUM, set *NPP to the node structure; + gain one user reference and lock the node. */ + error_t +@@ -79,47 +95,42 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) + { + error_t err; + struct node *np; ++ struct rbtree_node *node; ++ unsigned long slot; + struct disknode *dn; + + pthread_mutex_lock (&nodehash_lock); +- for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) +- if (np->cache_id == inum) +- { +- diskfs_nref (np); +- pthread_mutex_unlock (&nodehash_lock); +- pthread_mutex_lock (&np->lock); +- *npp = np; +- return 0; +- } +- +- /* Format specific data for the new node. */ +- dn = malloc (sizeof (struct disknode)); +- if (! dn) ++ node = rbtree_lookup_slot (&nodehash, inum, node_cmp_lookup, slot); ++ if (node != NULL) ++ { ++ np = node_get_np (node); ++ diskfs_nref (np); ++ pthread_mutex_unlock (&nodehash_lock); ++ pthread_mutex_lock (&np->lock); ++ *npp = np; ++ return 0; ++ } ++ ++ /* Create the new node. */ ++ np = diskfs_make_node_alloc (sizeof *dn); ++ if (np == NULL) + { + pthread_mutex_unlock (&nodehash_lock); + return ENOMEM; + } ++ np->cache_id = inum; ++ 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); +- +- /* Create the new node. */ +- np = diskfs_make_node (dn); +- np->cache_id = inum; +- + pthread_mutex_lock (&np->lock); + + /* Put NP in NODEHASH. */ +- dn->hnext = nodehash[INOHASH(inum)]; +- if (dn->hnext) +- dn->hnext->dn->hprevp = &dn->hnext; +- dn->hprevp = &nodehash[INOHASH(inum)]; +- nodehash[INOHASH(inum)] = np; + diskfs_nref_light (np); ++ rbtree_insert_slot (&nodehash, slot, &dn->tree_node); + nodehash_nr_items += 1; +- + pthread_mutex_unlock (&nodehash_lock); + + /* Get the contents of NP off disk. */ +@@ -149,16 +160,14 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) + struct node * + ifind (ino_t inum) + { +- struct node *np; ++ struct rbtree_node *node; + + pthread_mutex_lock (&nodehash_lock); +- for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) ++ node = rbtree_lookup (&nodehash, inum, node_cmp_lookup); ++ if (node != NULL) + { +- if (np->cache_id != inum) +- continue; +- + pthread_mutex_unlock (&nodehash_lock); +- return np; ++ return node_get_np (node); + } + assert (0); + } +@@ -176,7 +185,6 @@ diskfs_node_norefs (struct node *np) + pokel_inherit (&global_pokel, &np->dn->indir_pokel); + pokel_finalize (&np->dn->indir_pokel); + +- free (np->dn); + free (np); + } + +@@ -186,7 +194,7 @@ void + diskfs_try_dropping_softrefs (struct node *np) + { + pthread_mutex_lock (&nodehash_lock); +- if (np->dn->hnext != NULL) ++ if (np->cache_id != 0) + { + /* Check if someone reacquired a reference through the + nodehash. */ +@@ -200,11 +208,9 @@ diskfs_try_dropping_softrefs (struct node *np) + return; + } + +- *np->dn->hprevp = np->dn->hnext; +- if (np->dn->hnext) +- np->dn->hnext->dn->hprevp = np->dn->hprevp; +- np->dn->hnext = NULL; ++ rbtree_remove (&nodehash, &(diskfs_node_disknode (np))->tree_node); + nodehash_nr_items -= 1; ++ np->cache_id = 0; + diskfs_nrele_light (np); + } + pthread_mutex_unlock (&nodehash_lock); +@@ -581,7 +587,7 @@ error_t + diskfs_node_iterate (error_t (*fun)(struct node *)) + { + error_t err = 0; +- int n; ++ struct rbtree_node *n; + size_t num_nodes; + struct node *node, **node_list, **p; + +@@ -605,12 +611,12 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) + } + + p = node_list; +- for (n = 0; n < INOHSZ; n++) +- for (node = nodehash[n]; node; node = node->dn->hnext) +- { +- *p++ = node; +- diskfs_nref (node); +- } ++ for (n = rbtree_first (&nodehash); n; n = rbtree_next (n)) ++ { ++ node = node_get_np (n); ++ *p++ = node; ++ diskfs_nref (node); ++ } + + pthread_mutex_unlock (&nodehash_lock); + +-- +2.0.0.rc2 + |
