summaryrefslogtreecommitdiff
path: root/debian/patches/nodeihash0001-xxx-fix-node-iteration.patch
blob: b8a8a08ed9a5f737fbb1075ef0e840643d7da79d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
From 350d08ed953cfe2c3592cf9822725a2976937ac1 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Fri, 20 Nov 2015 12:45:28 +0100
Subject: [PATCH hurd] xxx fix node iteration

---
 libdiskfs/diskfs.h     |  8 +++----
 libdiskfs/node-cache.c | 63 ++++++++++++++++----------------------------------
 2 files changed, 24 insertions(+), 47 deletions(-)

diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index 106aeb0..51bb79f 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -521,10 +521,10 @@ void diskfs_write_disknode (struct node *np, int wait);
 void diskfs_file_update (struct node *np, int wait);
 
 /* The user must define this function unless she wants to use the node
-   cache.  See the section `Node cache' below.  For each active node, call
-   FUN.  The node is to be locked around the call to FUN.  If FUN
-   returns non-zero for any node, then immediately stop, and return
-   that value. */
+   cache.  See the section `Node cache' below.  For each active node,
+   call FUN.  The node is to be locked around the call to FUN.  FUN
+   must be idempotent.  If FUN returns non-zero for any node, then
+   immediately stop, and return that value. */
 error_t diskfs_node_iterate (error_t (*fun)(struct node *));
 
 /* The user must define this function.  Sync all the pagers and any
diff --git a/libdiskfs/node-cache.c b/libdiskfs/node-cache.c
index ee7e6fd..4016779 100644
--- a/libdiskfs/node-cache.c
+++ b/libdiskfs/node-cache.c
@@ -170,61 +170,38 @@ diskfs_try_dropping_softrefs (struct node *np)
   diskfs_user_try_dropping_softrefs (np);
 }
 
-/* For each active node, call FUN.  The node is to be locked around the call
-   to FUN.  If FUN returns non-zero for any node, then immediately stop, and
-   return that value.  */
+/* For each active node, call FUN.  FUN must be idempotent.  The node
+   is to be locked around the call to FUN.  If FUN returns non-zero
+   for any node, then immediately stop, and return that value.  */
 error_t __attribute__ ((weak))
 diskfs_node_iterate (error_t (*fun)(struct node *))
 {
   error_t err = 0;
-  size_t num_nodes;
-  struct node *node, **node_list, **p;
+  struct node *node;
 
+  /* XXX */
+ restart:
   pthread_rwlock_rdlock (&nodecache_lock);
 
-  /* We must copy everything from the hash table into another data structure
-     to avoid running into any problems with the hash-table being modified
-     during processing (normally we delegate access to hash-table with
-     nodecache_lock, but we can't hold this while locking the
-     individual node locks).  */
-  /* XXX: Can we?  */
-  num_nodes = nodecache.nr_items;
-
-  /* TODO This method doesn't scale beyond a few dozen nodes and should be
-     replaced.  */
-  node_list = malloc (num_nodes * sizeof (struct node *));
-  if (node_list == NULL)
-    {
-      pthread_rwlock_unlock (&nodecache_lock);
-      return ENOMEM;
-    }
-
-  p = node_list;
   HURD_IHASH_ITERATE (&nodecache, i)
     {
-      *p++ = node = i;
-
-      /* We acquire a hard reference for node, but without using
-	 diskfs_nref.  We do this so that diskfs_new_hardrefs will not
-	 get called.  */
-      refcounts_ref (&node->refcounts, NULL);
+      node = i;
+
+      if (pthread_mutex_trylock (&node->lock))
+        {
+          /* Failed to acquire the lock.  Release the cache lock and
+             restart iteration.  */
+          pthread_rwlock_unlock (&nodecache_lock);
+          goto restart;
+        }
+      err = (*fun)(node);
+      pthread_mutex_unlock (&node->lock);
+      if (err)
+        break;
     }
-  pthread_rwlock_unlock (&nodecache_lock);
 
-  p = node_list;
-  while (num_nodes-- > 0)
-    {
-      node = *p++;
-      if (!err)
-	{
-	  pthread_mutex_lock (&node->lock);
-	  err = (*fun)(node);
-	  pthread_mutex_unlock (&node->lock);
-	}
-      diskfs_nrele (node);
-    }
+  pthread_rwlock_unlock (&nodecache_lock);
 
-  free (node_list);
   return err;
 }
 
-- 
2.1.4