From e08859424e01697fe556e277283e8e1905327ce7 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 22 Aug 2017 13:07:54 +0200 Subject: libfshelp: Use node instead of name as key. Previously, libfshelp used the name of an translator as key in the hash table. This however is flawed, because a translator is bound to a node, and a node can have zero or more links in the file system. Use the nodes address (or rather, the address of the transbox embedded in the node) as key instead. * libfshelp/fshelp.h (fshelp_set_active_translator): Instead of the control port, hand the whole transbox to the function. * libfshelp/translator-list.c (struct translator): New field 'locp'. (hash): Hash pointer. (compare): Compare pointer. (translator_ihash): Use an location pointer. (fshelp_set_active_translator): Use the address of the transbox as key. (fshelp_remove_active_translator): Remove using the location pointer. * libdiskfs/dir-lookup.c (diskfs_S_dir_lookup): Fix callsite. * libdiskfs/file-set-trans.c (diskfs_S_file_set_translator): Likewise. * libnetfs/dir-lookup.c (netfs_S_dir_lookup): Likewise. * libnetfs/file-set-translator.c (netfs_S_file_set_translator): Likewise. --- libdiskfs/dir-lookup.c | 2 +- libdiskfs/file-set-trans.c | 2 +- libfshelp/fshelp.h | 10 ++++----- libfshelp/translator-list.c | 50 ++++++++++++++++++++++-------------------- libnetfs/dir-lookup.c | 2 +- libnetfs/file-set-translator.c | 2 +- 6 files changed, 35 insertions(+), 33 deletions(-) diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c index a0c368b1..eafeefc3 100644 --- a/libdiskfs/dir-lookup.c +++ b/libdiskfs/dir-lookup.c @@ -315,7 +315,7 @@ diskfs_S_dir_lookup (struct protid *dircred, err = fshelp_set_active_translator (&newpi->pi, complete_path, - np->transbox.active); + &np->transbox); if (complete_path != translator_path) free(complete_path); if (err) diff --git a/libdiskfs/file-set-trans.c b/libdiskfs/file-set-trans.c index 6a73e23c..de52ba49 100644 --- a/libdiskfs/file-set-trans.c +++ b/libdiskfs/file-set-trans.c @@ -222,7 +222,7 @@ diskfs_S_file_set_translator (struct protid *cred, pthread_mutex_unlock (&np->lock); if (! err && cred->po->path && active_flags & FS_TRANS_SET) - err = fshelp_set_active_translator (&cred->pi, cred->po->path, active); + err = fshelp_set_active_translator (&cred->pi, cred->po->path, &np->transbox); return err; } diff --git a/libfshelp/fshelp.h b/libfshelp/fshelp.h index d1dd49c4..7663ba1d 100644 --- a/libfshelp/fshelp.h +++ b/libfshelp/fshelp.h @@ -38,16 +38,16 @@ require multi threading but depend on the ports library. */ struct port_info; +struct transbox; /* Record an active translator being bound to the given file name - NAME. ACTIVE is the control port of the translator. PI references - a receive port that is used to request dead name notifications, - typically the port for the underlying node passed to the - translator. */ + NAME. TRANSBOX is the nodes transbox. PI references a receive + port that is used to request dead name notifications, typically the + port for the underlying node passed to the translator. */ error_t fshelp_set_active_translator (struct port_info *pi, const char *name, - mach_port_t active); + const struct transbox *transbox); /* Remove the active translator specified by its control port ACTIVE. If there is no active translator with the given control port, this diff --git a/libfshelp/translator-list.c b/libfshelp/translator-list.c index a3603300..7077b217 100644 --- a/libfshelp/translator-list.c +++ b/libfshelp/translator-list.c @@ -35,9 +35,13 @@ struct translator { - struct port_info *pi; - char *name; - mach_port_t active; + hurd_ihash_locp_t locp; /* Slot in the hash table. */ + struct port_info *pi; /* We get dead-name notifications + here. */ + char *name; /* The path to the node the translator + is bound to, relative to the root. + This is a best effort. */ + mach_port_t active; /* Translator control port. */ }; /* The hash table requires some callback functions. */ @@ -56,41 +60,43 @@ cleanup (void *value, void *arg) static hurd_ihash_key_t hash (const void *key) { - return (hurd_ihash_key_t) hurd_ihash_hash32 (key, strlen (key), 0); + return (hurd_ihash_key_t) hurd_ihash_hash32 (key, sizeof (void *), 0); } static int compare (const void *a, const void *b) { - return strcmp ((const char *) a, (const char *) b) == 0; + return *(void **) a == *(void **) b; } /* The list of active translators. */ static struct hurd_ihash translator_ihash - = HURD_IHASH_INITIALIZER_GKI (HURD_IHASH_NO_LOCP, cleanup, NULL, - hash, compare); + = HURD_IHASH_INITIALIZER_GKI (offsetof (struct translator, locp), + cleanup, NULL, hash, compare); /* The lock protecting the translator_ihash. */ static pthread_mutex_t translator_ihash_lock = PTHREAD_MUTEX_INITIALIZER; /* Record an active translator being bound to the given file name - NAME. ACTIVE is the control port of the translator. */ + NAME. TRANSBOX is the nodes transbox. PI references a receive + port that is used to request dead name notifications, typically the + port for the underlying node passed to the translator. */ error_t fshelp_set_active_translator (struct port_info *pi, const char *name, - mach_port_t active) + const struct transbox *transbox) { error_t err = 0; struct translator *t; hurd_ihash_locp_t slot; pthread_mutex_lock (&translator_ihash_lock); - t = hurd_ihash_locp_find (&translator_ihash, (hurd_ihash_key_t) name, + t = hurd_ihash_locp_find (&translator_ihash, (hurd_ihash_key_t) transbox, &slot); if (t) goto update; /* Entry exists. */ - if (! MACH_PORT_VALID (active)) + if (! MACH_PORT_VALID (transbox->active)) /* Avoid allocating an entry just to delete it. */ goto out; @@ -112,7 +118,7 @@ fshelp_set_active_translator (struct port_info *pi, } err = hurd_ihash_locp_add (&translator_ihash, slot, - (hurd_ihash_key_t) t->name, t); + (hurd_ihash_key_t) transbox, t); if (err) { free (t->name); @@ -121,17 +127,17 @@ fshelp_set_active_translator (struct port_info *pi, } update: - if (MACH_PORT_VALID (active) && active != t->active) + if (MACH_PORT_VALID (transbox->active) && transbox->active != t->active) { mach_port_t old; - err = mach_port_request_notification (mach_task_self (), active, + err = mach_port_request_notification (mach_task_self (), transbox->active, MACH_NOTIFY_DEAD_NAME, 0, pi->port_right, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); if (err) goto out; - if (old != MACH_PORT_NULL) + if (MACH_PORT_VALID (old)) mach_port_deallocate (mach_task_self (), old); if (t->pi) @@ -142,14 +148,14 @@ fshelp_set_active_translator (struct port_info *pi, if (MACH_PORT_VALID (t->active)) mach_port_deallocate (mach_task_self (), t->active); - mach_port_mod_refs (mach_task_self (), active, + mach_port_mod_refs (mach_task_self (), transbox->active, MACH_PORT_RIGHT_SEND, +1); - t->active = active; + t->active = transbox->active; } - else if (! MACH_PORT_VALID (active)) + else if (! MACH_PORT_VALID (transbox->active)) { int ok; - ok = hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) t->name); + ok = hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) transbox); assert_backtrace (ok); } @@ -179,11 +185,7 @@ fshelp_remove_active_translator (mach_port_t active) } if (t) - { - int ok; - ok = hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) t->name); - assert_backtrace (ok); - } + hurd_ihash_locp_remove (&translator_ihash, t->locp); pthread_mutex_unlock (&translator_ihash_lock); return err; diff --git a/libnetfs/dir-lookup.c b/libnetfs/dir-lookup.c index bfac2acd..a135917f 100644 --- a/libnetfs/dir-lookup.c +++ b/libnetfs/dir-lookup.c @@ -306,7 +306,7 @@ netfs_S_dir_lookup (struct protid *dircred, err = fshelp_set_active_translator (&newpi->pi, complete_path, - np->transbox.active); + &np->transbox); if (complete_path != translator_path) free(complete_path); if (err) diff --git a/libnetfs/file-set-translator.c b/libnetfs/file-set-translator.c index bac950e3..2b71848c 100644 --- a/libnetfs/file-set-translator.c +++ b/libnetfs/file-set-translator.c @@ -178,7 +178,7 @@ netfs_S_file_set_translator (struct protid *user, } if (! err && user->po->path && active_flags & FS_TRANS_SET) - err = fshelp_set_active_translator (&user->pi, user->po->path, active); + err = fshelp_set_active_translator (&user->pi, user->po->path, &np->transbox); out: pthread_mutex_unlock (&np->lock); -- cgit v1.2.3