Blame view
fs/gfs2/glock.c
45.6 KB
b3b94faa5 [GFS2] The core o... |
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
cf45b752c [GFS2] Remove rgr... |
3 |
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09 [GFS2] Update cop... |
7 |
* of the GNU General Public License version 2. |
b3b94faa5 [GFS2] The core o... |
8 9 10 11 12 |
*/ #include <linux/sched.h> #include <linux/slab.h> #include <linux/spinlock.h> |
b3b94faa5 [GFS2] The core o... |
13 14 15 16 |
#include <linux/buffer_head.h> #include <linux/delay.h> #include <linux/sort.h> #include <linux/jhash.h> |
d0dc80dba [GFS2] Update deb... |
17 |
#include <linux/kallsyms.h> |
5c676f6d3 [GFS2] Macros rem... |
18 |
#include <linux/gfs2_ondisk.h> |
242644346 [GFS2] Rewrite of... |
19 |
#include <linux/list.h> |
fee852e37 [GFS2] Shrink gfs... |
20 |
#include <linux/wait.h> |
95d97b7dd [GFS2] build fix |
21 |
#include <linux/module.h> |
b3b94faa5 [GFS2] The core o... |
22 |
#include <asm/uaccess.h> |
7c52b166c [GFS2] Add gfs2_t... |
23 24 |
#include <linux/seq_file.h> #include <linux/debugfs.h> |
8fbbfd214 [GFS2] Reduce num... |
25 26 |
#include <linux/kthread.h> #include <linux/freezer.h> |
c4f68a130 [GFS2] delay gloc... |
27 28 |
#include <linux/workqueue.h> #include <linux/jiffies.h> |
bc015cb84 GFS2: Use RCU for... |
29 30 31 |
#include <linux/rcupdate.h> #include <linux/rculist_bl.h> #include <linux/bit_spinlock.h> |
b3b94faa5 [GFS2] The core o... |
32 33 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
34 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
35 36 37 |
#include "glock.h" #include "glops.h" #include "inode.h" |
b3b94faa5 [GFS2] The core o... |
38 39 40 41 |
#include "lops.h" #include "meta_io.h" #include "quota.h" #include "super.h" |
5c676f6d3 [GFS2] Macros rem... |
42 |
#include "util.h" |
813e0c46c GFS2: Fix "trunca... |
43 |
#include "bmap.h" |
63997775b GFS2: Add tracepo... |
44 45 |
#define CREATE_TRACE_POINTS #include "trace_gfs2.h" |
b3b94faa5 [GFS2] The core o... |
46 |
|
6802e3400 [GFS2] Clean up t... |
47 48 49 50 51 |
struct gfs2_glock_iter { int hash; /* hash bucket index */ struct gfs2_sbd *sdp; /* incore superblock */ struct gfs2_glock *gl; /* current glock struct */ char string[512]; /* scratch space */ |
7c52b166c [GFS2] Add gfs2_t... |
52 |
}; |
b3b94faa5 [GFS2] The core o... |
53 |
typedef void (*glock_examiner) (struct gfs2_glock * gl); |
6802e3400 [GFS2] Clean up t... |
54 55 56 |
static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl); #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); |
c4f68a130 [GFS2] delay gloc... |
57 |
|
7c52b166c [GFS2] Add gfs2_t... |
58 |
static struct dentry *gfs2_root; |
c4f68a130 [GFS2] delay gloc... |
59 |
static struct workqueue_struct *glock_workqueue; |
b94a170e9 GFS2: remove dcac... |
60 |
struct workqueue_struct *gfs2_delete_workqueue; |
97cc1025b GFS2: Kill two da... |
61 62 |
static LIST_HEAD(lru_list); static atomic_t lru_count = ATOMIC_INIT(0); |
eb8374e71 GFS2: Use DEFINE_... |
63 |
static DEFINE_SPINLOCK(lru_lock); |
08bc2dbc7 [GFS2] [-mm patch... |
64 |
|
b6397893a [GFS2] Use hlist ... |
65 |
#define GFS2_GL_HASH_SHIFT 15 |
087efdd39 [GFS2] Make glock... |
66 67 |
#define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) #define GFS2_GL_HASH_MASK (GFS2_GL_HASH_SIZE - 1) |
bc015cb84 GFS2: Use RCU for... |
68 |
static struct hlist_bl_head gl_hash_table[GFS2_GL_HASH_SIZE]; |
04b933f27 [GFS2] Red Hat bz... |
69 |
static struct dentry *gfs2_root; |
087efdd39 [GFS2] Make glock... |
70 |
|
b3b94faa5 [GFS2] The core o... |
71 |
/** |
b3b94faa5 [GFS2] The core o... |
72 73 74 75 76 |
* gl_hash() - Turn glock number into hash bucket number * @lock: The glock number * * Returns: The number of the corresponding hash bucket */ |
b8547856f [GFS2] Add gfs2 s... |
77 78 |
static unsigned int gl_hash(const struct gfs2_sbd *sdp, const struct lm_lockname *name) |
b3b94faa5 [GFS2] The core o... |
79 80 |
{ unsigned int h; |
cd915493f [GFS2] Change all... |
81 |
h = jhash(&name->ln_number, sizeof(u64), 0); |
b3b94faa5 [GFS2] The core o... |
82 |
h = jhash(&name->ln_type, sizeof(unsigned int), h); |
b8547856f [GFS2] Add gfs2 s... |
83 |
h = jhash(&sdp, sizeof(struct gfs2_sbd *), h); |
b3b94faa5 [GFS2] The core o... |
84 85 86 87 |
h &= GFS2_GL_HASH_MASK; return h; } |
bc015cb84 GFS2: Use RCU for... |
88 89 |
static inline void spin_lock_bucket(unsigned int hash) { |
1879fd6a2 add hlist_bl_lock... |
90 |
hlist_bl_lock(&gl_hash_table[hash]); |
bc015cb84 GFS2: Use RCU for... |
91 |
} |
b3b94faa5 [GFS2] The core o... |
92 |
|
bc015cb84 GFS2: Use RCU for... |
93 94 |
static inline void spin_unlock_bucket(unsigned int hash) { |
1879fd6a2 add hlist_bl_lock... |
95 |
hlist_bl_unlock(&gl_hash_table[hash]); |
bc015cb84 GFS2: Use RCU for... |
96 |
} |
b3b94faa5 [GFS2] The core o... |
97 |
|
fc0e38dae GFS2: Fix glock d... |
98 |
static void gfs2_glock_dealloc(struct rcu_head *rcu) |
b3b94faa5 [GFS2] The core o... |
99 |
{ |
bc015cb84 GFS2: Use RCU for... |
100 |
struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu); |
b3b94faa5 [GFS2] The core o... |
101 |
|
bc015cb84 GFS2: Use RCU for... |
102 103 104 105 |
if (gl->gl_ops->go_flags & GLOF_ASPACE) kmem_cache_free(gfs2_glock_aspace_cachep, gl); else kmem_cache_free(gfs2_glock_cachep, gl); |
fc0e38dae GFS2: Fix glock d... |
106 107 108 |
} void gfs2_glock_free(struct gfs2_glock *gl) |
b3b94faa5 [GFS2] The core o... |
109 110 |
{ struct gfs2_sbd *sdp = gl->gl_sbd; |
b3b94faa5 [GFS2] The core o... |
111 |
|
fc0e38dae GFS2: Fix glock d... |
112 |
call_rcu(&gl->gl_rcu, gfs2_glock_dealloc); |
bc015cb84 GFS2: Use RCU for... |
113 114 |
if (atomic_dec_and_test(&sdp->sd_glock_disposal)) wake_up(&sdp->sd_glock_wait); |
b3b94faa5 [GFS2] The core o... |
115 116 117 118 119 120 121 |
} /** * gfs2_glock_hold() - increment reference count on glock * @gl: The glock to hold * */ |
b94a170e9 GFS2: remove dcac... |
122 |
void gfs2_glock_hold(struct gfs2_glock *gl) |
b3b94faa5 [GFS2] The core o... |
123 |
{ |
d8348de06 GFS2: Fix deadloc... |
124 |
GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0); |
16feb9fec [GFS2] Use atomic... |
125 |
atomic_inc(&gl->gl_ref); |
b3b94faa5 [GFS2] The core o... |
126 127 128 |
} /** |
8ff22a6f9 GFS2: Don't put u... |
129 130 131 132 133 134 135 136 137 138 139 140 |
* demote_ok - Check to see if it's ok to unlock a glock * @gl: the glock * * Returns: 1 if it's ok */ static int demote_ok(const struct gfs2_glock *gl) { const struct gfs2_glock_operations *glops = gl->gl_ops; if (gl->gl_state == LM_ST_UNLOCKED) return 0; |
f42ab0852 GFS2: Optimise gl... |
141 |
if (!list_empty(&gl->gl_holders)) |
8ff22a6f9 GFS2: Don't put u... |
142 143 144 145 146 |
return 0; if (glops->go_demote_ok) return glops->go_demote_ok(gl); return 1; } |
bc015cb84 GFS2: Use RCU for... |
147 |
|
29687a2ac GFS2: Alter point... |
148 149 150 151 152 153 154 155 156 157 |
void gfs2_glock_add_to_lru(struct gfs2_glock *gl) { spin_lock(&lru_lock); if (!list_empty(&gl->gl_lru)) list_del_init(&gl->gl_lru); else atomic_inc(&lru_count); list_add_tail(&gl->gl_lru, &lru_list); |
627c10b7e GFS2: Improve tra... |
158 |
set_bit(GLF_LRU, &gl->gl_flags); |
29687a2ac GFS2: Alter point... |
159 160 |
spin_unlock(&lru_lock); } |
f42ab0852 GFS2: Optimise gl... |
161 162 163 164 165 166 167 168 169 170 |
static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl) { spin_lock(&lru_lock); if (!list_empty(&gl->gl_lru)) { list_del_init(&gl->gl_lru); atomic_dec(&lru_count); clear_bit(GLF_LRU, &gl->gl_flags); } spin_unlock(&lru_lock); } |
8ff22a6f9 GFS2: Don't put u... |
171 |
/** |
bc015cb84 GFS2: Use RCU for... |
172 |
* __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list |
97cc1025b GFS2: Kill two da... |
173 174 |
* @gl: the glock * |
bc015cb84 GFS2: Use RCU for... |
175 176 |
* If the glock is demotable, then we add it (or move it) to the end * of the glock LRU list. |
97cc1025b GFS2: Kill two da... |
177 |
*/ |
bc015cb84 GFS2: Use RCU for... |
178 |
static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) |
97cc1025b GFS2: Kill two da... |
179 |
{ |
29687a2ac GFS2: Alter point... |
180 181 |
if (demote_ok(gl)) gfs2_glock_add_to_lru(gl); |
97cc1025b GFS2: Kill two da... |
182 183 184 |
} /** |
8ff22a6f9 GFS2: Don't put u... |
185 186 187 188 189 190 |
* gfs2_glock_put_nolock() - Decrement reference count on glock * @gl: The glock to put * * This function should only be used if the caller has its own reference * to the glock, in addition to the one it is dropping. */ |
b94a170e9 GFS2: remove dcac... |
191 |
void gfs2_glock_put_nolock(struct gfs2_glock *gl) |
8ff22a6f9 GFS2: Don't put u... |
192 193 194 |
{ if (atomic_dec_and_test(&gl->gl_ref)) GLOCK_BUG_ON(gl, 1); |
8ff22a6f9 GFS2: Don't put u... |
195 196 197 |
} /** |
b3b94faa5 [GFS2] The core o... |
198 199 200 201 |
* gfs2_glock_put() - Decrement reference count on glock * @gl: The glock to put * */ |
bc015cb84 GFS2: Use RCU for... |
202 |
void gfs2_glock_put(struct gfs2_glock *gl) |
b3b94faa5 [GFS2] The core o... |
203 |
{ |
bc015cb84 GFS2: Use RCU for... |
204 205 |
struct gfs2_sbd *sdp = gl->gl_sbd; struct address_space *mapping = gfs2_glock2aspace(gl); |
b3b94faa5 [GFS2] The core o... |
206 |
|
bc015cb84 GFS2: Use RCU for... |
207 208 209 210 |
if (atomic_dec_and_test(&gl->gl_ref)) { spin_lock_bucket(gl->gl_hash); hlist_bl_del_rcu(&gl->gl_list); spin_unlock_bucket(gl->gl_hash); |
f42ab0852 GFS2: Optimise gl... |
211 |
gfs2_glock_remove_from_lru(gl); |
6802e3400 [GFS2] Clean up t... |
212 |
GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); |
bc015cb84 GFS2: Use RCU for... |
213 214 215 |
GLOCK_BUG_ON(gl, mapping && mapping->nrpages); trace_gfs2_glock_put(gl); sdp->sd_lockstruct.ls_ops->lm_put_lock(gl); |
b3b94faa5 [GFS2] The core o... |
216 |
} |
b3b94faa5 [GFS2] The core o... |
217 218 219 |
} /** |
b3b94faa5 [GFS2] The core o... |
220 221 222 223 224 225 |
* search_bucket() - Find struct gfs2_glock by lock number * @bucket: the bucket to search * @name: The lock name * * Returns: NULL, or the struct gfs2_glock with the requested number */ |
37b2fa6a2 [GFS2] Move rwloc... |
226 |
static struct gfs2_glock *search_bucket(unsigned int hash, |
899be4d3b [GFS2] Add superb... |
227 |
const struct gfs2_sbd *sdp, |
d6a537276 [GFS2] Use const ... |
228 |
const struct lm_lockname *name) |
b3b94faa5 [GFS2] The core o... |
229 230 |
{ struct gfs2_glock *gl; |
bc015cb84 GFS2: Use RCU for... |
231 |
struct hlist_bl_node *h; |
b3b94faa5 [GFS2] The core o... |
232 |
|
bc015cb84 GFS2: Use RCU for... |
233 |
hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) { |
b3b94faa5 [GFS2] The core o... |
234 235 |
if (!lm_name_equal(&gl->gl_name, name)) continue; |
899be4d3b [GFS2] Add superb... |
236 237 |
if (gl->gl_sbd != sdp) continue; |
bc015cb84 GFS2: Use RCU for... |
238 239 |
if (atomic_inc_not_zero(&gl->gl_ref)) return gl; |
b3b94faa5 [GFS2] The core o... |
240 241 242 243 244 245 |
} return NULL; } /** |
6802e3400 [GFS2] Clean up t... |
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
* may_grant - check if its ok to grant a new lock * @gl: The glock * @gh: The lock request which we wish to grant * * Returns: true if its ok to grant the lock */ static inline int may_grant(const struct gfs2_glock *gl, const struct gfs2_holder *gh) { const struct gfs2_holder *gh_head = list_entry(gl->gl_holders.next, const struct gfs2_holder, gh_list); if ((gh->gh_state == LM_ST_EXCLUSIVE || gh_head->gh_state == LM_ST_EXCLUSIVE) && gh != gh_head) return 0; if (gl->gl_state == gh->gh_state) return 1; if (gh->gh_flags & GL_EXACT) return 0; |
209806aba [GFS2] Allow loca... |
263 264 265 266 267 268 |
if (gl->gl_state == LM_ST_EXCLUSIVE) { if (gh->gh_state == LM_ST_SHARED && gh_head->gh_state == LM_ST_SHARED) return 1; if (gh->gh_state == LM_ST_DEFERRED && gh_head->gh_state == LM_ST_DEFERRED) return 1; } |
6802e3400 [GFS2] Clean up t... |
269 270 271 272 273 274 275 276 277 278 279 280 281 |
if (gl->gl_state != LM_ST_UNLOCKED && (gh->gh_flags & LM_FLAG_ANY)) return 1; return 0; } static void gfs2_holder_wake(struct gfs2_holder *gh) { clear_bit(HIF_WAIT, &gh->gh_iflags); smp_mb__after_clear_bit(); wake_up_bit(&gh->gh_iflags, HIF_WAIT); } /** |
d5341a924 GFS2: Make "try" ... |
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
* do_error - Something unexpected has happened during a lock request * */ static inline void do_error(struct gfs2_glock *gl, const int ret) { struct gfs2_holder *gh, *tmp; list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { if (test_bit(HIF_HOLDER, &gh->gh_iflags)) continue; if (ret & LM_OUT_ERROR) gh->gh_error = -EIO; else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) gh->gh_error = GLR_TRYFAILED; else continue; list_del_init(&gh->gh_list); trace_gfs2_glock_queue(gh, 0); gfs2_holder_wake(gh); } } /** |
6802e3400 [GFS2] Clean up t... |
306 307 308 |
* do_promote - promote as many requests as possible on the current queue * @gl: The glock * |
813e0c46c GFS2: Fix "trunca... |
309 310 |
* Returns: 1 if there is a blocked holder at the head of the list, or 2 * if a type specific operation is underway. |
6802e3400 [GFS2] Clean up t... |
311 312 313 |
*/ static int do_promote(struct gfs2_glock *gl) |
55ba474da GFS2: sparse anno... |
314 315 |
__releases(&gl->gl_spin) __acquires(&gl->gl_spin) |
6802e3400 [GFS2] Clean up t... |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
{ const struct gfs2_glock_operations *glops = gl->gl_ops; struct gfs2_holder *gh, *tmp; int ret; restart: list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { if (test_bit(HIF_HOLDER, &gh->gh_iflags)) continue; if (may_grant(gl, gh)) { if (gh->gh_list.prev == &gl->gl_holders && glops->go_lock) { spin_unlock(&gl->gl_spin); /* FIXME: eliminate this eventually */ ret = glops->go_lock(gh); spin_lock(&gl->gl_spin); if (ret) { |
813e0c46c GFS2: Fix "trunca... |
333 334 |
if (ret == 1) return 2; |
6802e3400 [GFS2] Clean up t... |
335 336 |
gh->gh_error = ret; list_del_init(&gh->gh_list); |
63997775b GFS2: Add tracepo... |
337 |
trace_gfs2_glock_queue(gh, 0); |
6802e3400 [GFS2] Clean up t... |
338 339 340 341 |
gfs2_holder_wake(gh); goto restart; } set_bit(HIF_HOLDER, &gh->gh_iflags); |
63997775b GFS2: Add tracepo... |
342 |
trace_gfs2_promote(gh, 1); |
6802e3400 [GFS2] Clean up t... |
343 344 345 346 |
gfs2_holder_wake(gh); goto restart; } set_bit(HIF_HOLDER, &gh->gh_iflags); |
63997775b GFS2: Add tracepo... |
347 |
trace_gfs2_promote(gh, 0); |
6802e3400 [GFS2] Clean up t... |
348 349 350 351 352 |
gfs2_holder_wake(gh); continue; } if (gh->gh_list.prev == &gl->gl_holders) return 1; |
d5341a924 GFS2: Make "try" ... |
353 |
do_error(gl, 0); |
6802e3400 [GFS2] Clean up t... |
354 355 356 357 358 359 |
break; } return 0; } /** |
6802e3400 [GFS2] Clean up t... |
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
* find_first_waiter - find the first gh that's waiting for the glock * @gl: the glock */ static inline struct gfs2_holder *find_first_waiter(const struct gfs2_glock *gl) { struct gfs2_holder *gh; list_for_each_entry(gh, &gl->gl_holders, gh_list) { if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) return gh; } return NULL; } /** * state_change - record that the glock is now in a different state * @gl: the glock * @new_state the new state * */ static void state_change(struct gfs2_glock *gl, unsigned int new_state) { int held1, held2; held1 = (gl->gl_state != LM_ST_UNLOCKED); held2 = (new_state != LM_ST_UNLOCKED); if (held1 != held2) { if (held2) gfs2_glock_hold(gl); else |
8ff22a6f9 GFS2: Don't put u... |
393 |
gfs2_glock_put_nolock(gl); |
6802e3400 [GFS2] Clean up t... |
394 |
} |
7b5e3d5fc GFS2: Don't enfor... |
395 396 |
if (held1 && held2 && list_empty(&gl->gl_holders)) clear_bit(GLF_QUEUED, &gl->gl_flags); |
6802e3400 [GFS2] Clean up t... |
397 |
|
7cf8dcd3b GFS2: Automatical... |
398 399 400 401 |
if (new_state != gl->gl_target) /* shorten our minimum hold time */ gl->gl_hold_time = max(gl->gl_hold_time - GL_GLOCK_HOLD_DECR, GL_GLOCK_MIN_HOLD); |
6802e3400 [GFS2] Clean up t... |
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
gl->gl_state = new_state; gl->gl_tchange = jiffies; } static void gfs2_demote_wake(struct gfs2_glock *gl) { gl->gl_demote_state = LM_ST_EXCLUSIVE; clear_bit(GLF_DEMOTE, &gl->gl_flags); smp_mb__after_clear_bit(); wake_up_bit(&gl->gl_flags, GLF_DEMOTE); } /** * finish_xmote - The DLM has replied to one of our lock requests * @gl: The glock * @ret: The status from the DLM * */ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) { const struct gfs2_glock_operations *glops = gl->gl_ops; struct gfs2_holder *gh; unsigned state = ret & LM_OUT_ST_MASK; |
813e0c46c GFS2: Fix "trunca... |
426 |
int rv; |
6802e3400 [GFS2] Clean up t... |
427 428 |
spin_lock(&gl->gl_spin); |
63997775b GFS2: Add tracepo... |
429 |
trace_gfs2_glock_state_change(gl, state); |
6802e3400 [GFS2] Clean up t... |
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
state_change(gl, state); gh = find_first_waiter(gl); /* Demote to UN request arrived during demote to SH or DF */ if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags) && state != LM_ST_UNLOCKED && gl->gl_demote_state == LM_ST_UNLOCKED) gl->gl_target = LM_ST_UNLOCKED; /* Check for state != intended state */ if (unlikely(state != gl->gl_target)) { if (gh && !test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) { /* move to back of queue and try next entry */ if (ret & LM_OUT_CANCELED) { if ((gh->gh_flags & LM_FLAG_PRIORITY) == 0) list_move_tail(&gh->gh_list, &gl->gl_holders); gh = find_first_waiter(gl); gl->gl_target = gh->gh_state; goto retry; } /* Some error or failed "try lock" - report it */ if ((ret & LM_OUT_ERROR) || (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { gl->gl_target = gl->gl_state; do_error(gl, ret); goto out; } } switch(state) { /* Unlocked due to conversion deadlock, try again */ case LM_ST_UNLOCKED: retry: do_xmote(gl, gh, gl->gl_target); break; /* Conversion fails, unlock and try again */ case LM_ST_SHARED: case LM_ST_DEFERRED: do_xmote(gl, gh, LM_ST_UNLOCKED); break; default: /* Everything else */ printk(KERN_ERR "GFS2: wanted %u got %u ", gl->gl_target, state); GLOCK_BUG_ON(gl, 1); } spin_unlock(&gl->gl_spin); |
6802e3400 [GFS2] Clean up t... |
474 475 476 477 478 479 480 481 |
return; } /* Fast path - we got what we asked for */ if (test_and_clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) gfs2_demote_wake(gl); if (state != LM_ST_UNLOCKED) { if (glops->go_xmote_bh) { |
6802e3400 [GFS2] Clean up t... |
482 483 |
spin_unlock(&gl->gl_spin); rv = glops->go_xmote_bh(gl, gh); |
6802e3400 [GFS2] Clean up t... |
484 485 486 487 488 489 |
spin_lock(&gl->gl_spin); if (rv) { do_error(gl, rv); goto out; } } |
813e0c46c GFS2: Fix "trunca... |
490 491 492 |
rv = do_promote(gl); if (rv == 2) goto out_locked; |
6802e3400 [GFS2] Clean up t... |
493 494 495 |
} out: clear_bit(GLF_LOCK, &gl->gl_flags); |
813e0c46c GFS2: Fix "trunca... |
496 |
out_locked: |
6802e3400 [GFS2] Clean up t... |
497 |
spin_unlock(&gl->gl_spin); |
6802e3400 [GFS2] Clean up t... |
498 |
} |
6802e3400 [GFS2] Clean up t... |
499 500 501 502 503 504 505 506 507 |
/** * do_xmote - Calls the DLM to change the state of a lock * @gl: The lock state * @gh: The holder (only for promotes) * @target: The target lock state * */ static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target) |
55ba474da GFS2: sparse anno... |
508 509 |
__releases(&gl->gl_spin) __acquires(&gl->gl_spin) |
6802e3400 [GFS2] Clean up t... |
510 511 512 513 514 515 516 517 |
{ const struct gfs2_glock_operations *glops = gl->gl_ops; struct gfs2_sbd *sdp = gl->gl_sbd; unsigned int lck_flags = gh ? gh->gh_flags : 0; int ret; lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP | LM_FLAG_PRIORITY); |
921169ca2 GFS2: Clean up of... |
518 519 |
GLOCK_BUG_ON(gl, gl->gl_state == target); GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target); |
6802e3400 [GFS2] Clean up t... |
520 521 522 523 524 |
if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) && glops->go_inval) { set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); do_error(gl, 0); /* Fail queued try locks */ } |
47a25380e GFS2: Merge glock... |
525 |
gl->gl_req = target; |
6802e3400 [GFS2] Clean up t... |
526 527 528 529 530 531 532 533 |
spin_unlock(&gl->gl_spin); if (glops->go_xmote_th) glops->go_xmote_th(gl); if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA); clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); gfs2_glock_hold(gl); |
921169ca2 GFS2: Clean up of... |
534 535 536 537 538 539 |
if (sdp->sd_lockstruct.ls_ops->lm_lock) { /* lock_dlm */ ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); GLOCK_BUG_ON(gl, ret); } else { /* lock_nolock */ finish_xmote(gl, target); |
6802e3400 [GFS2] Clean up t... |
540 541 |
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); |
6802e3400 [GFS2] Clean up t... |
542 |
} |
921169ca2 GFS2: Clean up of... |
543 |
|
6802e3400 [GFS2] Clean up t... |
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
spin_lock(&gl->gl_spin); } /** * find_first_holder - find the first "holder" gh * @gl: the glock */ static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl) { struct gfs2_holder *gh; if (!list_empty(&gl->gl_holders)) { gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); if (test_bit(HIF_HOLDER, &gh->gh_iflags)) return gh; } return NULL; } /** * run_queue - do all outstanding tasks related to a glock * @gl: The glock in question * @nonblock: True if we must not block in run_queue * */ static void run_queue(struct gfs2_glock *gl, const int nonblock) |
55ba474da GFS2: sparse anno... |
572 573 |
__releases(&gl->gl_spin) __acquires(&gl->gl_spin) |
6802e3400 [GFS2] Clean up t... |
574 575 |
{ struct gfs2_holder *gh = NULL; |
813e0c46c GFS2: Fix "trunca... |
576 |
int ret; |
6802e3400 [GFS2] Clean up t... |
577 578 579 580 581 582 583 584 585 |
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) return; GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); if (test_bit(GLF_DEMOTE, &gl->gl_flags) && gl->gl_demote_state != gl->gl_state) { if (find_first_holder(gl)) |
d8348de06 GFS2: Fix deadloc... |
586 |
goto out_unlock; |
6802e3400 [GFS2] Clean up t... |
587 588 589 |
if (nonblock) goto out_sched; set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); |
265d529ce [GFS2] Fix delaye... |
590 |
GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE); |
6802e3400 [GFS2] Clean up t... |
591 592 593 594 |
gl->gl_target = gl->gl_demote_state; } else { if (test_bit(GLF_DEMOTE, &gl->gl_flags)) gfs2_demote_wake(gl); |
813e0c46c GFS2: Fix "trunca... |
595 596 |
ret = do_promote(gl); if (ret == 0) |
d8348de06 GFS2: Fix deadloc... |
597 |
goto out_unlock; |
813e0c46c GFS2: Fix "trunca... |
598 |
if (ret == 2) |
a228df633 GFS2: Move umount... |
599 |
goto out; |
6802e3400 [GFS2] Clean up t... |
600 601 602 603 604 605 |
gh = find_first_waiter(gl); gl->gl_target = gh->gh_state; if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) do_error(gl, 0); /* Fail queued try locks */ } do_xmote(gl, gh, gl->gl_target); |
a228df633 GFS2: Move umount... |
606 |
out: |
6802e3400 [GFS2] Clean up t... |
607 608 609 |
return; out_sched: |
7e71c55ee GFS2: Fix potenti... |
610 611 |
clear_bit(GLF_LOCK, &gl->gl_flags); smp_mb__after_clear_bit(); |
6802e3400 [GFS2] Clean up t... |
612 613 |
gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
8ff22a6f9 GFS2: Don't put u... |
614 |
gfs2_glock_put_nolock(gl); |
7e71c55ee GFS2: Fix potenti... |
615 |
return; |
d8348de06 GFS2: Fix deadloc... |
616 |
out_unlock: |
6802e3400 [GFS2] Clean up t... |
617 |
clear_bit(GLF_LOCK, &gl->gl_flags); |
7e71c55ee GFS2: Fix potenti... |
618 619 |
smp_mb__after_clear_bit(); return; |
6802e3400 [GFS2] Clean up t... |
620 |
} |
b94a170e9 GFS2: remove dcac... |
621 622 623 624 |
static void delete_work_func(struct work_struct *work) { struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete); struct gfs2_sbd *sdp = gl->gl_sbd; |
044b9414c GFS2: Fix inode d... |
625 |
struct gfs2_inode *ip; |
b94a170e9 GFS2: remove dcac... |
626 |
struct inode *inode; |
044b9414c GFS2: Fix inode d... |
627 628 629 630 |
u64 no_addr = gl->gl_name.ln_number; ip = gl->gl_object; /* Note: Unsafe to dereference ip as we don't hold right refs/locks */ |
b94a170e9 GFS2: remove dcac... |
631 |
|
b94a170e9 GFS2: remove dcac... |
632 |
if (ip) |
4667a0ec3 GFS2: Make writeb... |
633 |
inode = gfs2_ilookup(sdp->sd_vfs, no_addr, 1); |
044b9414c GFS2: Fix inode d... |
634 635 636 637 638 |
else inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED); if (inode && !IS_ERR(inode)) { d_prune_aliases(inode); iput(inode); |
b94a170e9 GFS2: remove dcac... |
639 640 641 |
} gfs2_glock_put(gl); } |
c4f68a130 [GFS2] delay gloc... |
642 643 |
static void glock_work_func(struct work_struct *work) { |
6802e3400 [GFS2] Clean up t... |
644 |
unsigned long delay = 0; |
c4f68a130 [GFS2] delay gloc... |
645 |
struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); |
26bb7505c GFS2: Fix glock r... |
646 |
int drop_ref = 0; |
c4f68a130 [GFS2] delay gloc... |
647 |
|
26bb7505c GFS2: Fix glock r... |
648 |
if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { |
6802e3400 [GFS2] Clean up t... |
649 |
finish_xmote(gl, gl->gl_reply); |
26bb7505c GFS2: Fix glock r... |
650 651 |
drop_ref = 1; } |
c4f68a130 [GFS2] delay gloc... |
652 |
spin_lock(&gl->gl_spin); |
f90e5b5b1 GFS2: Processes w... |
653 |
if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && |
265d529ce [GFS2] Fix delaye... |
654 655 |
gl->gl_state != LM_ST_UNLOCKED && gl->gl_demote_state != LM_ST_EXCLUSIVE) { |
6802e3400 [GFS2] Clean up t... |
656 |
unsigned long holdtime, now = jiffies; |
f90e5b5b1 GFS2: Processes w... |
657 |
|
7cf8dcd3b GFS2: Automatical... |
658 |
holdtime = gl->gl_tchange + gl->gl_hold_time; |
6802e3400 [GFS2] Clean up t... |
659 660 |
if (time_before(now, holdtime)) delay = holdtime - now; |
f90e5b5b1 GFS2: Processes w... |
661 662 663 664 665 |
if (!delay) { clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags); set_bit(GLF_DEMOTE, &gl->gl_flags); } |
6802e3400 [GFS2] Clean up t... |
666 667 |
} run_queue(gl, 0); |
c4f68a130 [GFS2] delay gloc... |
668 |
spin_unlock(&gl->gl_spin); |
7cf8dcd3b GFS2: Automatical... |
669 |
if (!delay) |
6802e3400 [GFS2] Clean up t... |
670 |
gfs2_glock_put(gl); |
7cf8dcd3b GFS2: Automatical... |
671 672 673 674 675 676 |
else { if (gl->gl_name.ln_type != LM_TYPE_INODE) delay = 0; if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) gfs2_glock_put(gl); } |
26bb7505c GFS2: Fix glock r... |
677 678 |
if (drop_ref) gfs2_glock_put(gl); |
c4f68a130 [GFS2] delay gloc... |
679 |
} |
b3b94faa5 [GFS2] The core o... |
680 681 682 683 684 685 686 687 688 689 690 691 |
/** * gfs2_glock_get() - Get a glock, or create one if one doesn't exist * @sdp: The GFS2 superblock * @number: the lock number * @glops: The glock_operations to use * @create: If 0, don't create the glock if it doesn't exist * @glp: the glock is returned here * * This does not lock a glock, just finds/creates structures for one. * * Returns: errno */ |
cd915493f [GFS2] Change all... |
692 |
int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, |
8fb4b536e [GFS2] Make glock... |
693 |
const struct gfs2_glock_operations *glops, int create, |
b3b94faa5 [GFS2] The core o... |
694 695 |
struct gfs2_glock **glp) { |
009d85183 GFS2: Metadata ad... |
696 |
struct super_block *s = sdp->sd_vfs; |
37b2fa6a2 [GFS2] Move rwloc... |
697 |
struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; |
b3b94faa5 [GFS2] The core o... |
698 |
struct gfs2_glock *gl, *tmp; |
37b2fa6a2 [GFS2] Move rwloc... |
699 |
unsigned int hash = gl_hash(sdp, &name); |
009d85183 GFS2: Metadata ad... |
700 |
struct address_space *mapping; |
bc015cb84 GFS2: Use RCU for... |
701 |
struct kmem_cache *cachep; |
b3b94faa5 [GFS2] The core o... |
702 |
|
bc015cb84 GFS2: Use RCU for... |
703 |
rcu_read_lock(); |
37b2fa6a2 [GFS2] Move rwloc... |
704 |
gl = search_bucket(hash, sdp, &name); |
bc015cb84 GFS2: Use RCU for... |
705 |
rcu_read_unlock(); |
b3b94faa5 [GFS2] The core o... |
706 |
|
64d576ba2 GFS2: Add a "demo... |
707 708 |
*glp = gl; if (gl) |
b3b94faa5 [GFS2] The core o... |
709 |
return 0; |
64d576ba2 GFS2: Add a "demo... |
710 711 |
if (!create) return -ENOENT; |
b3b94faa5 [GFS2] The core o... |
712 |
|
009d85183 GFS2: Metadata ad... |
713 |
if (glops->go_flags & GLOF_ASPACE) |
bc015cb84 GFS2: Use RCU for... |
714 |
cachep = gfs2_glock_aspace_cachep; |
009d85183 GFS2: Metadata ad... |
715 |
else |
bc015cb84 GFS2: Use RCU for... |
716 717 |
cachep = gfs2_glock_cachep; gl = kmem_cache_alloc(cachep, GFP_KERNEL); |
b3b94faa5 [GFS2] The core o... |
718 719 |
if (!gl) return -ENOMEM; |
8f05228ee GFS2: Extend umou... |
720 |
atomic_inc(&sdp->sd_glock_disposal); |
ec45d9f58 [GFS2] Use slab p... |
721 |
gl->gl_flags = 0; |
b3b94faa5 [GFS2] The core o... |
722 |
gl->gl_name = name; |
16feb9fec [GFS2] Use atomic... |
723 |
atomic_set(&gl->gl_ref, 1); |
b3b94faa5 [GFS2] The core o... |
724 |
gl->gl_state = LM_ST_UNLOCKED; |
6802e3400 [GFS2] Clean up t... |
725 |
gl->gl_target = LM_ST_UNLOCKED; |
c4f68a130 [GFS2] delay gloc... |
726 |
gl->gl_demote_state = LM_ST_EXCLUSIVE; |
37b2fa6a2 [GFS2] Move rwloc... |
727 |
gl->gl_hash = hash; |
b3b94faa5 [GFS2] The core o... |
728 |
gl->gl_ops = glops; |
f057f6cdf GFS2: Merge lock_... |
729 730 731 |
snprintf(gl->gl_strname, GDLM_STRNAME_BYTES, "%8x%16llx", name.ln_type, (unsigned long long)number); memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb)); gl->gl_lksb.sb_lvbptr = gl->gl_lvb; |
c4f68a130 [GFS2] delay gloc... |
732 |
gl->gl_tchange = jiffies; |
ec45d9f58 [GFS2] Use slab p... |
733 |
gl->gl_object = NULL; |
b3b94faa5 [GFS2] The core o... |
734 |
gl->gl_sbd = sdp; |
7cf8dcd3b GFS2: Automatical... |
735 |
gl->gl_hold_time = GL_GLOCK_DFT_HOLD; |
c4f68a130 [GFS2] delay gloc... |
736 |
INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); |
b94a170e9 GFS2: remove dcac... |
737 |
INIT_WORK(&gl->gl_delete, delete_work_func); |
b3b94faa5 [GFS2] The core o... |
738 |
|
009d85183 GFS2: Metadata ad... |
739 740 741 742 743 744 745 746 747 |
mapping = gfs2_glock2aspace(gl); if (mapping) { mapping->a_ops = &gfs2_meta_aops; mapping->host = s->s_bdev->bd_inode; mapping->flags = 0; mapping_set_gfp_mask(mapping, GFP_NOFS); mapping->assoc_mapping = NULL; mapping->backing_dev_info = s->s_bdi; mapping->writeback_index = 0; |
b3b94faa5 [GFS2] The core o... |
748 |
} |
bc015cb84 GFS2: Use RCU for... |
749 |
spin_lock_bucket(hash); |
37b2fa6a2 [GFS2] Move rwloc... |
750 |
tmp = search_bucket(hash, sdp, &name); |
b3b94faa5 [GFS2] The core o... |
751 |
if (tmp) { |
bc015cb84 GFS2: Use RCU for... |
752 753 |
spin_unlock_bucket(hash); kmem_cache_free(cachep, gl); |
fc0e38dae GFS2: Fix glock d... |
754 |
atomic_dec(&sdp->sd_glock_disposal); |
b3b94faa5 [GFS2] The core o... |
755 756 |
gl = tmp; } else { |
bc015cb84 GFS2: Use RCU for... |
757 758 |
hlist_bl_add_head_rcu(&gl->gl_list, &gl_hash_table[hash]); spin_unlock_bucket(hash); |
b3b94faa5 [GFS2] The core o... |
759 760 761 762 763 |
} *glp = gl; return 0; |
b3b94faa5 [GFS2] The core o... |
764 765 766 767 768 769 770 771 772 773 |
} /** * gfs2_holder_init - initialize a struct gfs2_holder in the default way * @gl: the glock * @state: the state we're requesting * @flags: the modifier flags * @gh: the holder structure * */ |
190562bd8 [GFS2] Fix a bug:... |
774 |
void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, |
b3b94faa5 [GFS2] The core o... |
775 776 777 778 |
struct gfs2_holder *gh) { INIT_LIST_HEAD(&gh->gh_list); gh->gh_gl = gl; |
d0dc80dba [GFS2] Update deb... |
779 |
gh->gh_ip = (unsigned long)__builtin_return_address(0); |
b1e058da5 gfs2: make gfs2_h... |
780 |
gh->gh_owner_pid = get_pid(task_pid(current)); |
b3b94faa5 [GFS2] The core o... |
781 782 783 784 |
gh->gh_state = state; gh->gh_flags = flags; gh->gh_error = 0; gh->gh_iflags = 0; |
b3b94faa5 [GFS2] The core o... |
785 786 787 788 789 790 791 792 793 794 795 796 |
gfs2_glock_hold(gl); } /** * gfs2_holder_reinit - reinitialize a struct gfs2_holder so we can requeue it * @state: the state we're requesting * @flags: the modifier flags * @gh: the holder structure * * Don't mess with the glock. * */ |
190562bd8 [GFS2] Fix a bug:... |
797 |
void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *gh) |
b3b94faa5 [GFS2] The core o... |
798 799 |
{ gh->gh_state = state; |
579b78a43 [GFS2] Remove GL_... |
800 |
gh->gh_flags = flags; |
3b8249f61 [GFS2] Fix bz 224... |
801 |
gh->gh_iflags = 0; |
d0dc80dba [GFS2] Update deb... |
802 |
gh->gh_ip = (unsigned long)__builtin_return_address(0); |
1a0eae884 GFS2: glock livelock |
803 804 805 |
if (gh->gh_owner_pid) put_pid(gh->gh_owner_pid); gh->gh_owner_pid = get_pid(task_pid(current)); |
b3b94faa5 [GFS2] The core o... |
806 807 808 809 810 811 812 813 814 815 |
} /** * gfs2_holder_uninit - uninitialize a holder structure (drop glock reference) * @gh: the holder structure * */ void gfs2_holder_uninit(struct gfs2_holder *gh) { |
b1e058da5 gfs2: make gfs2_h... |
816 |
put_pid(gh->gh_owner_pid); |
b3b94faa5 [GFS2] The core o... |
817 818 |
gfs2_glock_put(gh->gh_gl); gh->gh_gl = NULL; |
d0dc80dba [GFS2] Update deb... |
819 |
gh->gh_ip = 0; |
b3b94faa5 [GFS2] The core o... |
820 |
} |
fe64d517d GFS2: Umount reco... |
821 822 823 824 825 826 827 828 829 830 |
/** * gfs2_glock_holder_wait * @word: unused * * This function and gfs2_glock_demote_wait both show up in the WCHAN * field. Thus I've separated these otherwise identical functions in * order to be more informative to the user. */ static int gfs2_glock_holder_wait(void *word) |
fee852e37 [GFS2] Shrink gfs... |
831 832 833 834 |
{ schedule(); return 0; } |
fe64d517d GFS2: Umount reco... |
835 836 837 838 839 |
static int gfs2_glock_demote_wait(void *word) { schedule(); return 0; } |
6802e3400 [GFS2] Clean up t... |
840 |
static void wait_on_holder(struct gfs2_holder *gh) |
da755fdb4 [GFS2] Remove lm.... |
841 |
{ |
7cf8dcd3b GFS2: Automatical... |
842 |
unsigned long time1 = jiffies; |
6802e3400 [GFS2] Clean up t... |
843 |
might_sleep(); |
fe64d517d GFS2: Umount reco... |
844 |
wait_on_bit(&gh->gh_iflags, HIF_WAIT, gfs2_glock_holder_wait, TASK_UNINTERRUPTIBLE); |
7cf8dcd3b GFS2: Automatical... |
845 846 847 848 849 |
if (time_after(jiffies, time1 + HZ)) /* have we waited > a second? */ /* Lengthen the minimum hold time. */ gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time + GL_GLOCK_HOLD_INCR, GL_GLOCK_MAX_HOLD); |
da755fdb4 [GFS2] Remove lm.... |
850 |
} |
6802e3400 [GFS2] Clean up t... |
851 |
static void wait_on_demote(struct gfs2_glock *gl) |
b3b94faa5 [GFS2] The core o... |
852 |
{ |
6802e3400 [GFS2] Clean up t... |
853 |
might_sleep(); |
fe64d517d GFS2: Umount reco... |
854 |
wait_on_bit(&gl->gl_flags, GLF_DEMOTE, gfs2_glock_demote_wait, TASK_UNINTERRUPTIBLE); |
b3b94faa5 [GFS2] The core o... |
855 856 857 |
} /** |
6802e3400 [GFS2] Clean up t... |
858 859 860 |
* handle_callback - process a demote request * @gl: the glock * @state: the state the caller wants us to change to |
b3b94faa5 [GFS2] The core o... |
861 |
* |
6802e3400 [GFS2] Clean up t... |
862 863 |
* There are only two requests that we are going to see in actual * practise: LM_ST_SHARED and LM_ST_UNLOCKED |
b3b94faa5 [GFS2] The core o... |
864 |
*/ |
6802e3400 [GFS2] Clean up t... |
865 |
static void handle_callback(struct gfs2_glock *gl, unsigned int state, |
97cc1025b GFS2: Kill two da... |
866 |
unsigned long delay) |
b3b94faa5 [GFS2] The core o... |
867 |
{ |
6802e3400 [GFS2] Clean up t... |
868 |
int bit = delay ? GLF_PENDING_DEMOTE : GLF_DEMOTE; |
b3b94faa5 [GFS2] The core o... |
869 |
|
6802e3400 [GFS2] Clean up t... |
870 871 872 873 |
set_bit(bit, &gl->gl_flags); if (gl->gl_demote_state == LM_ST_EXCLUSIVE) { gl->gl_demote_state = state; gl->gl_demote_time = jiffies; |
6802e3400 [GFS2] Clean up t... |
874 875 876 |
} else if (gl->gl_demote_state != LM_ST_UNLOCKED && gl->gl_demote_state != state) { gl->gl_demote_state = LM_ST_UNLOCKED; |
b3b94faa5 [GFS2] The core o... |
877 |
} |
b94a170e9 GFS2: remove dcac... |
878 879 |
if (gl->gl_ops->go_callback) gl->gl_ops->go_callback(gl); |
63997775b GFS2: Add tracepo... |
880 |
trace_gfs2_demote_rq(gl); |
b3b94faa5 [GFS2] The core o... |
881 882 883 |
} /** |
6802e3400 [GFS2] Clean up t... |
884 |
* gfs2_glock_wait - wait on a glock acquisition |
b3b94faa5 [GFS2] The core o... |
885 886 887 888 |
* @gh: the glock holder * * Returns: 0 on success */ |
6802e3400 [GFS2] Clean up t... |
889 |
int gfs2_glock_wait(struct gfs2_holder *gh) |
b3b94faa5 [GFS2] The core o... |
890 |
{ |
fee852e37 [GFS2] Shrink gfs... |
891 |
wait_on_holder(gh); |
b3b94faa5 [GFS2] The core o... |
892 893 |
return gh->gh_error; } |
6802e3400 [GFS2] Clean up t... |
894 |
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) |
7c52b166c [GFS2] Add gfs2_t... |
895 |
{ |
5e69069c1 GFS2: fs/gfs2/glo... |
896 |
struct va_format vaf; |
7c52b166c [GFS2] Add gfs2_t... |
897 898 899 |
va_list args; va_start(args, fmt); |
5e69069c1 GFS2: fs/gfs2/glo... |
900 |
|
6802e3400 [GFS2] Clean up t... |
901 902 |
if (seq) { struct gfs2_glock_iter *gi = seq->private; |
7c52b166c [GFS2] Add gfs2_t... |
903 |
vsprintf(gi->string, fmt, args); |
6802e3400 [GFS2] Clean up t... |
904 905 |
seq_printf(seq, gi->string); } else { |
5e69069c1 GFS2: fs/gfs2/glo... |
906 907 908 909 |
vaf.fmt = fmt; vaf.va = &args; printk(KERN_ERR " %pV", &vaf); |
6802e3400 [GFS2] Clean up t... |
910 |
} |
5e69069c1 GFS2: fs/gfs2/glo... |
911 |
|
7c52b166c [GFS2] Add gfs2_t... |
912 913 |
va_end(args); } |
b3b94faa5 [GFS2] The core o... |
914 |
/** |
b3b94faa5 [GFS2] The core o... |
915 916 917 |
* add_to_queue - Add a holder to the wait queue (but look for recursion) * @gh: the holder structure to add * |
6802e3400 [GFS2] Clean up t... |
918 919 920 921 |
* Eventually we should move the recursive locking trap to a * debugging option or something like that. This is the fast * path and needs to have the minimum number of distractions. * |
b3b94faa5 [GFS2] The core o... |
922 |
*/ |
6802e3400 [GFS2] Clean up t... |
923 |
static inline void add_to_queue(struct gfs2_holder *gh) |
55ba474da GFS2: sparse anno... |
924 925 |
__releases(&gl->gl_spin) __acquires(&gl->gl_spin) |
b3b94faa5 [GFS2] The core o... |
926 927 |
{ struct gfs2_glock *gl = gh->gh_gl; |
6802e3400 [GFS2] Clean up t... |
928 929 930 931 |
struct gfs2_sbd *sdp = gl->gl_sbd; struct list_head *insert_pt = NULL; struct gfs2_holder *gh2; int try_lock = 0; |
b3b94faa5 [GFS2] The core o... |
932 |
|
b1e058da5 gfs2: make gfs2_h... |
933 |
BUG_ON(gh->gh_owner_pid == NULL); |
fee852e37 [GFS2] Shrink gfs... |
934 935 |
if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) BUG(); |
190562bd8 [GFS2] Fix a bug:... |
936 |
|
6802e3400 [GFS2] Clean up t... |
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 |
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { if (test_bit(GLF_LOCK, &gl->gl_flags)) try_lock = 1; if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) goto fail; } list_for_each_entry(gh2, &gl->gl_holders, gh_list) { if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid && (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK))) goto trap_recursive; if (try_lock && !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) && !may_grant(gl, gh)) { fail: gh->gh_error = GLR_TRYFAILED; gfs2_holder_wake(gh); return; |
b4c20166d [GFS2] flocks fro... |
955 |
} |
6802e3400 [GFS2] Clean up t... |
956 957 958 959 960 |
if (test_bit(HIF_HOLDER, &gh2->gh_iflags)) continue; if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt)) insert_pt = &gh2->gh_list; } |
7b5e3d5fc GFS2: Don't enfor... |
961 |
set_bit(GLF_QUEUED, &gl->gl_flags); |
edae38a64 GFS2: Fix glock q... |
962 |
trace_gfs2_glock_queue(gh, 1); |
6802e3400 [GFS2] Clean up t... |
963 964 965 966 967 968 969 970 971 972 973 |
if (likely(insert_pt == NULL)) { list_add_tail(&gh->gh_list, &gl->gl_holders); if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY)) goto do_cancel; return; } list_add_tail(&gh->gh_list, insert_pt); do_cancel: gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); if (!(gh->gh_flags & LM_FLAG_PRIORITY)) { spin_unlock(&gl->gl_spin); |
048bca223 [GFS2] No lock_no... |
974 |
if (sdp->sd_lockstruct.ls_ops->lm_cancel) |
f057f6cdf GFS2: Merge lock_... |
975 |
sdp->sd_lockstruct.ls_ops->lm_cancel(gl); |
6802e3400 [GFS2] Clean up t... |
976 |
spin_lock(&gl->gl_spin); |
b3b94faa5 [GFS2] The core o... |
977 |
} |
6802e3400 [GFS2] Clean up t... |
978 |
return; |
b3b94faa5 [GFS2] The core o... |
979 |
|
6802e3400 [GFS2] Clean up t... |
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 |
trap_recursive: print_symbol(KERN_ERR "original: %s ", gh2->gh_ip); printk(KERN_ERR "pid: %d ", pid_nr(gh2->gh_owner_pid)); printk(KERN_ERR "lock type: %d req lock state : %d ", gh2->gh_gl->gl_name.ln_type, gh2->gh_state); print_symbol(KERN_ERR "new: %s ", gh->gh_ip); printk(KERN_ERR "pid: %d ", pid_nr(gh->gh_owner_pid)); printk(KERN_ERR "lock type: %d req lock state : %d ", gh->gh_gl->gl_name.ln_type, gh->gh_state); __dump_glock(NULL, gl); BUG(); |
b3b94faa5 [GFS2] The core o... |
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 |
} /** * gfs2_glock_nq - enqueue a struct gfs2_holder onto a glock (acquire a glock) * @gh: the holder structure * * if (gh->gh_flags & GL_ASYNC), this never returns an error * * Returns: 0, GLR_TRYFAILED, or errno on failure */ int gfs2_glock_nq(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; struct gfs2_sbd *sdp = gl->gl_sbd; int error = 0; |
6802e3400 [GFS2] Clean up t... |
1013 |
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
b3b94faa5 [GFS2] The core o... |
1014 |
return -EIO; |
b3b94faa5 [GFS2] The core o... |
1015 |
|
f42ab0852 GFS2: Optimise gl... |
1016 1017 |
if (test_bit(GLF_LRU, &gl->gl_flags)) gfs2_glock_remove_from_lru(gl); |
b3b94faa5 [GFS2] The core o... |
1018 1019 |
spin_lock(&gl->gl_spin); add_to_queue(gh); |
0809f6ec1 GFS2: Fix recover... |
1020 1021 1022 |
if ((LM_FLAG_NOEXP & gh->gh_flags) && test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) set_bit(GLF_REPLY_PENDING, &gl->gl_flags); |
6802e3400 [GFS2] Clean up t... |
1023 |
run_queue(gl, 1); |
b3b94faa5 [GFS2] The core o... |
1024 |
spin_unlock(&gl->gl_spin); |
6802e3400 [GFS2] Clean up t... |
1025 1026 |
if (!(gh->gh_flags & GL_ASYNC)) error = gfs2_glock_wait(gh); |
b3b94faa5 [GFS2] The core o... |
1027 |
|
b3b94faa5 [GFS2] The core o... |
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 |
return error; } /** * gfs2_glock_poll - poll to see if an async request has been completed * @gh: the holder * * Returns: 1 if the request is ready to be gfs2_glock_wait()ed on */ int gfs2_glock_poll(struct gfs2_holder *gh) { |
6802e3400 [GFS2] Clean up t... |
1040 |
return test_bit(HIF_WAIT, &gh->gh_iflags) ? 0 : 1; |
b3b94faa5 [GFS2] The core o... |
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 |
} /** * gfs2_glock_dq - dequeue a struct gfs2_holder from a glock (release a glock) * @gh: the glock holder * */ void gfs2_glock_dq(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; |
8fb4b536e [GFS2] Make glock... |
1052 |
const struct gfs2_glock_operations *glops = gl->gl_ops; |
c4f68a130 [GFS2] delay gloc... |
1053 |
unsigned delay = 0; |
6802e3400 [GFS2] Clean up t... |
1054 |
int fast_path = 0; |
b3b94faa5 [GFS2] The core o... |
1055 |
|
6802e3400 [GFS2] Clean up t... |
1056 |
spin_lock(&gl->gl_spin); |
b3b94faa5 [GFS2] The core o... |
1057 |
if (gh->gh_flags & GL_NOCACHE) |
97cc1025b GFS2: Kill two da... |
1058 |
handle_callback(gl, LM_ST_UNLOCKED, 0); |
b3b94faa5 [GFS2] The core o... |
1059 |
|
b3b94faa5 [GFS2] The core o... |
1060 |
list_del_init(&gh->gh_list); |
6802e3400 [GFS2] Clean up t... |
1061 |
if (find_first_holder(gl) == NULL) { |
3042a2ccd [GFS2] Reorder wr... |
1062 |
if (glops->go_unlock) { |
6802e3400 [GFS2] Clean up t... |
1063 |
GLOCK_BUG_ON(gl, test_and_set_bit(GLF_LOCK, &gl->gl_flags)); |
3042a2ccd [GFS2] Reorder wr... |
1064 |
spin_unlock(&gl->gl_spin); |
b3b94faa5 [GFS2] The core o... |
1065 |
glops->go_unlock(gh); |
3042a2ccd [GFS2] Reorder wr... |
1066 |
spin_lock(&gl->gl_spin); |
6802e3400 [GFS2] Clean up t... |
1067 |
clear_bit(GLF_LOCK, &gl->gl_flags); |
3042a2ccd [GFS2] Reorder wr... |
1068 |
} |
6802e3400 [GFS2] Clean up t... |
1069 1070 1071 1072 |
if (list_empty(&gl->gl_holders) && !test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && !test_bit(GLF_DEMOTE, &gl->gl_flags)) fast_path = 1; |
b3b94faa5 [GFS2] The core o... |
1073 |
} |
f42ab0852 GFS2: Optimise gl... |
1074 1075 |
if (!test_bit(GLF_LFLUSH, &gl->gl_flags)) __gfs2_glock_schedule_for_reclaim(gl); |
63997775b GFS2: Add tracepo... |
1076 |
trace_gfs2_glock_queue(gh, 0); |
b3b94faa5 [GFS2] The core o... |
1077 |
spin_unlock(&gl->gl_spin); |
6802e3400 [GFS2] Clean up t... |
1078 1079 |
if (likely(fast_path)) return; |
c4f68a130 [GFS2] delay gloc... |
1080 1081 1082 |
gfs2_glock_hold(gl); if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && |
7cf8dcd3b GFS2: Automatical... |
1083 1084 1085 |
!test_bit(GLF_DEMOTE, &gl->gl_flags) && gl->gl_name.ln_type == LM_TYPE_INODE) delay = gl->gl_hold_time; |
c4f68a130 [GFS2] delay gloc... |
1086 1087 |
if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) gfs2_glock_put(gl); |
b3b94faa5 [GFS2] The core o... |
1088 |
} |
d93cfa988 [GFS2] Fix deallo... |
1089 1090 1091 1092 1093 1094 |
void gfs2_glock_dq_wait(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; gfs2_glock_dq(gh); wait_on_demote(gl); } |
b3b94faa5 [GFS2] The core o... |
1095 |
/** |
b3b94faa5 [GFS2] The core o... |
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 |
* gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it * @gh: the holder structure * */ void gfs2_glock_dq_uninit(struct gfs2_holder *gh) { gfs2_glock_dq(gh); gfs2_holder_uninit(gh); } /** * gfs2_glock_nq_num - acquire a glock based on lock number * @sdp: the filesystem * @number: the lock number * @glops: the glock operations for the type of glock * @state: the state to acquire the glock in |
25985edce Fix common misspe... |
1113 |
* @flags: modifier flags for the acquisition |
b3b94faa5 [GFS2] The core o... |
1114 1115 1116 1117 |
* @gh: the struct gfs2_holder * * Returns: errno */ |
cd915493f [GFS2] Change all... |
1118 |
int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number, |
8fb4b536e [GFS2] Make glock... |
1119 1120 |
const struct gfs2_glock_operations *glops, unsigned int state, int flags, struct gfs2_holder *gh) |
b3b94faa5 [GFS2] The core o... |
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 |
{ struct gfs2_glock *gl; int error; error = gfs2_glock_get(sdp, number, glops, CREATE, &gl); if (!error) { error = gfs2_glock_nq_init(gl, state, flags, gh); gfs2_glock_put(gl); } return error; } /** * glock_compare - Compare two struct gfs2_glock structures for sorting * @arg_a: the first structure * @arg_b: the second structure * */ static int glock_compare(const void *arg_a, const void *arg_b) { |
a5e08a9ef [GFS2] Add consts... |
1143 1144 1145 1146 |
const struct gfs2_holder *gh_a = *(const struct gfs2_holder **)arg_a; const struct gfs2_holder *gh_b = *(const struct gfs2_holder **)arg_b; const struct lm_lockname *a = &gh_a->gh_gl->gl_name; const struct lm_lockname *b = &gh_b->gh_gl->gl_name; |
b3b94faa5 [GFS2] The core o... |
1147 1148 |
if (a->ln_number > b->ln_number) |
a5e08a9ef [GFS2] Add consts... |
1149 1150 1151 |
return 1; if (a->ln_number < b->ln_number) return -1; |
1c0f4872d [GFS2] Remove loc... |
1152 |
BUG_ON(gh_a->gh_gl->gl_ops->go_type == gh_b->gh_gl->gl_ops->go_type); |
a5e08a9ef [GFS2] Add consts... |
1153 |
return 0; |
b3b94faa5 [GFS2] The core o... |
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
} /** * nq_m_sync - synchonously acquire more than one glock in deadlock free order * @num_gh: the number of structures * @ghs: an array of struct gfs2_holder structures * * Returns: 0 on success (all glocks acquired), * errno on failure (no glocks acquired) */ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs, struct gfs2_holder **p) { unsigned int x; int error = 0; for (x = 0; x < num_gh; x++) p[x] = &ghs[x]; sort(p, num_gh, sizeof(struct gfs2_holder *), glock_compare, NULL); for (x = 0; x < num_gh; x++) { p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); error = gfs2_glock_nq(p[x]); if (error) { while (x--) gfs2_glock_dq(p[x]); break; } } return error; } /** * gfs2_glock_nq_m - acquire multiple glocks * @num_gh: the number of structures * @ghs: an array of struct gfs2_holder structures * |
b3b94faa5 [GFS2] The core o... |
1195 1196 1197 1198 1199 1200 1201 |
* * Returns: 0 on success (all glocks acquired), * errno on failure (no glocks acquired) */ int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs) { |
eaf5bd3ca [GFS2] Simplify m... |
1202 1203 |
struct gfs2_holder *tmp[4]; struct gfs2_holder **pph = tmp; |
b3b94faa5 [GFS2] The core o... |
1204 |
int error = 0; |
eaf5bd3ca [GFS2] Simplify m... |
1205 1206 |
switch(num_gh) { case 0: |
b3b94faa5 [GFS2] The core o... |
1207 |
return 0; |
eaf5bd3ca [GFS2] Simplify m... |
1208 |
case 1: |
b3b94faa5 [GFS2] The core o... |
1209 1210 |
ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); return gfs2_glock_nq(ghs); |
eaf5bd3ca [GFS2] Simplify m... |
1211 1212 |
default: if (num_gh <= 4) |
b3b94faa5 [GFS2] The core o... |
1213 |
break; |
eaf5bd3ca [GFS2] Simplify m... |
1214 1215 1216 |
pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS); if (!pph) return -ENOMEM; |
b3b94faa5 [GFS2] The core o... |
1217 |
} |
eaf5bd3ca [GFS2] Simplify m... |
1218 |
error = nq_m_sync(num_gh, ghs, pph); |
b3b94faa5 [GFS2] The core o... |
1219 |
|
eaf5bd3ca [GFS2] Simplify m... |
1220 1221 |
if (pph != tmp) kfree(pph); |
b3b94faa5 [GFS2] The core o... |
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 |
return error; } /** * gfs2_glock_dq_m - release multiple glocks * @num_gh: the number of structures * @ghs: an array of struct gfs2_holder structures * */ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs) { |
fa1bbdea3 GFS2: Optimize gl... |
1235 1236 |
while (num_gh--) gfs2_glock_dq(&ghs[num_gh]); |
b3b94faa5 [GFS2] The core o... |
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
} /** * gfs2_glock_dq_uninit_m - release multiple glocks * @num_gh: the number of structures * @ghs: an array of struct gfs2_holder structures * */ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs) { |
fa1bbdea3 GFS2: Optimize gl... |
1248 1249 |
while (num_gh--) gfs2_glock_dq_uninit(&ghs[num_gh]); |
b3b94faa5 [GFS2] The core o... |
1250 |
} |
f057f6cdf GFS2: Merge lock_... |
1251 |
void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) |
da755fdb4 [GFS2] Remove lm.... |
1252 |
{ |
c4f68a130 [GFS2] delay gloc... |
1253 1254 1255 |
unsigned long delay = 0; unsigned long holdtime; unsigned long now = jiffies; |
b3b94faa5 [GFS2] The core o... |
1256 |
|
f057f6cdf GFS2: Merge lock_... |
1257 |
gfs2_glock_hold(gl); |
7cf8dcd3b GFS2: Automatical... |
1258 1259 1260 |
holdtime = gl->gl_tchange + gl->gl_hold_time; if (test_bit(GLF_QUEUED, &gl->gl_flags) && gl->gl_name.ln_type == LM_TYPE_INODE) { |
7b5e3d5fc GFS2: Don't enfor... |
1261 1262 1263 |
if (time_before(now, holdtime)) delay = holdtime - now; if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) |
7cf8dcd3b GFS2: Automatical... |
1264 |
delay = gl->gl_hold_time; |
7b5e3d5fc GFS2: Don't enfor... |
1265 |
} |
b3b94faa5 [GFS2] The core o... |
1266 |
|
6802e3400 [GFS2] Clean up t... |
1267 |
spin_lock(&gl->gl_spin); |
97cc1025b GFS2: Kill two da... |
1268 |
handle_callback(gl, state, delay); |
6802e3400 [GFS2] Clean up t... |
1269 |
spin_unlock(&gl->gl_spin); |
c4f68a130 [GFS2] delay gloc... |
1270 1271 |
if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) gfs2_glock_put(gl); |
b3b94faa5 [GFS2] The core o... |
1272 1273 1274 |
} /** |
0809f6ec1 GFS2: Fix recover... |
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 |
* gfs2_should_freeze - Figure out if glock should be frozen * @gl: The glock in question * * Glocks are not frozen if (a) the result of the dlm operation is * an error, (b) the locking operation was an unlock operation or * (c) if there is a "noexp" flagged request anywhere in the queue * * Returns: 1 if freezing should occur, 0 otherwise */ static int gfs2_should_freeze(const struct gfs2_glock *gl) { const struct gfs2_holder *gh; if (gl->gl_reply & ~LM_OUT_ST_MASK) return 0; if (gl->gl_target == LM_ST_UNLOCKED) return 0; list_for_each_entry(gh, &gl->gl_holders, gh_list) { if (test_bit(HIF_HOLDER, &gh->gh_iflags)) continue; if (LM_FLAG_NOEXP & gh->gh_flags) return 0; } return 1; } /** |
f057f6cdf GFS2: Merge lock_... |
1305 1306 1307 |
* gfs2_glock_complete - Callback used by locking * @gl: Pointer to the glock * @ret: The return value from the dlm |
b3b94faa5 [GFS2] The core o... |
1308 |
* |
47a25380e GFS2: Merge glock... |
1309 1310 |
* The gl_reply field is under the gl_spin lock so that it is ok * to use a bitfield shared with other glock state fields. |
b3b94faa5 [GFS2] The core o... |
1311 |
*/ |
f057f6cdf GFS2: Merge lock_... |
1312 |
void gfs2_glock_complete(struct gfs2_glock *gl, int ret) |
b3b94faa5 [GFS2] The core o... |
1313 |
{ |
f057f6cdf GFS2: Merge lock_... |
1314 |
struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; |
0809f6ec1 GFS2: Fix recover... |
1315 |
|
47a25380e GFS2: Merge glock... |
1316 |
spin_lock(&gl->gl_spin); |
f057f6cdf GFS2: Merge lock_... |
1317 |
gl->gl_reply = ret; |
0809f6ec1 GFS2: Fix recover... |
1318 |
|
e0c2a9aa1 GFS2: dlm based r... |
1319 |
if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_recover_flags))) { |
0809f6ec1 GFS2: Fix recover... |
1320 |
if (gfs2_should_freeze(gl)) { |
f057f6cdf GFS2: Merge lock_... |
1321 |
set_bit(GLF_FROZEN, &gl->gl_flags); |
0809f6ec1 GFS2: Fix recover... |
1322 |
spin_unlock(&gl->gl_spin); |
b3b94faa5 [GFS2] The core o... |
1323 |
return; |
0809f6ec1 GFS2: Fix recover... |
1324 |
} |
b3b94faa5 [GFS2] The core o... |
1325 |
} |
47a25380e GFS2: Merge glock... |
1326 1327 |
spin_unlock(&gl->gl_spin); |
f057f6cdf GFS2: Merge lock_... |
1328 |
set_bit(GLF_REPLY_PENDING, &gl->gl_flags); |
47a25380e GFS2: Merge glock... |
1329 |
smp_wmb(); |
f057f6cdf GFS2: Merge lock_... |
1330 1331 1332 |
gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); |
b3b94faa5 [GFS2] The core o... |
1333 |
} |
b3b94faa5 [GFS2] The core o... |
1334 |
|
1495f230f vmscan: change sh... |
1335 1336 |
static int gfs2_shrink_glock_memory(struct shrinker *shrink, struct shrink_control *sc) |
b3b94faa5 [GFS2] The core o... |
1337 1338 |
{ struct gfs2_glock *gl; |
97cc1025b GFS2: Kill two da... |
1339 1340 |
int may_demote; int nr_skipped = 0; |
1495f230f vmscan: change sh... |
1341 1342 |
int nr = sc->nr_to_scan; gfp_t gfp_mask = sc->gfp_mask; |
97cc1025b GFS2: Kill two da... |
1343 |
LIST_HEAD(skipped); |
b3b94faa5 [GFS2] The core o... |
1344 |
|
97cc1025b GFS2: Kill two da... |
1345 1346 |
if (nr == 0) goto out; |
b3b94faa5 [GFS2] The core o... |
1347 |
|
97cc1025b GFS2: Kill two da... |
1348 1349 |
if (!(gfp_mask & __GFP_FS)) return -1; |
b3b94faa5 [GFS2] The core o... |
1350 |
|
97cc1025b GFS2: Kill two da... |
1351 1352 1353 1354 |
spin_lock(&lru_lock); while(nr && !list_empty(&lru_list)) { gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru); list_del_init(&gl->gl_lru); |
627c10b7e GFS2: Improve tra... |
1355 |
clear_bit(GLF_LRU, &gl->gl_flags); |
97cc1025b GFS2: Kill two da... |
1356 1357 1358 1359 1360 |
atomic_dec(&lru_count); /* Test for being demotable */ if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { gfs2_glock_hold(gl); |
97cc1025b GFS2: Kill two da... |
1361 1362 1363 |
spin_unlock(&lru_lock); spin_lock(&gl->gl_spin); may_demote = demote_ok(gl); |
97cc1025b GFS2: Kill two da... |
1364 1365 1366 |
if (may_demote) { handle_callback(gl, LM_ST_UNLOCKED, 0); nr--; |
97cc1025b GFS2: Kill two da... |
1367 |
} |
7e71c55ee GFS2: Fix potenti... |
1368 1369 |
clear_bit(GLF_LOCK, &gl->gl_flags); smp_mb__after_clear_bit(); |
2163b1e61 GFS2: Shrink the ... |
1370 |
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
b94a170e9 GFS2: remove dcac... |
1371 1372 |
gfs2_glock_put_nolock(gl); spin_unlock(&gl->gl_spin); |
97cc1025b GFS2: Kill two da... |
1373 |
spin_lock(&lru_lock); |
2163b1e61 GFS2: Shrink the ... |
1374 |
continue; |
97cc1025b GFS2: Kill two da... |
1375 |
} |
2163b1e61 GFS2: Shrink the ... |
1376 1377 |
nr_skipped++; list_add(&gl->gl_lru, &skipped); |
627c10b7e GFS2: Improve tra... |
1378 |
set_bit(GLF_LRU, &gl->gl_flags); |
b3b94faa5 [GFS2] The core o... |
1379 |
} |
97cc1025b GFS2: Kill two da... |
1380 1381 1382 1383 1384 |
list_splice(&skipped, &lru_list); atomic_add(nr_skipped, &lru_count); spin_unlock(&lru_lock); out: return (atomic_read(&lru_count) / 100) * sysctl_vfs_cache_pressure; |
b3b94faa5 [GFS2] The core o... |
1385 |
} |
97cc1025b GFS2: Kill two da... |
1386 1387 1388 1389 |
static struct shrinker glock_shrinker = { .shrink = gfs2_shrink_glock_memory, .seeks = DEFAULT_SEEKS, }; |
b3b94faa5 [GFS2] The core o... |
1390 1391 1392 1393 1394 1395 |
/** * examine_bucket - Call a function for glock in a hash bucket * @examiner: the function * @sdp: the filesystem * @bucket: the bucket * |
b3b94faa5 [GFS2] The core o... |
1396 |
*/ |
bc015cb84 GFS2: Use RCU for... |
1397 |
static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp, |
37b2fa6a2 [GFS2] Move rwloc... |
1398 |
unsigned int hash) |
b3b94faa5 [GFS2] The core o... |
1399 |
{ |
bc015cb84 GFS2: Use RCU for... |
1400 1401 1402 |
struct gfs2_glock *gl; struct hlist_bl_head *head = &gl_hash_table[hash]; struct hlist_bl_node *pos; |
b3b94faa5 [GFS2] The core o... |
1403 |
|
bc015cb84 GFS2: Use RCU for... |
1404 1405 1406 |
rcu_read_lock(); hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) { if ((gl->gl_sbd == sdp) && atomic_read(&gl->gl_ref)) |
242644346 [GFS2] Rewrite of... |
1407 |
examiner(gl); |
b3b94faa5 [GFS2] The core o... |
1408 |
} |
bc015cb84 GFS2: Use RCU for... |
1409 |
rcu_read_unlock(); |
8fbbfd214 [GFS2] Reduce num... |
1410 |
cond_resched(); |
bc015cb84 GFS2: Use RCU for... |
1411 1412 1413 1414 1415 1416 1417 1418 |
} static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) { unsigned x; for (x = 0; x < GFS2_GL_HASH_SIZE; x++) examine_bucket(examiner, sdp, x); |
b3b94faa5 [GFS2] The core o... |
1419 |
} |
f057f6cdf GFS2: Merge lock_... |
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 |
/** * thaw_glock - thaw out a glock which has an unprocessed reply waiting * @gl: The glock to thaw * * N.B. When we freeze a glock, we leave a ref to the glock outstanding, * so this has to result in the ref count being dropped by one. */ static void thaw_glock(struct gfs2_glock *gl) { if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) return; |
f057f6cdf GFS2: Merge lock_... |
1433 1434 1435 1436 |
set_bit(GLF_REPLY_PENDING, &gl->gl_flags); gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); |
f057f6cdf GFS2: Merge lock_... |
1437 |
} |
b3b94faa5 [GFS2] The core o... |
1438 |
/** |
b3b94faa5 [GFS2] The core o... |
1439 1440 1441 1442 1443 1444 1445 |
* clear_glock - look at a glock and see if we can free it from glock cache * @gl: the glock to look at * */ static void clear_glock(struct gfs2_glock *gl) { |
f42ab0852 GFS2: Optimise gl... |
1446 |
gfs2_glock_remove_from_lru(gl); |
b3b94faa5 [GFS2] The core o... |
1447 |
|
6802e3400 [GFS2] Clean up t... |
1448 |
spin_lock(&gl->gl_spin); |
c741c4551 GFS2: Fix spectat... |
1449 |
if (gl->gl_state != LM_ST_UNLOCKED) |
97cc1025b GFS2: Kill two da... |
1450 |
handle_callback(gl, LM_ST_UNLOCKED, 0); |
6802e3400 [GFS2] Clean up t... |
1451 1452 1453 1454 |
spin_unlock(&gl->gl_spin); gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); |
b3b94faa5 [GFS2] The core o... |
1455 1456 1457 |
} /** |
f057f6cdf GFS2: Merge lock_... |
1458 1459 1460 1461 1462 1463 1464 |
* gfs2_glock_thaw - Thaw any frozen glocks * @sdp: The super block * */ void gfs2_glock_thaw(struct gfs2_sbd *sdp) { |
bc015cb84 GFS2: Use RCU for... |
1465 1466 |
glock_hash_walk(thaw_glock, sdp); } |
f057f6cdf GFS2: Merge lock_... |
1467 |
|
bc015cb84 GFS2: Use RCU for... |
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 |
static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl) { int ret; spin_lock(&gl->gl_spin); ret = __dump_glock(seq, gl); spin_unlock(&gl->gl_spin); return ret; } static void dump_glock_func(struct gfs2_glock *gl) { dump_glock(NULL, gl); |
f057f6cdf GFS2: Merge lock_... |
1480 1481 1482 |
} /** |
b3b94faa5 [GFS2] The core o... |
1483 1484 1485 1486 |
* gfs2_gl_hash_clear - Empty out the glock hash table * @sdp: the filesystem * @wait: wait until it's all gone * |
1bdad6063 [GFS2] Remove rem... |
1487 |
* Called when unmounting the filesystem. |
b3b94faa5 [GFS2] The core o... |
1488 |
*/ |
fefc03bfe Revert "GFS2: Fix... |
1489 |
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) |
b3b94faa5 [GFS2] The core o... |
1490 |
{ |
bc015cb84 GFS2: Use RCU for... |
1491 |
glock_hash_walk(clear_glock, sdp); |
8f05228ee GFS2: Extend umou... |
1492 1493 |
flush_workqueue(glock_workqueue); wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); |
bc015cb84 GFS2: Use RCU for... |
1494 |
glock_hash_walk(dump_glock_func, sdp); |
b3b94faa5 [GFS2] The core o... |
1495 |
} |
813e0c46c GFS2: Fix "trunca... |
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 |
void gfs2_glock_finish_truncate(struct gfs2_inode *ip) { struct gfs2_glock *gl = ip->i_gl; int ret; ret = gfs2_truncatei_resume(ip); gfs2_assert_withdraw(gl->gl_sbd, ret == 0); spin_lock(&gl->gl_spin); clear_bit(GLF_LOCK, &gl->gl_flags); run_queue(gl, 1); spin_unlock(&gl->gl_spin); } |
6802e3400 [GFS2] Clean up t... |
1509 |
static const char *state2str(unsigned state) |
04b933f27 [GFS2] Red Hat bz... |
1510 |
{ |
6802e3400 [GFS2] Clean up t... |
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 |
switch(state) { case LM_ST_UNLOCKED: return "UN"; case LM_ST_SHARED: return "SH"; case LM_ST_DEFERRED: return "DF"; case LM_ST_EXCLUSIVE: return "EX"; } return "??"; } static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags) { char *p = buf; if (flags & LM_FLAG_TRY) *p++ = 't'; if (flags & LM_FLAG_TRY_1CB) *p++ = 'T'; if (flags & LM_FLAG_NOEXP) *p++ = 'e'; if (flags & LM_FLAG_ANY) |
f057f6cdf GFS2: Merge lock_... |
1534 |
*p++ = 'A'; |
6802e3400 [GFS2] Clean up t... |
1535 1536 1537 1538 1539 1540 |
if (flags & LM_FLAG_PRIORITY) *p++ = 'p'; if (flags & GL_ASYNC) *p++ = 'a'; if (flags & GL_EXACT) *p++ = 'E'; |
6802e3400 [GFS2] Clean up t... |
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 |
if (flags & GL_NOCACHE) *p++ = 'c'; if (test_bit(HIF_HOLDER, &iflags)) *p++ = 'H'; if (test_bit(HIF_WAIT, &iflags)) *p++ = 'W'; if (test_bit(HIF_FIRST, &iflags)) *p++ = 'F'; *p = 0; return buf; |
04b933f27 [GFS2] Red Hat bz... |
1551 |
} |
b3b94faa5 [GFS2] The core o... |
1552 1553 |
/** * dump_holder - print information about a glock holder |
6802e3400 [GFS2] Clean up t... |
1554 |
* @seq: the seq_file struct |
b3b94faa5 [GFS2] The core o... |
1555 1556 1557 1558 |
* @gh: the glock holder * * Returns: 0 on success, -ENOBUFS when we run out of space */ |
6802e3400 [GFS2] Clean up t... |
1559 |
static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) |
b3b94faa5 [GFS2] The core o... |
1560 |
{ |
6802e3400 [GFS2] Clean up t... |
1561 |
struct task_struct *gh_owner = NULL; |
6802e3400 [GFS2] Clean up t... |
1562 |
char flags_buf[32]; |
b3b94faa5 [GFS2] The core o... |
1563 |
|
6802e3400 [GFS2] Clean up t... |
1564 |
if (gh->gh_owner_pid) |
b1e058da5 gfs2: make gfs2_h... |
1565 |
gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID); |
cc18152eb GFS2: fs/gfs2/glo... |
1566 1567 1568 1569 1570 1571 1572 1573 |
gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS ", state2str(gh->gh_state), hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags), gh->gh_error, gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1, gh_owner ? gh_owner->comm : "(ended)", (void *)gh->gh_ip); |
7c52b166c [GFS2] Add gfs2_t... |
1574 |
return 0; |
b3b94faa5 [GFS2] The core o... |
1575 |
} |
627c10b7e GFS2: Improve tra... |
1576 |
static const char *gflags2str(char *buf, const struct gfs2_glock *gl) |
6802e3400 [GFS2] Clean up t... |
1577 |
{ |
627c10b7e GFS2: Improve tra... |
1578 |
const unsigned long *gflags = &gl->gl_flags; |
6802e3400 [GFS2] Clean up t... |
1579 |
char *p = buf; |
627c10b7e GFS2: Improve tra... |
1580 |
|
6802e3400 [GFS2] Clean up t... |
1581 1582 |
if (test_bit(GLF_LOCK, gflags)) *p++ = 'l'; |
6802e3400 [GFS2] Clean up t... |
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 |
if (test_bit(GLF_DEMOTE, gflags)) *p++ = 'D'; if (test_bit(GLF_PENDING_DEMOTE, gflags)) *p++ = 'd'; if (test_bit(GLF_DEMOTE_IN_PROGRESS, gflags)) *p++ = 'p'; if (test_bit(GLF_DIRTY, gflags)) *p++ = 'y'; if (test_bit(GLF_LFLUSH, gflags)) *p++ = 'f'; if (test_bit(GLF_INVALIDATE_IN_PROGRESS, gflags)) *p++ = 'i'; if (test_bit(GLF_REPLY_PENDING, gflags)) *p++ = 'r'; |
f057f6cdf GFS2: Merge lock_... |
1597 |
if (test_bit(GLF_INITIAL, gflags)) |
d8348de06 GFS2: Fix deadloc... |
1598 |
*p++ = 'I'; |
f057f6cdf GFS2: Merge lock_... |
1599 1600 |
if (test_bit(GLF_FROZEN, gflags)) *p++ = 'F'; |
7b5e3d5fc GFS2: Don't enfor... |
1601 1602 |
if (test_bit(GLF_QUEUED, gflags)) *p++ = 'q'; |
627c10b7e GFS2: Improve tra... |
1603 1604 1605 1606 |
if (test_bit(GLF_LRU, gflags)) *p++ = 'L'; if (gl->gl_object) *p++ = 'o'; |
6802e3400 [GFS2] Clean up t... |
1607 1608 |
*p = 0; return buf; |
b3b94faa5 [GFS2] The core o... |
1609 1610 1611 |
} /** |
6802e3400 [GFS2] Clean up t... |
1612 1613 |
* __dump_glock - print information about a glock * @seq: The seq_file struct |
b3b94faa5 [GFS2] The core o... |
1614 |
* @gl: the glock |
6802e3400 [GFS2] Clean up t... |
1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 |
* * The file format is as follows: * One line per object, capital letters are used to indicate objects * G = glock, I = Inode, R = rgrp, H = holder. Glocks are not indented, * other objects are indented by a single space and follow the glock to * which they are related. Fields are indicated by lower case letters * followed by a colon and the field value, except for strings which are in * [] so that its possible to see if they are composed of spaces for * example. The field's are n = number (id of the object), f = flags, * t = type, s = state, r = refcount, e = error, p = pid. |
b3b94faa5 [GFS2] The core o... |
1625 1626 1627 |
* * Returns: 0 on success, -ENOBUFS when we run out of space */ |
6802e3400 [GFS2] Clean up t... |
1628 |
static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) |
b3b94faa5 [GFS2] The core o... |
1629 |
{ |
6802e3400 [GFS2] Clean up t... |
1630 1631 1632 1633 1634 |
const struct gfs2_glock_operations *glops = gl->gl_ops; unsigned long long dtime; const struct gfs2_holder *gh; char gflags_buf[32]; int error = 0; |
b3b94faa5 [GFS2] The core o... |
1635 |
|
6802e3400 [GFS2] Clean up t... |
1636 1637 1638 1639 |
dtime = jiffies - gl->gl_demote_time; dtime *= 1000000/HZ; /* demote time in uSec */ if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) dtime = 0; |
7cf8dcd3b GFS2: Automatical... |
1640 1641 |
gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d m:%ld ", |
6802e3400 [GFS2] Clean up t... |
1642 1643 1644 |
state2str(gl->gl_state), gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number, |
627c10b7e GFS2: Improve tra... |
1645 |
gflags2str(gflags_buf, gl), |
6802e3400 [GFS2] Clean up t... |
1646 1647 |
state2str(gl->gl_target), state2str(gl->gl_demote_state), dtime, |
6802e3400 [GFS2] Clean up t... |
1648 |
atomic_read(&gl->gl_ail_count), |
f42ab0852 GFS2: Optimise gl... |
1649 |
atomic_read(&gl->gl_revokes), |
7cf8dcd3b GFS2: Automatical... |
1650 |
atomic_read(&gl->gl_ref), gl->gl_hold_time); |
b3b94faa5 [GFS2] The core o... |
1651 |
|
b3b94faa5 [GFS2] The core o... |
1652 |
list_for_each_entry(gh, &gl->gl_holders, gh_list) { |
6802e3400 [GFS2] Clean up t... |
1653 |
error = dump_holder(seq, gh); |
b3b94faa5 [GFS2] The core o... |
1654 1655 1656 |
if (error) goto out; } |
6802e3400 [GFS2] Clean up t... |
1657 1658 |
if (gl->gl_state != LM_ST_UNLOCKED && glops->go_dump) error = glops->go_dump(seq, gl); |
a91ea69ff [GFS2] Align all ... |
1659 |
out: |
b3b94faa5 [GFS2] The core o... |
1660 1661 |
return error; } |
6802e3400 [GFS2] Clean up t... |
1662 |
|
b3b94faa5 [GFS2] The core o... |
1663 |
|
8fbbfd214 [GFS2] Reduce num... |
1664 |
|
85d1da67f [GFS2] Move glock... |
1665 1666 1667 1668 |
int __init gfs2_glock_init(void) { unsigned i; for(i = 0; i < GFS2_GL_HASH_SIZE; i++) { |
bc015cb84 GFS2: Use RCU for... |
1669 |
INIT_HLIST_BL_HEAD(&gl_hash_table[i]); |
087efdd39 [GFS2] Make glock... |
1670 |
} |
8fbbfd214 [GFS2] Reduce num... |
1671 |
|
d2115778c GFS2: Change two ... |
1672 |
glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM | |
58a69cb47 workqueue, freeze... |
1673 |
WQ_HIGHPRI | WQ_FREEZABLE, 0); |
97cc1025b GFS2: Kill two da... |
1674 |
if (IS_ERR(glock_workqueue)) |
c4f68a130 [GFS2] delay gloc... |
1675 |
return PTR_ERR(glock_workqueue); |
d2115778c GFS2: Change two ... |
1676 |
gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", |
58a69cb47 workqueue, freeze... |
1677 |
WQ_MEM_RECLAIM | WQ_FREEZABLE, |
d2115778c GFS2: Change two ... |
1678 |
0); |
b94a170e9 GFS2: remove dcac... |
1679 1680 1681 1682 |
if (IS_ERR(gfs2_delete_workqueue)) { destroy_workqueue(glock_workqueue); return PTR_ERR(gfs2_delete_workqueue); } |
97cc1025b GFS2: Kill two da... |
1683 1684 |
register_shrinker(&glock_shrinker); |
c4f68a130 [GFS2] delay gloc... |
1685 |
|
85d1da67f [GFS2] Move glock... |
1686 1687 |
return 0; } |
8fbbfd214 [GFS2] Reduce num... |
1688 1689 |
void gfs2_glock_exit(void) { |
97cc1025b GFS2: Kill two da... |
1690 |
unregister_shrinker(&glock_shrinker); |
c4f68a130 [GFS2] delay gloc... |
1691 |
destroy_workqueue(glock_workqueue); |
b94a170e9 GFS2: remove dcac... |
1692 |
destroy_workqueue(gfs2_delete_workqueue); |
8fbbfd214 [GFS2] Reduce num... |
1693 |
} |
bc015cb84 GFS2: Use RCU for... |
1694 1695 1696 1697 1698 1699 1700 1701 |
static inline struct gfs2_glock *glock_hash_chain(unsigned hash) { return hlist_bl_entry(hlist_bl_first_rcu(&gl_hash_table[hash]), struct gfs2_glock, gl_list); } static inline struct gfs2_glock *glock_hash_next(struct gfs2_glock *gl) { |
7e32d0261 GFS2: Don't use _... |
1702 |
return hlist_bl_entry(rcu_dereference(gl->gl_list.next), |
bc015cb84 GFS2: Use RCU for... |
1703 1704 |
struct gfs2_glock, gl_list); } |
6802e3400 [GFS2] Clean up t... |
1705 |
static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) |
7c52b166c [GFS2] Add gfs2_t... |
1706 |
{ |
7b08fc620 [GFS2] Fix an oop... |
1707 |
struct gfs2_glock *gl; |
bc015cb84 GFS2: Use RCU for... |
1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 |
do { gl = gi->gl; if (gl) { gi->gl = glock_hash_next(gl); } else { gi->gl = glock_hash_chain(gi->hash); } while (gi->gl == NULL) { gi->hash++; if (gi->hash >= GFS2_GL_HASH_SIZE) { rcu_read_unlock(); return 1; } gi->gl = glock_hash_chain(gi->hash); } /* Skip entries for other sb and dead entries */ } while (gi->sdp != gi->gl->gl_sbd || atomic_read(&gi->gl->gl_ref) == 0); |
a947e0335 [GFS2] Wendy's du... |
1725 |
|
7c52b166c [GFS2] Add gfs2_t... |
1726 1727 |
return 0; } |
6802e3400 [GFS2] Clean up t... |
1728 |
static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) |
7c52b166c [GFS2] Add gfs2_t... |
1729 |
{ |
6802e3400 [GFS2] Clean up t... |
1730 |
struct gfs2_glock_iter *gi = seq->private; |
7c52b166c [GFS2] Add gfs2_t... |
1731 |
loff_t n = *pos; |
6802e3400 [GFS2] Clean up t... |
1732 |
gi->hash = 0; |
bc015cb84 GFS2: Use RCU for... |
1733 |
rcu_read_lock(); |
7c52b166c [GFS2] Add gfs2_t... |
1734 |
|
6802e3400 [GFS2] Clean up t... |
1735 |
do { |
bc015cb84 GFS2: Use RCU for... |
1736 |
if (gfs2_glock_iter_next(gi)) |
7c52b166c [GFS2] Add gfs2_t... |
1737 |
return NULL; |
6802e3400 [GFS2] Clean up t... |
1738 |
} while (n--); |
7c52b166c [GFS2] Add gfs2_t... |
1739 |
|
6802e3400 [GFS2] Clean up t... |
1740 |
return gi->gl; |
7c52b166c [GFS2] Add gfs2_t... |
1741 |
} |
6802e3400 [GFS2] Clean up t... |
1742 |
static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr, |
7c52b166c [GFS2] Add gfs2_t... |
1743 1744 |
loff_t *pos) { |
6802e3400 [GFS2] Clean up t... |
1745 |
struct gfs2_glock_iter *gi = seq->private; |
7c52b166c [GFS2] Add gfs2_t... |
1746 1747 |
(*pos)++; |
bc015cb84 GFS2: Use RCU for... |
1748 |
if (gfs2_glock_iter_next(gi)) |
7c52b166c [GFS2] Add gfs2_t... |
1749 |
return NULL; |
7c52b166c [GFS2] Add gfs2_t... |
1750 |
|
6802e3400 [GFS2] Clean up t... |
1751 |
return gi->gl; |
7c52b166c [GFS2] Add gfs2_t... |
1752 |
} |
6802e3400 [GFS2] Clean up t... |
1753 |
static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr) |
7c52b166c [GFS2] Add gfs2_t... |
1754 |
{ |
6802e3400 [GFS2] Clean up t... |
1755 |
struct gfs2_glock_iter *gi = seq->private; |
bc015cb84 GFS2: Use RCU for... |
1756 1757 1758 1759 |
if (gi->gl) rcu_read_unlock(); gi->gl = NULL; |
7c52b166c [GFS2] Add gfs2_t... |
1760 |
} |
6802e3400 [GFS2] Clean up t... |
1761 |
static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) |
7c52b166c [GFS2] Add gfs2_t... |
1762 |
{ |
6802e3400 [GFS2] Clean up t... |
1763 |
return dump_glock(seq, iter_ptr); |
7c52b166c [GFS2] Add gfs2_t... |
1764 |
} |
4ef290025 [GFS2] mark struc... |
1765 |
static const struct seq_operations gfs2_glock_seq_ops = { |
7c52b166c [GFS2] Add gfs2_t... |
1766 1767 1768 1769 1770 1771 1772 1773 |
.start = gfs2_glock_seq_start, .next = gfs2_glock_seq_next, .stop = gfs2_glock_seq_stop, .show = gfs2_glock_seq_show, }; static int gfs2_debugfs_open(struct inode *inode, struct file *file) { |
6802e3400 [GFS2] Clean up t... |
1774 1775 1776 1777 1778 1779 1780 1781 |
int ret = seq_open_private(file, &gfs2_glock_seq_ops, sizeof(struct gfs2_glock_iter)); if (ret == 0) { struct seq_file *seq = file->private_data; struct gfs2_glock_iter *gi = seq->private; gi->sdp = inode->i_private; } return ret; |
7c52b166c [GFS2] Add gfs2_t... |
1782 1783 1784 1785 1786 1787 1788 |
} static const struct file_operations gfs2_debug_fops = { .owner = THIS_MODULE, .open = gfs2_debugfs_open, .read = seq_read, .llseek = seq_lseek, |
6802e3400 [GFS2] Clean up t... |
1789 |
.release = seq_release_private, |
7c52b166c [GFS2] Add gfs2_t... |
1790 1791 1792 1793 |
}; int gfs2_create_debugfs_file(struct gfs2_sbd *sdp) { |
5f8820960 [GFS2] lockdump i... |
1794 1795 1796 1797 1798 1799 1800 1801 |
sdp->debugfs_dir = debugfs_create_dir(sdp->sd_table_name, gfs2_root); if (!sdp->debugfs_dir) return -ENOMEM; sdp->debugfs_dentry_glocks = debugfs_create_file("glocks", S_IFREG | S_IRUGO, sdp->debugfs_dir, sdp, &gfs2_debug_fops); if (!sdp->debugfs_dentry_glocks) |
7c52b166c [GFS2] Add gfs2_t... |
1802 1803 1804 1805 1806 1807 1808 |
return -ENOMEM; return 0; } void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp) { |
5f8820960 [GFS2] lockdump i... |
1809 1810 1811 1812 1813 1814 1815 1816 |
if (sdp && sdp->debugfs_dir) { if (sdp->debugfs_dentry_glocks) { debugfs_remove(sdp->debugfs_dentry_glocks); sdp->debugfs_dentry_glocks = NULL; } debugfs_remove(sdp->debugfs_dir); sdp->debugfs_dir = NULL; } |
7c52b166c [GFS2] Add gfs2_t... |
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 |
} int gfs2_register_debugfs(void) { gfs2_root = debugfs_create_dir("gfs2", NULL); return gfs2_root ? 0 : -ENOMEM; } void gfs2_unregister_debugfs(void) { debugfs_remove(gfs2_root); |
5f8820960 [GFS2] lockdump i... |
1828 |
gfs2_root = NULL; |
7c52b166c [GFS2] Add gfs2_t... |
1829 |
} |