diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2011-01-19 04:30:01 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2011-01-21 04:39:08 -0500 |
commit | bc015cb84129eb1451913cfebece270bf7a39e0f (patch) | |
tree | 4f116a61b802d87ae80051e9ae05d8fcb73d9ae7 /fs/gfs2/glops.c | |
parent | 2b1caf6ed7b888c95a1909d343799672731651a5 (diff) |
GFS2: Use RCU for glock hash table
This has a number of advantages:
- Reduces contention on the hash table lock
- Makes the code smaller and simpler
- Should speed up glock dumps when under load
- Removes ref count changing in examine_bucket
- No longer need hash chain lock in glock_put() in common case
There are some further changes which this enables and which
we may do in the future. One is to look at using SLAB_RCU,
and another is to look at using a per-cpu counter for the
per-sb glock counter, since that is touched twice in the
lifetime of each glock (but only used at umount time).
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r-- | fs/gfs2/glops.c | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 263561bf1a50..ac5fac948f87 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -206,8 +206,17 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
206 | static int inode_go_demote_ok(const struct gfs2_glock *gl) | 206 | static int inode_go_demote_ok(const struct gfs2_glock *gl) |
207 | { | 207 | { |
208 | struct gfs2_sbd *sdp = gl->gl_sbd; | 208 | struct gfs2_sbd *sdp = gl->gl_sbd; |
209 | struct gfs2_holder *gh; | ||
210 | |||
209 | if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) | 211 | if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) |
210 | return 0; | 212 | return 0; |
213 | |||
214 | if (!list_empty(&gl->gl_holders)) { | ||
215 | gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); | ||
216 | if (gh->gh_list.next != &gl->gl_holders) | ||
217 | return 0; | ||
218 | } | ||
219 | |||
211 | return 1; | 220 | return 1; |
212 | } | 221 | } |
213 | 222 | ||
@@ -272,19 +281,6 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
272 | } | 281 | } |
273 | 282 | ||
274 | /** | 283 | /** |
275 | * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock | ||
276 | * @gl: the glock | ||
277 | * | ||
278 | * Returns: 1 if it's ok | ||
279 | */ | ||
280 | |||
281 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) | ||
282 | { | ||
283 | const struct address_space *mapping = (const struct address_space *)(gl + 1); | ||
284 | return !mapping->nrpages; | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * rgrp_go_lock - operation done after an rgrp lock is locked by | 284 | * rgrp_go_lock - operation done after an rgrp lock is locked by |
289 | * a first holder on this node. | 285 | * a first holder on this node. |
290 | * @gl: the glock | 286 | * @gl: the glock |
@@ -410,7 +406,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = { | |||
410 | const struct gfs2_glock_operations gfs2_rgrp_glops = { | 406 | const struct gfs2_glock_operations gfs2_rgrp_glops = { |
411 | .go_xmote_th = rgrp_go_sync, | 407 | .go_xmote_th = rgrp_go_sync, |
412 | .go_inval = rgrp_go_inval, | 408 | .go_inval = rgrp_go_inval, |
413 | .go_demote_ok = rgrp_go_demote_ok, | ||
414 | .go_lock = rgrp_go_lock, | 409 | .go_lock = rgrp_go_lock, |
415 | .go_unlock = rgrp_go_unlock, | 410 | .go_unlock = rgrp_go_unlock, |
416 | .go_dump = gfs2_rgrp_dump, | 411 | .go_dump = gfs2_rgrp_dump, |