Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
fs
btrfs
locking.c
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2008 Oracle. All rights reserved.
3
*
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public
6
* License v2 as published by the Free Software Foundation.
7
*
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
12
*
13
* You should have received a copy of the GNU General Public
14
* License along with this program; if not, write to the
15
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16
* Boston, MA 021110-1307, USA.
17
*/
18
#include <linux/sched.h>
19
#include <
linux/pagemap.h
>
20
#include <
linux/spinlock.h
>
21
#include <
linux/page-flags.h
>
22
#include <asm/bug.h>
23
#include "
ctree.h
"
24
#include "
extent_io.h
"
25
#include "
locking.h
"
26
27
void
btrfs_assert_tree_read_locked
(
struct
extent_buffer
*
eb
);
28
29
/*
30
* if we currently have a spinning reader or writer lock
31
* (indicated by the rw flag) this will bump the count
32
* of blocking holders and drop the spinlock.
33
*/
34
void
btrfs_set_lock_blocking_rw
(
struct
extent_buffer
*
eb
,
int
rw
)
35
{
36
if
(eb->
lock_nested
) {
37
read_lock
(&eb->
lock
);
38
if
(eb->
lock_nested
&&
current
->pid == eb->
lock_owner
) {
39
read_unlock
(&eb->
lock
);
40
return
;
41
}
42
read_unlock
(&eb->
lock
);
43
}
44
if
(rw ==
BTRFS_WRITE_LOCK
) {
45
if
(
atomic_read
(&eb->
blocking_writers
) == 0) {
46
WARN_ON
(
atomic_read
(&eb->
spinning_writers
) != 1);
47
atomic_dec
(&eb->
spinning_writers
);
48
btrfs_assert_tree_locked
(eb);
49
atomic_inc
(&eb->
blocking_writers
);
50
write_unlock
(&eb->
lock
);
51
}
52
}
else
if
(rw ==
BTRFS_READ_LOCK
) {
53
btrfs_assert_tree_read_locked
(eb);
54
atomic_inc
(&eb->
blocking_readers
);
55
WARN_ON
(
atomic_read
(&eb->
spinning_readers
) == 0);
56
atomic_dec
(&eb->
spinning_readers
);
57
read_unlock
(&eb->
lock
);
58
}
59
return
;
60
}
61
62
/*
63
* if we currently have a blocking lock, take the spinlock
64
* and drop our blocking count
65
*/
66
void
btrfs_clear_lock_blocking_rw
(
struct
extent_buffer
*
eb
,
int
rw
)
67
{
68
if
(eb->
lock_nested
) {
69
read_lock
(&eb->
lock
);
70
if
(eb->
lock_nested
&&
current
->pid == eb->
lock_owner
) {
71
read_unlock
(&eb->
lock
);
72
return
;
73
}
74
read_unlock
(&eb->
lock
);
75
}
76
if
(rw ==
BTRFS_WRITE_LOCK_BLOCKING
) {
77
BUG_ON
(
atomic_read
(&eb->
blocking_writers
) != 1);
78
write_lock
(&eb->
lock
);
79
WARN_ON
(
atomic_read
(&eb->
spinning_writers
));
80
atomic_inc
(&eb->
spinning_writers
);
81
if
(
atomic_dec_and_test
(&eb->
blocking_writers
) &&
82
waitqueue_active(&eb->
write_lock_wq
))
83
wake_up
(&eb->
write_lock_wq
);
84
}
else
if
(rw ==
BTRFS_READ_LOCK_BLOCKING
) {
85
BUG_ON
(
atomic_read
(&eb->
blocking_readers
) == 0);
86
read_lock
(&eb->
lock
);
87
atomic_inc
(&eb->
spinning_readers
);
88
if
(
atomic_dec_and_test
(&eb->
blocking_readers
) &&
89
waitqueue_active(&eb->
read_lock_wq
))
90
wake_up
(&eb->
read_lock_wq
);
91
}
92
return
;
93
}
94
95
/*
96
* take a spinning read lock. This will wait for any blocking
97
* writers
98
*/
99
void
btrfs_tree_read_lock
(
struct
extent_buffer
*
eb
)
100
{
101
again:
102
read_lock
(&eb->
lock
);
103
if
(
atomic_read
(&eb->
blocking_writers
) &&
104
current
->pid == eb->
lock_owner
) {
105
/*
106
* This extent is already write-locked by our thread. We allow
107
* an additional read lock to be added because it's for the same
108
* thread. btrfs_find_all_roots() depends on this as it may be
109
* called on a partly (write-)locked tree.
110
*/
111
BUG_ON
(eb->
lock_nested
);
112
eb->
lock_nested
= 1;
113
read_unlock
(&eb->
lock
);
114
return
;
115
}
116
read_unlock
(&eb->
lock
);
117
wait_event
(eb->
write_lock_wq
,
atomic_read
(&eb->
blocking_writers
) == 0);
118
read_lock
(&eb->
lock
);
119
if
(
atomic_read
(&eb->
blocking_writers
)) {
120
read_unlock
(&eb->
lock
);
121
goto
again;
122
}
123
atomic_inc
(&eb->
read_locks
);
124
atomic_inc
(&eb->
spinning_readers
);
125
}
126
127
/*
128
* returns 1 if we get the read lock and 0 if we don't
129
* this won't wait for blocking writers
130
*/
131
int
btrfs_try_tree_read_lock
(
struct
extent_buffer
*
eb
)
132
{
133
if
(
atomic_read
(&eb->
blocking_writers
))
134
return
0;
135
136
read_lock
(&eb->
lock
);
137
if
(
atomic_read
(&eb->
blocking_writers
)) {
138
read_unlock
(&eb->
lock
);
139
return
0;
140
}
141
atomic_inc
(&eb->
read_locks
);
142
atomic_inc
(&eb->
spinning_readers
);
143
return
1;
144
}
145
146
/*
147
* returns 1 if we get the read lock and 0 if we don't
148
* this won't wait for blocking writers or readers
149
*/
150
int
btrfs_try_tree_write_lock
(
struct
extent_buffer
*
eb
)
151
{
152
if
(
atomic_read
(&eb->
blocking_writers
) ||
153
atomic_read
(&eb->
blocking_readers
))
154
return
0;
155
write_lock
(&eb->
lock
);
156
if
(
atomic_read
(&eb->
blocking_writers
) ||
157
atomic_read
(&eb->
blocking_readers
)) {
158
write_unlock
(&eb->
lock
);
159
return
0;
160
}
161
atomic_inc
(&eb->
write_locks
);
162
atomic_inc
(&eb->
spinning_writers
);
163
eb->
lock_owner
=
current
->pid;
164
return
1;
165
}
166
167
/*
168
* drop a spinning read lock
169
*/
170
void
btrfs_tree_read_unlock
(
struct
extent_buffer
*
eb
)
171
{
172
if
(eb->
lock_nested
) {
173
read_lock
(&eb->
lock
);
174
if
(eb->
lock_nested
&&
current
->pid == eb->
lock_owner
) {
175
eb->
lock_nested
= 0;
176
read_unlock
(&eb->
lock
);
177
return
;
178
}
179
read_unlock
(&eb->
lock
);
180
}
181
btrfs_assert_tree_read_locked
(eb);
182
WARN_ON
(
atomic_read
(&eb->
spinning_readers
) == 0);
183
atomic_dec
(&eb->
spinning_readers
);
184
atomic_dec
(&eb->
read_locks
);
185
read_unlock
(&eb->
lock
);
186
}
187
188
/*
189
* drop a blocking read lock
190
*/
191
void
btrfs_tree_read_unlock_blocking
(
struct
extent_buffer
*
eb
)
192
{
193
if
(eb->
lock_nested
) {
194
read_lock
(&eb->
lock
);
195
if
(eb->
lock_nested
&&
current
->pid == eb->
lock_owner
) {
196
eb->
lock_nested
= 0;
197
read_unlock
(&eb->
lock
);
198
return
;
199
}
200
read_unlock
(&eb->
lock
);
201
}
202
btrfs_assert_tree_read_locked
(eb);
203
WARN_ON
(
atomic_read
(&eb->
blocking_readers
) == 0);
204
if
(
atomic_dec_and_test
(&eb->
blocking_readers
) &&
205
waitqueue_active(&eb->
read_lock_wq
))
206
wake_up
(&eb->
read_lock_wq
);
207
atomic_dec
(&eb->
read_locks
);
208
}
209
210
/*
211
* take a spinning write lock. This will wait for both
212
* blocking readers or writers
213
*/
214
void
btrfs_tree_lock
(
struct
extent_buffer
*
eb
)
215
{
216
again:
217
wait_event
(eb->
read_lock_wq
,
atomic_read
(&eb->
blocking_readers
) == 0);
218
wait_event
(eb->
write_lock_wq
,
atomic_read
(&eb->
blocking_writers
) == 0);
219
write_lock
(&eb->
lock
);
220
if
(
atomic_read
(&eb->
blocking_readers
)) {
221
write_unlock
(&eb->
lock
);
222
wait_event
(eb->
read_lock_wq
,
223
atomic_read
(&eb->
blocking_readers
) == 0);
224
goto
again;
225
}
226
if
(
atomic_read
(&eb->
blocking_writers
)) {
227
write_unlock
(&eb->
lock
);
228
wait_event
(eb->
write_lock_wq
,
229
atomic_read
(&eb->
blocking_writers
) == 0);
230
goto
again;
231
}
232
WARN_ON
(
atomic_read
(&eb->
spinning_writers
));
233
atomic_inc
(&eb->
spinning_writers
);
234
atomic_inc
(&eb->
write_locks
);
235
eb->
lock_owner
=
current
->pid;
236
}
237
238
/*
239
* drop a spinning or a blocking write lock.
240
*/
241
void
btrfs_tree_unlock
(
struct
extent_buffer
*
eb
)
242
{
243
int
blockers =
atomic_read
(&eb->
blocking_writers
);
244
245
BUG_ON
(blockers > 1);
246
247
btrfs_assert_tree_locked
(eb);
248
atomic_dec
(&eb->
write_locks
);
249
250
if
(blockers) {
251
WARN_ON
(
atomic_read
(&eb->
spinning_writers
));
252
atomic_dec
(&eb->
blocking_writers
);
253
smp_mb
();
254
if
(waitqueue_active(&eb->
write_lock_wq
))
255
wake_up
(&eb->
write_lock_wq
);
256
}
else
{
257
WARN_ON
(
atomic_read
(&eb->
spinning_writers
) != 1);
258
atomic_dec
(&eb->
spinning_writers
);
259
write_unlock
(&eb->
lock
);
260
}
261
}
262
263
void
btrfs_assert_tree_locked
(
struct
extent_buffer
*
eb
)
264
{
265
BUG_ON
(!
atomic_read
(&eb->
write_locks
));
266
}
267
268
void
btrfs_assert_tree_read_locked
(
struct
extent_buffer
*
eb
)
269
{
270
BUG_ON
(!
atomic_read
(&eb->
read_locks
));
271
}
Generated on Thu Jan 10 2013 14:45:34 for Linux Kernel by
1.8.2