From 5eef605eb523e4148ccd22578327492178cfd0c4 Mon Sep 17 00:00:00 2001 From: Flavio Cruz <flaviocruz@gmail.com> Date: Tue, 15 Mar 2016 04:50:02 -0400 Subject: 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. --- console/console.c | 64 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 27 deletions(-) (limited to 'console/console.c') diff --git a/console/console.c b/console/console.c index 57ae8133..9c5869dd 100644 --- a/console/console.c +++ b/console/console.c @@ -415,47 +415,51 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type) /* Node management. */ -/* Node NP has no more references; free all its associated - storage. */ +/* We need to drop the soft references on NP. */ void -netfs_node_norefs (struct node *np) +netfs_try_dropping_softrefs (struct node *np) { vcons_t vcons = np->nn->vcons; + int release = FALSE; - /* The root node does never go away. */ - assert (!np->nn->cons && np->nn->vcons); - - /* Avoid deadlock. */ - pthread_spin_unlock (&netfs_node_refcnt_lock); - - /* Find the back reference to ourself in the virtual console - structure, and delete it. */ pthread_mutex_lock (&vcons->lock); - pthread_spin_lock (&netfs_node_refcnt_lock); - if (np->references) + if (np == vcons->dir_node) { - /* Someone else got a reference while we were attempting to go - away. This can happen in netfs_attempt_lookup. In this - case, just unlock the node and do nothing else. */ - pthread_mutex_unlock (&vcons->lock); - pthread_mutex_unlock (&np->lock); - return; + release = TRUE; + vcons->dir_node = 0; } - if (np == vcons->dir_node) - vcons->dir_node = 0; else if (np == vcons->cons_node) - vcons->cons_node = 0; + { + release = TRUE; + vcons->cons_node = 0; + } else if (np == vcons->disp_node) - vcons->disp_node = 0; - else { - assert (np == vcons->inpt_node); + release = TRUE; + vcons->disp_node = 0; + } + else if (np == vcons->inpt_node) + { + release = TRUE; vcons->inpt_node = 0; } + if (release) + netfs_nrele_light (np); pthread_mutex_unlock (&vcons->lock); /* Release our reference. */ - vcons_release (vcons); + if (release) + vcons_release (vcons); + +} + +/* Node NP has no more references; free all its associated + storage. */ +void +netfs_node_norefs (struct node *np) +{ + /* The root node does never go away. */ + assert (!np->nn->cons && np->nn->vcons); free (np->nn); free (np); @@ -634,7 +638,10 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir, the virtual console. */ err = new_node (node, vcons, VCONS_NODE_DIR); if (!err) - vcons->dir_node = *node; + { + vcons->dir_node = *node; + netfs_nref_light (*node); + } else release_vcons = 1; } @@ -663,6 +670,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir, if (!err) { vcons->cons_node = *node; + netfs_nref_light (*node); ref_vcons = 1; } } @@ -682,6 +690,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir, if (!err) { vcons->disp_node = *node; + netfs_nref_light (*node); ref_vcons = 1; } } @@ -701,6 +710,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir, if (!err) { vcons->inpt_node = *node; + netfs_nref_light (*node); ref_vcons = 1; } } -- cgit v1.2.3