diff options
author | Bob Peterson <rpeterso@redhat.com> | 2019-04-04 23:41:38 -0400 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2019-05-07 17:39:14 -0400 |
commit | 73118ca8baf78dddd1f9c8ac67c1d80b47d9830e (patch) | |
tree | 72c0d2a327c8bace37ce5984f39d971ab5768594 /fs/gfs2 | |
parent | 9287c6452d2b1f24ea8e84bd3cf6f3c6f267f712 (diff) |
gfs2: Replace gl_revokes with a GLF flag
The gl_revokes value determines how many outstanding revokes a glock has
on the superblock revokes list; this is used to avoid unnecessary log
flushes. However, gl_revokes is only ever tested for being zero, and it's
only decremented in revoke_lo_after_commit, which removes all revokes
from the list, so we know that the gl_revoke values of all the glocks on
the list will reach zero. Therefore, we can replace gl_revokes with a
bit flag. This saves an atomic counter in struct gfs2_glock.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/glock.c | 4 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 2 | ||||
-rw-r--r-- | fs/gfs2/log.c | 4 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 33 | ||||
-rw-r--r-- | fs/gfs2/main.c | 1 | ||||
-rw-r--r-- | fs/gfs2/super.c | 2 |
6 files changed, 31 insertions, 15 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 71c28ff98b56..15c605cfcfc8 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -140,7 +140,7 @@ void gfs2_glock_free(struct gfs2_glock *gl) | |||
140 | { | 140 | { |
141 | struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; | 141 | struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; |
142 | 142 | ||
143 | BUG_ON(atomic_read(&gl->gl_revokes)); | 143 | BUG_ON(test_bit(GLF_REVOKES, &gl->gl_flags)); |
144 | rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms); | 144 | rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms); |
145 | smp_mb(); | 145 | smp_mb(); |
146 | wake_up_glock(gl); | 146 | wake_up_glock(gl); |
@@ -1801,7 +1801,7 @@ void gfs2_dump_glock(struct seq_file *seq, struct gfs2_glock *gl) | |||
1801 | state2str(gl->gl_target), | 1801 | state2str(gl->gl_target), |
1802 | state2str(gl->gl_demote_state), dtime, | 1802 | state2str(gl->gl_demote_state), dtime, |
1803 | atomic_read(&gl->gl_ail_count), | 1803 | atomic_read(&gl->gl_ail_count), |
1804 | atomic_read(&gl->gl_revokes), | 1804 | test_bit(GLF_REVOKES, &gl->gl_flags) ? 1 : 0, |
1805 | (int)gl->gl_lockref.count, gl->gl_hold_time); | 1805 | (int)gl->gl_lockref.count, gl->gl_hold_time); |
1806 | 1806 | ||
1807 | list_for_each_entry(gh, &gl->gl_holders, gh_list) | 1807 | list_for_each_entry(gh, &gl->gl_holders, gh_list) |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 86840a70ee1a..6a94b094a904 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -345,6 +345,7 @@ enum { | |||
345 | GLF_OBJECT = 14, /* Used only for tracing */ | 345 | GLF_OBJECT = 14, /* Used only for tracing */ |
346 | GLF_BLOCKING = 15, | 346 | GLF_BLOCKING = 15, |
347 | GLF_INODE_CREATING = 16, /* Inode creation occurring */ | 347 | GLF_INODE_CREATING = 16, /* Inode creation occurring */ |
348 | GLF_REVOKES = 17, /* Glock has revokes in queue */ | ||
348 | }; | 349 | }; |
349 | 350 | ||
350 | struct gfs2_glock { | 351 | struct gfs2_glock { |
@@ -374,7 +375,6 @@ struct gfs2_glock { | |||
374 | struct list_head gl_lru; | 375 | struct list_head gl_lru; |
375 | struct list_head gl_ail_list; | 376 | struct list_head gl_ail_list; |
376 | atomic_t gl_ail_count; | 377 | atomic_t gl_ail_count; |
377 | atomic_t gl_revokes; | ||
378 | struct delayed_work gl_work; | 378 | struct delayed_work gl_work; |
379 | union { | 379 | union { |
380 | /* For inode and iopen glocks only */ | 380 | /* For inode and iopen glocks only */ |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 7ba94b66c91b..d55315a46ece 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -606,8 +606,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | |||
606 | gfs2_remove_from_ail(bd); /* drops ref on bh */ | 606 | gfs2_remove_from_ail(bd); /* drops ref on bh */ |
607 | bd->bd_bh = NULL; | 607 | bd->bd_bh = NULL; |
608 | sdp->sd_log_num_revoke++; | 608 | sdp->sd_log_num_revoke++; |
609 | if (atomic_inc_return(&gl->gl_revokes) == 1) | 609 | if (!test_bit(GLF_REVOKES, &gl->gl_flags)) { |
610 | set_bit(GLF_REVOKES, &gl->gl_flags); | ||
610 | gfs2_glock_hold(gl); | 611 | gfs2_glock_hold(gl); |
612 | } | ||
611 | set_bit(GLF_LFLUSH, &gl->gl_flags); | 613 | set_bit(GLF_LFLUSH, &gl->gl_flags); |
612 | list_add(&bd->bd_list, &sdp->sd_log_le_revoke); | 614 | list_add(&bd->bd_list, &sdp->sd_log_le_revoke); |
613 | } | 615 | } |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index b4f0a6a3ba59..2fd61853ba63 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -662,19 +662,34 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
662 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 662 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
663 | { | 663 | { |
664 | struct list_head *head = &sdp->sd_log_le_revoke; | 664 | struct list_head *head = &sdp->sd_log_le_revoke; |
665 | struct gfs2_bufdata *bd; | 665 | struct gfs2_bufdata *bd, *tmp; |
666 | struct gfs2_glock *gl; | ||
667 | 666 | ||
668 | while (!list_empty(head)) { | 667 | /* |
669 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); | 668 | * Glocks can be referenced repeatedly on the revoke list, but the list |
670 | list_del_init(&bd->bd_list); | 669 | * only holds one reference. All glocks on the list will have the |
671 | gl = bd->bd_gl; | 670 | * GLF_REVOKES flag set initially. |
672 | if (atomic_dec_return(&gl->gl_revokes) == 0) { | 671 | */ |
673 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | 672 | |
674 | gfs2_glock_queue_put(gl); | 673 | list_for_each_entry_safe(bd, tmp, head, bd_list) { |
674 | struct gfs2_glock *gl = bd->bd_gl; | ||
675 | |||
676 | if (test_bit(GLF_REVOKES, &gl->gl_flags)) { | ||
677 | /* Keep each glock on the list exactly once. */ | ||
678 | clear_bit(GLF_REVOKES, &gl->gl_flags); | ||
679 | continue; | ||
675 | } | 680 | } |
681 | list_del(&bd->bd_list); | ||
682 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
683 | } | ||
684 | list_for_each_entry_safe(bd, tmp, head, bd_list) { | ||
685 | struct gfs2_glock *gl = bd->bd_gl; | ||
686 | |||
687 | list_del(&bd->bd_list); | ||
676 | kmem_cache_free(gfs2_bufdata_cachep, bd); | 688 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
689 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
690 | gfs2_glock_queue_put(gl); | ||
677 | } | 691 | } |
692 | /* the list is empty now */ | ||
678 | } | 693 | } |
679 | 694 | ||
680 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, | 695 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 136484ef35d3..c700738de1f7 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -59,7 +59,6 @@ static void gfs2_init_glock_once(void *foo) | |||
59 | INIT_LIST_HEAD(&gl->gl_lru); | 59 | INIT_LIST_HEAD(&gl->gl_lru); |
60 | INIT_LIST_HEAD(&gl->gl_ail_list); | 60 | INIT_LIST_HEAD(&gl->gl_ail_list); |
61 | atomic_set(&gl->gl_ail_count, 0); | 61 | atomic_set(&gl->gl_ail_count, 0); |
62 | atomic_set(&gl->gl_revokes, 0); | ||
63 | } | 62 | } |
64 | 63 | ||
65 | static void gfs2_init_gl_aspace_once(void *foo) | 64 | static void gfs2_init_gl_aspace_once(void *foo) |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 7b8d2306b3d3..2a7692d70394 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1474,7 +1474,7 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip) | |||
1474 | truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0); | 1474 | truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0); |
1475 | truncate_inode_pages(&inode->i_data, 0); | 1475 | truncate_inode_pages(&inode->i_data, 0); |
1476 | 1476 | ||
1477 | if (atomic_read(&gl->gl_revokes) == 0) { | 1477 | if (!test_bit(GLF_REVOKES, &gl->gl_flags)) { |
1478 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | 1478 | clear_bit(GLF_LFLUSH, &gl->gl_flags); |
1479 | clear_bit(GLF_DIRTY, &gl->gl_flags); | 1479 | clear_bit(GLF_DIRTY, &gl->gl_flags); |
1480 | } | 1480 | } |