summaryrefslogtreecommitdiff
path: root/debian/patches/0007-libtrivfs-lock-less-reference-counting-for-trivfs_pe.patch
blob: 7e3bf100a3084f88482b72c403beb7a48ac38cff (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
From c4bd59b5b1bda56338215fd509e9414ec8c7f052 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Tue, 6 May 2014 19:07:13 +0200
Subject: [PATCH 07/15] libtrivfs: lock-less reference counting for
 trivfs_peropen objects

* libtrivfs/trivfs.h (struct trivfs_peropen): Use refcount_t for field
refcnt.
(struct trivfs_control): Remove unused field lock.
* libtrivfs/cntl-create.c (trivfs_create_control): Drop the mutex
initialization.
* libtrivfs/io-reauthenticate.c (trivfs_S_io_reauthenticate): Adjust
accordingly.
* libtrivfs/io-restrict-auth.c (trivfs_S_io_restrict_auth): Likewise.
* libtrivfs/open.c (trivfs_open): Initialize refcnt.
* libtrivfs/protid-clean.c (trivfs_clean_protid): Likewise.
* libtrivfs/protid-dup.c (trivfs_protid_dup): Likewise.
---
 libtrivfs/cntl-create.c       |  1 -
 libtrivfs/io-reauthenticate.c |  5 +----
 libtrivfs/io-restrict-auth.c  |  4 +---
 libtrivfs/open.c              |  2 +-
 libtrivfs/protid-clean.c      | 26 +++++++++++++++-----------
 libtrivfs/protid-dup.c        |  5 +----
 libtrivfs/trivfs.h            |  4 ++--
 7 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/libtrivfs/cntl-create.c b/libtrivfs/cntl-create.c
index 910daf3..eb9a834 100644
--- a/libtrivfs/cntl-create.c
+++ b/libtrivfs/cntl-create.c
@@ -85,7 +85,6 @@ trivfs_create_control (mach_port_t underlying,
 	}
 
       (*control)->hook = 0;
-      pthread_mutex_init (&(*control)->lock, NULL);
     }
 
 out:
diff --git a/libtrivfs/io-reauthenticate.c b/libtrivfs/io-reauthenticate.c
index 7677697..df0ed2e 100644
--- a/libtrivfs/io-reauthenticate.c
+++ b/libtrivfs/io-reauthenticate.c
@@ -62,11 +62,8 @@ trivfs_S_io_reauthenticate (struct trivfs_protid *cred,
     newcred->isroot = 1;
 
   newcred->hook = cred->hook;
-
-  pthread_mutex_lock (&cred->po->cntl->lock);
   newcred->po = cred->po;
-  newcred->po->refcnt++;
-  pthread_mutex_unlock (&cred->po->cntl->lock);
+  refcount_ref (&newcred->po->refcnt);
 
   do
     err = io_restrict_auth (newcred->po->cntl->underlying, &newcred->realnode,
diff --git a/libtrivfs/io-restrict-auth.c b/libtrivfs/io-restrict-auth.c
index 65b4fd6..39670fe 100644
--- a/libtrivfs/io-restrict-auth.c
+++ b/libtrivfs/io-restrict-auth.c
@@ -110,10 +110,8 @@ trivfs_S_io_restrict_auth (struct trivfs_protid *cred,
     }
 
   newcred->isroot = 0;
-  pthread_mutex_lock (&cred->po->cntl->lock);
   newcred->po = cred->po;
-  newcred->po->refcnt++;
-  pthread_mutex_unlock (&cred->po->cntl->lock);
+  refcount_ref (&newcred->po->refcnt);
   if (cred->isroot && idvec_contains (user->uids, 0))
     newcred->isroot = 1;
   newcred->user = user;
diff --git a/libtrivfs/open.c b/libtrivfs/open.c
index f64d2ff..97e70a1 100644
--- a/libtrivfs/open.c
+++ b/libtrivfs/open.c
@@ -40,7 +40,7 @@ trivfs_open (struct trivfs_control *cntl,
 
   ports_port_ref (cntl);
 
-  po->refcnt = 1;
+  refcount_init (&po->refcnt, 1);
   po->cntl = cntl;
   po->openmodes = flags;
   po->hook = 0;
diff --git a/libtrivfs/protid-clean.c b/libtrivfs/protid-clean.c
index f98da6a..cce736d 100644
--- a/libtrivfs/protid-clean.c
+++ b/libtrivfs/protid-clean.c
@@ -31,19 +31,23 @@ trivfs_clean_protid (void *arg)
     (*trivfs_protid_destroy_hook) (cred);
 
   /* If we hold the only reference to the peropen, try to get rid of it. */
-  pthread_mutex_lock (&cntl->lock);
-  if (cred->po->refcnt == 1 && trivfs_peropen_destroy_hook)
+  if (refcount_deref (&cred->po->refcnt) == 0)
     {
-      pthread_mutex_unlock (&cntl->lock);
-      (*trivfs_peropen_destroy_hook) (cred->po);
-      pthread_mutex_lock (&cntl->lock);
+      if (trivfs_peropen_destroy_hook)
+        {
+          /* Reaquire a reference while we call the hook.  */
+          refcount_ref (&cred->po->refcnt);
+          (*trivfs_peropen_destroy_hook) (cred->po);
+          if (refcount_deref (&cred->po->refcnt) == 0)
+            goto free_po;
+        }
+      else
+        {
+        free_po:
+          ports_port_deref (cntl);
+          free (cred->po);
+        }
     }
-  if (--cred->po->refcnt == 0)
-    {
-      ports_port_deref (cntl);
-      free (cred->po);
-    }
-  pthread_mutex_unlock (&cntl->lock);
 
   iohelp_free_iouser (cred->user);
 
diff --git a/libtrivfs/protid-dup.c b/libtrivfs/protid-dup.c
index 6169603..75f3ca8 100644
--- a/libtrivfs/protid-dup.c
+++ b/libtrivfs/protid-dup.c
@@ -35,11 +35,8 @@ trivfs_protid_dup (struct trivfs_protid *cred, struct trivfs_protid **dup)
 
   if (! err)
     {
-      pthread_mutex_lock (&cred->po->cntl->lock);
       new->po = cred->po;
-      new->po->refcnt++;
-      pthread_mutex_unlock (&cred->po->cntl->lock);
-
+      refcount_ref (&new->po->refcnt);
       new->isroot = cred->isroot;
 
       err = iohelp_dup_iouser (&new->user, cred->user);
diff --git a/libtrivfs/trivfs.h b/libtrivfs/trivfs.h
index bb456ff..8902338 100644
--- a/libtrivfs/trivfs.h
+++ b/libtrivfs/trivfs.h
@@ -24,6 +24,7 @@
 #include <mach/mach.h>
 #include <hurd/ports.h>
 #include <hurd/iohelp.h>
+#include <refcount.h>
 
 struct trivfs_protid
 {
@@ -41,14 +42,13 @@ struct trivfs_peropen
 {
   void *hook;			/* for user use */
   int openmodes;
-  int refcnt;
+  refcount_t refcnt;
   struct trivfs_control *cntl;
 };
 
 struct trivfs_control
 {
   struct port_info pi;
-  pthread_mutex_t lock;
   struct port_class *protid_class;
   struct port_bucket *protid_bucket;
   mach_port_t filesys_id;
-- 
2.0.0.rc0