aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/glops.c
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2011-08-31 04:53:19 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-10-21 07:39:31 -0400
commit7c9ca621137cde26be05448133fc1a554345f4f8 (patch)
tree9c0779d2ca6fa8a1c6dab7ff6391bef8f444f1b3 /fs/gfs2/glops.c
parent9453615a1a7ef3fa910c6464a619595556cfcd63 (diff)
GFS2: Use rbtree for resource groups and clean up bitmap buffer ref count scheme
Here is an update of Bob's original rbtree patch which, in addition, also resolves the rather strange ref counting that was being done relating to the bitmap blocks. Originally we had a dual system for journaling resource groups. The metadata blocks were journaled and also the rgrp itself was added to a list. The reason for adding the rgrp to the list in the journal was so that the "repolish clones" code could be run to update the free space, and potentially send any discard requests when the log was flushed. This was done by comparing the "cloned" bitmap with what had been written back on disk during the transaction commit. Due to this, there was a requirement to hang on to the rgrps' bitmap buffers until the journal had been flushed. For that reason, there was a rather complicated set up in the ->go_lock ->go_unlock functions for rgrps involving both a mutex and a spinlock (the ->sd_rindex_spin) to maintain a reference count on the buffers. However, the journal maintains a reference count on the buffers anyway, since they are being journaled as metadata buffers. So by moving the code which deals with the post-journal accounting for bitmap blocks to the metadata journaling code, we can entirely dispense with the rather strange buffer ref counting scheme and also the requirement to journal the rgrps. The net result of all this is that the ->sd_rindex_spin is left to do exactly one job, and that is to look after the rbtree or rgrps. This patch is designed to be a stepping stone towards using RCU for the rbtree of resource groups, however the reduction in the number of uses of the ->sd_rindex_spin is likely to have benefits for multi-threaded workloads, anyway. The patch retains ->go_lock and ->go_unlock for rgrps, however these maybe also be removed in future in favour of calling the functions directly where required in the code. That will allow locking of resource groups without needing to actually read them in - something that could be useful in speeding up statfs. In the mean time though it is valid to dereference ->bi_bh only when the rgrp is locked. This is basically the same rule as before, modulo the references not being valid until the following journal flush. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Signed-off-by: Bob Peterson <rpeterso@redhat.com> Cc: Benjamin Marzinski <bmarzins@redhat.com>
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r--fs/gfs2/glops.c42
1 files changed, 13 insertions, 29 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 0cc3ff48ce20..6f82aac9b0ee 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -134,6 +134,8 @@ void gfs2_ail_flush(struct gfs2_glock *gl)
134static void rgrp_go_sync(struct gfs2_glock *gl) 134static void rgrp_go_sync(struct gfs2_glock *gl)
135{ 135{
136 struct address_space *metamapping = gfs2_glock2aspace(gl); 136 struct address_space *metamapping = gfs2_glock2aspace(gl);
137 struct gfs2_rgrpd *rgd = gl->gl_object;
138 unsigned int x;
137 int error; 139 int error;
138 140
139 if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) 141 if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
@@ -145,6 +147,15 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
145 error = filemap_fdatawait(metamapping); 147 error = filemap_fdatawait(metamapping);
146 mapping_set_error(metamapping, error); 148 mapping_set_error(metamapping, error);
147 gfs2_ail_empty_gl(gl); 149 gfs2_ail_empty_gl(gl);
150
151 if (!rgd)
152 return;
153
154 for (x = 0; x < rgd->rd_length; x++) {
155 struct gfs2_bitmap *bi = rgd->rd_bits + x;
156 kfree(bi->bi_clone);
157 bi->bi_clone = NULL;
158 }
148} 159}
149 160
150/** 161/**
@@ -445,33 +456,6 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
445} 456}
446 457
447/** 458/**
448 * rgrp_go_lock - operation done after an rgrp lock is locked by
449 * a first holder on this node.
450 * @gl: the glock
451 * @flags:
452 *
453 * Returns: errno
454 */
455
456static int rgrp_go_lock(struct gfs2_holder *gh)
457{
458 return gfs2_rgrp_bh_get(gh->gh_gl->gl_object);
459}
460
461/**
462 * rgrp_go_unlock - operation done before an rgrp lock is unlocked by
463 * a last holder on this node.
464 * @gl: the glock
465 * @flags:
466 *
467 */
468
469static void rgrp_go_unlock(struct gfs2_holder *gh)
470{
471 gfs2_rgrp_bh_put(gh->gh_gl->gl_object);
472}
473
474/**
475 * trans_go_sync - promote/demote the transaction glock 459 * trans_go_sync - promote/demote the transaction glock
476 * @gl: the glock 460 * @gl: the glock
477 * @state: the requested state 461 * @state: the requested state
@@ -573,8 +557,8 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
573const struct gfs2_glock_operations gfs2_rgrp_glops = { 557const struct gfs2_glock_operations gfs2_rgrp_glops = {
574 .go_xmote_th = rgrp_go_sync, 558 .go_xmote_th = rgrp_go_sync,
575 .go_inval = rgrp_go_inval, 559 .go_inval = rgrp_go_inval,
576 .go_lock = rgrp_go_lock, 560 .go_lock = gfs2_rgrp_go_lock,
577 .go_unlock = rgrp_go_unlock, 561 .go_unlock = gfs2_rgrp_go_unlock,
578 .go_dump = gfs2_rgrp_dump, 562 .go_dump = gfs2_rgrp_dump,
579 .go_type = LM_TYPE_RGRP, 563 .go_type = LM_TYPE_RGRP,
580 .go_flags = GLOF_ASPACE, 564 .go_flags = GLOF_ASPACE,