summaryrefslogtreecommitdiff
path: root/trans
diff options
context:
space:
mode:
authorFlavio Cruz <flaviocruz@gmail.com>2016-03-15 04:50:02 -0400
committerJustus Winter <justus@gnupg.org>2016-03-21 19:45:11 +0100
commit5eef605eb523e4148ccd22578327492178cfd0c4 (patch)
treeaab9f03896e9acec97d99b5617bf7792f6022f0d /trans
parent0da2914ac9d9321cca2d402b2c505881e436c725 (diff)
netfs: Remove global reference count lock.
* libnetfs/drop-node.c: Remove use of netfs_node_refcnt_lock. * libnetfs/init-init.c: Remove netfs_node_refcnt_lock. * libnetfs/make-node.c: Initialize refcounts in refcounts_init. * libnetfs/netfs.h: Use refcounts_t for tracking node references. Remove netfs_node_refcnt_lock. Add netfs_nref_light, netfs_nrele_light and handler netfs_try_dropping_softrefs. Adjust comments. * libnetfs/nput.c: Use refcounts_t. Call netfs_try_dropping_softrefs to remove any soft reference that the translator might have acquired during the lifetime of the node. Implement empty netfs_try_dropping_softrefs. * libnetfs/nref.c: Implement netfs_nref_light. * libnetfs/nrele.c: Use refcounts_t and netfs_try_dropping_softrefs. Implement netfs_nrele_light. * ftpfs/dir.c: Use netfs_nref without locking the old netfs_node_refcnt_lock. * ftpfs/node.c: Likewise. * usermux/mux.c: Use netfs_nref to increase hard references of the node. * hostmux/mux.c: Use netfs_nref to increase hard references of the node. * trans/fakeroot.c (new_node): Use a light reference when storing a node in the hash table. * trans/fakeroot.c (netfs_try_dropping_softrefs): Implement netfs_try_dropping_softrefs to remove the node from the hash table. * trans/fakeroot.c (netfs_node_norefs): Remove code to remove the node from the hash table. * trans/fakeroot.c (netfs_S_dir_lookup): Simplify lookup code since we don't need to lock netfs_node_refcnt_lock anymore. * procfs/netfs.c: Remove use of netfs_node_refcnt_lock. * nfs/cache.c: Add mutex to handle exclusive access to nodehash. This replaces the use of netfs_node_refcnt_lock. * nfs/cache.c (lookup_handle): Use nodehash_ihash_lock when accessing nodehash. Use netfs_nref_light to add one soft reference to the node just added to nodehash. * nfs/cache.c (netfs_node_norefs): Use netfs_nref. Don't use netfs_node_refcnt_lock and don't remove the node from nodehash here. * nfs/cache.c (netfs_try_dropping_softrefs): Drop the light reference when the node has no more hard references. * nfs/cache.c (recache_handle): Use nodehash_ihash_lock instead. * nfs/ops.c (netds_attempt_unlink): Use refcounts_references. * console/console.c (netfs_node_norefs): Use a soft reference to store a node in dir_node, cons_node, disp_node, inp_node. * console/console.c (netfs_try_dropping_softrefs): When dropping all soft references remove node pointer from the fields above.
Diffstat (limited to 'trans')
-rw-r--r--trans/fakeroot.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/trans/fakeroot.c b/trans/fakeroot.c
index cb4f818d..ad7bec98 100644
--- a/trans/fakeroot.c
+++ b/trans/fakeroot.c
@@ -108,6 +108,9 @@ new_node (file_t file, mach_port_t idport, int locked, int openmodes,
}
nn->faked = FAKE_DEFAULT;
+ /* The light reference allows us to safely keep the node in the
+ hash table. */
+ netfs_nref_light (*np);
if (!locked)
pthread_mutex_lock (&idport_ihash_lock);
err = hurd_ihash_add (&idport_ihash, nn->idport, *np);
@@ -155,22 +158,31 @@ set_faked_attribute (struct node *np, unsigned int faked)
}
}
+void
+netfs_try_dropping_softrefs (struct node *np)
+{
+ /* We have to drop our light reference by removing the node from the
+ idport_ihash hash table. */
+ pthread_mutex_lock (&idport_ihash_lock);
+
+ hurd_ihash_locp_remove (&idport_ihash, netfs_node_netnode (np)->idport_locp);
+ pthread_mutex_unlock (&idport_ihash_lock);
+
+ netfs_nrele_light (np);
+}
+
/* Node NP has no more references; free all its associated storage. */
void
netfs_node_norefs (struct node *np)
{
pthread_mutex_unlock (&np->lock);
- pthread_spin_unlock (&netfs_node_refcnt_lock);
- pthread_mutex_lock (&idport_ihash_lock);
- hurd_ihash_locp_remove (&idport_ihash, netfs_node_netnode (np)->idport_locp);
- pthread_mutex_unlock (&idport_ihash_lock);
+ /* NP was already removed from idport_ihash through
+ netfs_try_dropping_softrefs. */
mach_port_deallocate (mach_task_self (), netfs_node_netnode (np)->file);
mach_port_deallocate (mach_task_self (), netfs_node_netnode (np)->idport);
free (np);
-
- pthread_spin_lock (&netfs_node_refcnt_lock);
}
/* This is the cleanup function we install in netfs_protid_class. If
@@ -363,29 +375,27 @@ netfs_S_dir_lookup (struct protid *diruser,
redo_hash_lookup:
pthread_mutex_lock (&idport_ihash_lock);
pthread_mutex_lock (&dnp->lock);
- /* The hashtable may not hold a true reference on the node. Acquire the
- refcount lock so that, if a node is found, its reference counter cannot
- drop to 0 before we get our own reference. */
- pthread_spin_lock (&netfs_node_refcnt_lock);
np = hurd_ihash_find (&idport_ihash, idport);
if (np != NULL)
{
- /* We already know about this node. */
+ /* We quickly check that NP has hard references. If the node is being
+ removed, netfs_try_dropping_softrefs is attempting to drop the light
+ reference on this. */
+ struct references result;
+
+ refcounts_references (&np->refcounts, &result);
- if (np->references == 0)
+ if (result.hard == 0)
{
- /* But it might be in the process of being released. If so,
- unlock the hash table to give the node a chance to actually
+ /* If so, unlock the hash table to give the node a chance to actually
be removed and retry. */
- pthread_spin_unlock (&netfs_node_refcnt_lock);
pthread_mutex_unlock (&dnp->lock);
pthread_mutex_unlock (&idport_ihash_lock);
goto redo_hash_lookup;
}
/* Otherwise, reference it right away. */
- np->references++;
- pthread_spin_unlock (&netfs_node_refcnt_lock);
+ netfs_nref (np);
mach_port_deallocate (mach_task_self (), idport);
@@ -405,7 +415,6 @@ netfs_S_dir_lookup (struct protid *diruser,
}
else
{
- pthread_spin_unlock (&netfs_node_refcnt_lock);
err = new_node (file, idport, 1, flags & (O_RDWR|O_EXEC), &np);
pthread_mutex_unlock (&dnp->lock);
if (!err)