diff options
author | Flavio Cruz <flaviocruz@gmail.com> | 2016-03-15 04:50:02 -0400 |
---|---|---|
committer | Justus Winter <justus@gnupg.org> | 2016-03-21 19:45:11 +0100 |
commit | 5eef605eb523e4148ccd22578327492178cfd0c4 (patch) | |
tree | aab9f03896e9acec97d99b5617bf7792f6022f0d /trans | |
parent | 0da2914ac9d9321cca2d402b2c505881e436c725 (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.c | 45 |
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) |