diff options
Diffstat (limited to 'debian/patches/flavio0001-Use-libihash-to-store-directory-entries-in-ftpfs.patch')
-rw-r--r-- | debian/patches/flavio0001-Use-libihash-to-store-directory-entries-in-ftpfs.patch | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/debian/patches/flavio0001-Use-libihash-to-store-directory-entries-in-ftpfs.patch b/debian/patches/flavio0001-Use-libihash-to-store-directory-entries-in-ftpfs.patch new file mode 100644 index 00000000..d942ac2d --- /dev/null +++ b/debian/patches/flavio0001-Use-libihash-to-store-directory-entries-in-ftpfs.patch @@ -0,0 +1,385 @@ +From 3e1d2756a0a373d91155d0e4e557f2e805f37e3b Mon Sep 17 00:00:00 2001 +From: Flavio Cruz <flaviocruz@gmail.com> +Date: Sun, 7 Feb 2016 15:53:53 -0500 +Subject: [PATCH hurd] Use libihash to store directory entries in ftpfs. + +* ftpfs/ftpfs.h: Add dir_locp for each directory entry and replace the table with a libihash table. +* ftpfs/dir.c: Modify the code to use libihash. Remove several functions such as rehash and insert. +--- + ftpfs/dir.c | 158 +++++++++++++++++----------------------------------------- + ftpfs/ftpfs.h | 17 ++----- + 2 files changed, 50 insertions(+), 125 deletions(-) + +diff --git a/ftpfs/dir.c b/ftpfs/dir.c +index be20b3d..96424c2 100644 +--- a/ftpfs/dir.c ++++ b/ftpfs/dir.c +@@ -30,70 +30,29 @@ + void + free_entry (struct ftpfs_dir_entry *e) + { +- assert (! e->self_p); /* We should only free deleted nodes. */ ++ assert (e->deleted); + free (e->name); + if (e->symlink_target) + free (e->symlink_target); + free (e); + } +- +-/* Put the directory entry E into the hash table HTABLE, of length HTABLE_LEN. */ +-static void +-insert (struct ftpfs_dir_entry *e, +- struct ftpfs_dir_entry **htable, size_t htable_len) ++ ++/* Calculate NAME_PTR's hash value. */ ++static hurd_ihash_key_t ++ihash_hash (const void *name_ptr) + { +- struct ftpfs_dir_entry **t = &htable[e->hv % htable_len]; +- if (*t) +- (*t)->self_p = &e->next; +- e->next = *t; +- e->self_p = t; +- *t = e; ++ const char *name = (const char *) name_ptr; ++ return (hurd_ihash_key_t) hurd_ihash_hash32 (name, strlen (name), 0); + } + +-/* Replace DIR's hashtable with a new one of length NEW_LEN, retaining all +- existing entries. */ +-static error_t +-rehash (struct ftpfs_dir *dir, size_t new_len) ++/* Compare two names which are used as keys. */ ++static int ++ihash_compare (const void *key1, const void *key2) + { +- int i; +- size_t old_len = dir->htable_len; +- struct ftpfs_dir_entry **old_htable = dir->htable; +- struct ftpfs_dir_entry **new_htable = +- malloc (new_len * sizeof (struct ftpfs_dir_entry *)); +- +- if (! new_htable) +- return ENOMEM; +- +- memset (new_htable, 0, new_len * sizeof(struct ftpfs_dir_entry *)); +- +- for (i = 0; i < old_len; i++) +- while (old_htable[i]) +- { +- struct ftpfs_dir_entry *e = old_htable[i]; +- +- /* Remove E from the old table (don't bother to fixup +- e->next->self_p). */ +- old_htable[i] = e->next; +- +- insert (e, new_htable, new_len); +- } +- +- free (old_htable); ++ const char *name1 = (const char *) key1; ++ const char *name2 = (const char *) key2; + +- dir->htable = new_htable; +- dir->htable_len = new_len; +- +- return 0; +-} +- +-/* Calculate NAME's hash value. */ +-static size_t +-hash (const char *name) +-{ +- size_t hv = 0; +- while (*name) +- hv = ((hv << 5) + *name++) & 0xFFFFFF; +- return hv; ++ return strcmp (name1, name2) == 0; + } + + /* Lookup NAME in DIR and return its entry. If there is no such entry, and +@@ -103,23 +62,14 @@ hash (const char *name) + struct ftpfs_dir_entry * + lookup (struct ftpfs_dir *dir, const char *name, int add) + { +- size_t hv = hash (name); +- struct ftpfs_dir_entry *h = dir->htable[hv % dir->htable_len], *e = h; +- +- while (e && strcmp (name, e->name) != 0) +- e = e->next; ++ struct ftpfs_dir_entry *e = ++ hurd_ihash_find (&dir->htable, (hurd_ihash_key_t) name); + + if (!e && add) + { +- if (dir->num_entries > dir->htable_len) +- /* Grow the hash table. */ +- if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) +- return 0; +- + e = malloc (sizeof *e); + if (e) + { +- e->hv = hv; + e->name = strdup (name); + e->node = 0; + e->dir = dir; +@@ -128,19 +78,17 @@ lookup (struct ftpfs_dir *dir, const char *name, int add) + e->symlink_target = 0; + e->noent = 0; + e->valid = 0; ++ e->deleted = 0; + e->name_timestamp = e->stat_timestamp = 0; + e->ordered_next = 0; + e->ordered_self_p = 0; +- e->next = 0; +- e->self_p = 0; +- insert (e, dir->htable, dir->htable_len); +- dir->num_entries++; ++ hurd_ihash_add (&dir->htable, (hurd_ihash_key_t) e->name, e); + } + } + + return e; + } +- ++ + /* Remove E from its position in the ordered_next chain. */ + static void + ordered_unlink (struct ftpfs_dir_entry *e) +@@ -148,59 +96,50 @@ ordered_unlink (struct ftpfs_dir_entry *e) + if (e->ordered_self_p) + *e->ordered_self_p = e->ordered_next; + if (e->ordered_next) +- e->ordered_next->self_p = e->ordered_self_p; ++ e->ordered_next->ordered_self_p = e->ordered_self_p; + } + + /* Delete E from its directory, freeing any resources it holds. */ + static void + delete (struct ftpfs_dir_entry *e, struct ftpfs_dir *dir) + { +- dir->num_entries--; +- +- /* Take out of the hash chain. */ +- if (e->self_p) +- *e->self_p = e->next; +- if (e->next) +- e->next->self_p = e->self_p; +- + /* This indicates a deleted entry. */ +- e->self_p = 0; +- e->next = 0; ++ e->deleted = 1; + + /* Take out of the directory ordered list. */ + ordered_unlink (e); + ++ hurd_ihash_locp_remove (&dir->htable, e->dir_locp); ++ + /* If there's a node attached, we'll delete the entry whenever it goes + away, otherwise, just delete it now. */ + if (! e->node) + free_entry (e); + } +- ++ + /* Clear the valid bit in all DIR's htable. */ + static void + mark (struct ftpfs_dir *dir) + { +- size_t len = dir->htable_len, i; +- struct ftpfs_dir_entry **htable = dir->htable, *e; +- +- for (i = 0; i < len; i++) +- for (e = htable[i]; e; e = e->next) ++ HURD_IHASH_ITERATE (&dir->htable, value) ++ { ++ struct ftpfs_dir_entry *e = (struct ftpfs_dir_entry *) value; + e->valid = 0; ++ } + } + + /* Delete any entries in DIR which don't have their valid bit set. */ + static void + sweep (struct ftpfs_dir *dir) + { +- size_t len = dir->htable_len, i; +- struct ftpfs_dir_entry **htable = dir->htable, *e; +- +- for (i = 0; i < len; i++) +- for (e = htable[i]; e; e = e->next) ++ HURD_IHASH_ITERATE (&dir->htable, value) ++ { ++ struct ftpfs_dir_entry *e = (struct ftpfs_dir_entry *) value; + if (!e->valid && !e->noent) +- delete (e, dir); ++ delete (e, dir); ++ } + } +- ++ + /* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. + True is returned if successful, or false if there was a memory allocation + error. TIMESTAMP is used to record the time of this update. */ +@@ -238,7 +177,7 @@ update_entry (struct ftpfs_dir_entry *e, const struct stat *st, + e->stat.st_fsid = fs->fsid; + e->stat.st_fstype = FSTYPE_FTP; + } +- ++ + /* Add the timestamp TIMESTAMP to the set used to detect bulk stats, and + return true if there have been enough individual stats recently to call + for just refetching the whole directory. */ +@@ -466,7 +405,7 @@ ftpfs_refresh_node (struct node *node) + + pthread_mutex_lock (&dir->node->lock); + +- if (! entry->self_p) ++ if (entry->deleted) + /* This is a deleted entry, just awaiting disposal; do so. */ + { + nn->dir_entry = 0; +@@ -556,7 +495,7 @@ ftpfs_refresh_node (struct node *node) + return err; + } + } +- ++ + /* Remove NODE from its entry (if the entry is still valid, it will remain + without a node). NODE should be locked. */ + error_t +@@ -572,7 +511,7 @@ ftpfs_detach_node (struct node *node) + + pthread_mutex_lock (&dir->node->lock); + +- if (entry->self_p) ++ if (!entry->deleted) + /* Just detach NODE from the still active entry. */ + entry->node = 0; + else +@@ -590,7 +529,7 @@ ftpfs_detach_node (struct node *node) + + return 0; + } +- ++ + /* State shared between ftpfs_dir_lookup and update_new_entry. */ + struct new_entry_state + { +@@ -777,7 +716,7 @@ ftpfs_dir_lookup (struct ftpfs_dir *dir, const char *name, + + return err; + } +- ++ + /* Lookup the null name in DIR, and return a node for it in NODE. Unlike + ftpfs_dir_lookup, this won't attempt to validate the existence of the + entry (to avoid opening a new connection if possible) -- that will happen +@@ -825,7 +764,7 @@ ftpfs_dir_null_lookup (struct ftpfs_dir *dir, struct node **node) + + return err; + } +- ++ + /* Size of initial htable for a new directory. */ + #define INIT_HTABLE_LEN 5 + +@@ -837,15 +776,10 @@ ftpfs_dir_create (struct ftpfs *fs, struct node *node, const char *rmt_path, + struct ftpfs_dir **dir) + { + struct ftpfs_dir *new = malloc (sizeof (struct ftpfs_dir)); +- struct ftpfs_dir_entry **htable +- = calloc (INIT_HTABLE_LEN, sizeof (struct ftpfs_dir_entry *)); + +- if (!new || !htable) ++ if (!new) + { +- if (new) +- free (new); +- if (htable) +- free (htable); ++ free (new); + return ENOMEM; + } + +@@ -854,10 +788,9 @@ ftpfs_dir_create (struct ftpfs *fs, struct node *node, const char *rmt_path, + node->references++; + pthread_spin_unlock (&netfs_node_refcnt_lock); + +- new->num_entries = 0; ++ hurd_ihash_init (&new->htable, offsetof (struct ftpfs_dir_entry, dir_locp)); ++ hurd_ihash_set_gki (&new->htable, ihash_hash, ihash_compare); + new->num_live_entries = 0; +- new->htable_len = INIT_HTABLE_LEN; +- new->htable = htable; + new->ordered = 0; + new->rmt_path = rmt_path; + new->fs = fs; +@@ -880,8 +813,7 @@ ftpfs_dir_free (struct ftpfs_dir *dir) + mark (dir); + sweep (dir); + +- if (dir->htable) +- free (dir->htable); ++ hurd_ihash_destroy (&dir->htable); + + netfs_nrele (dir->node); + +diff --git a/ftpfs/ftpfs.h b/ftpfs/ftpfs.h +index 206726f..a067bfe 100644 +--- a/ftpfs/ftpfs.h ++++ b/ftpfs/ftpfs.h +@@ -35,7 +35,6 @@ struct ftpfs_conn; + struct ftpfs_dir_entry + { + char *name; /* Name of this entry */ +- size_t hv; /* Hash value of NAME (before mod'ing) */ + + /* The active node referred to by this name (may be 0). + NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ +@@ -48,11 +47,6 @@ struct ftpfs_dir_entry + /* The directory to which this entry belongs. */ + struct ftpfs_dir *dir; + +- /* Link to next entry in hash bucket, and address of previous entry's (or +- hash table's) pointer to this entry. If the SELF_P field is 0, then +- this is a deleted entry, awaiting final disposal. */ +- struct ftpfs_dir_entry *next, **self_p; +- + /* Next entry in `directory order', or 0 if none known. */ + struct ftpfs_dir_entry *ordered_next, **ordered_self_p; + +@@ -61,24 +55,23 @@ struct ftpfs_dir_entry + + hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ + ++ hurd_ihash_locp_t dir_locp; /* Position in the directory table. */ ++ + int noent : 1; /* A negative lookup result. */ + int valid : 1; /* Marker for GC'ing. */ ++ int deleted : 1; /* Indicates a deleted entry. */ + }; + + /* A directory. */ + struct ftpfs_dir + { +- /* Number of entries in HTABLE. */ +- size_t num_entries; ++ /* Hash table mapping names to children nodes. */ ++ struct hurd_ihash htable; + + /* The number of entries that have nodes attached. We keep an additional + reference to our node if there are any, to prevent it from going away. */ + size_t num_live_entries; + +- /* Hash table of entries. */ +- struct ftpfs_dir_entry **htable; +- size_t htable_len; /* # of elements in HTABLE (not bytes). */ +- + /* List of dir entries in `directory order', in a linked list using the + ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries + in HTABLE need be in this list. */ +-- +2.1.4 + |