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