diff options
author | Bob Peterson <rpeterso@redhat.com> | 2019-06-06 08:33:38 -0400 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2019-06-06 10:29:26 -0400 |
commit | 638803d4568121d73a266e440530f880ffa2dacc (patch) | |
tree | 79e35d2f48a94513f50de1995c4a3cb88dc7769d /fs/gfs2 | |
parent | f2c7c76c5d0a443053e94adb9f0918fa2fb85c3a (diff) |
Revert "gfs2: Replace gl_revokes with a GLF flag"
Commit 73118ca8baf7 introduced a glock reference counting bug in
gfs2_trans_remove_revoke. Given that, replacing gl_revokes with a GLF flag is
no longer useful, so revert that commit.
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, 15 insertions, 31 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 15c605cfcfc8..71c28ff98b56 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(test_bit(GLF_REVOKES, &gl->gl_flags)); | 143 | BUG_ON(atomic_read(&gl->gl_revokes)); |
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 | test_bit(GLF_REVOKES, &gl->gl_flags) ? 1 : 0, | 1804 | atomic_read(&gl->gl_revokes), |
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 b15755068593..1d35e0da0ef8 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -345,7 +345,6 @@ 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 */ | ||
349 | }; | 348 | }; |
350 | 349 | ||
351 | struct gfs2_glock { | 350 | struct gfs2_glock { |
@@ -375,6 +374,7 @@ struct gfs2_glock { | |||
375 | struct list_head gl_lru; | 374 | struct list_head gl_lru; |
376 | struct list_head gl_ail_list; | 375 | struct list_head gl_ail_list; |
377 | atomic_t gl_ail_count; | 376 | 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 a2e1df488df0..86703c95353e 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -606,10 +606,8 @@ 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 (!test_bit(GLF_REVOKES, &gl->gl_flags)) { | 609 | if (atomic_inc_return(&gl->gl_revokes) == 1) |
610 | set_bit(GLF_REVOKES, &gl->gl_flags); | ||
611 | gfs2_glock_hold(gl); | 610 | gfs2_glock_hold(gl); |
612 | } | ||
613 | set_bit(GLF_LFLUSH, &gl->gl_flags); | 611 | set_bit(GLF_LFLUSH, &gl->gl_flags); |
614 | list_add(&bd->bd_list, &sdp->sd_log_revokes); | 612 | list_add(&bd->bd_list, &sdp->sd_log_revokes); |
615 | } | 613 | } |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 33ab662c9aac..bb0e5b8e445e 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -860,34 +860,19 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
860 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 860 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
861 | { | 861 | { |
862 | struct list_head *head = &sdp->sd_log_revokes; | 862 | struct list_head *head = &sdp->sd_log_revokes; |
863 | struct gfs2_bufdata *bd, *tmp; | 863 | struct gfs2_bufdata *bd; |
864 | 864 | struct gfs2_glock *gl; | |
865 | /* | ||
866 | * Glocks can be referenced repeatedly on the revoke list, but the list | ||
867 | * only holds one reference. All glocks on the list will have the | ||
868 | * GLF_REVOKES flag set initially. | ||
869 | */ | ||
870 | |||
871 | list_for_each_entry_safe(bd, tmp, head, bd_list) { | ||
872 | struct gfs2_glock *gl = bd->bd_gl; | ||
873 | 865 | ||
874 | if (test_bit(GLF_REVOKES, &gl->gl_flags)) { | 866 | while (!list_empty(head)) { |
875 | /* Keep each glock on the list exactly once. */ | 867 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); |
876 | clear_bit(GLF_REVOKES, &gl->gl_flags); | 868 | list_del_init(&bd->bd_list); |
877 | continue; | 869 | gl = bd->bd_gl; |
870 | if (atomic_dec_return(&gl->gl_revokes) == 0) { | ||
871 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
872 | gfs2_glock_queue_put(gl); | ||
878 | } | 873 | } |
879 | list_del(&bd->bd_list); | ||
880 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
881 | } | ||
882 | list_for_each_entry_safe(bd, tmp, head, bd_list) { | ||
883 | struct gfs2_glock *gl = bd->bd_gl; | ||
884 | |||
885 | list_del(&bd->bd_list); | ||
886 | kmem_cache_free(gfs2_bufdata_cachep, bd); | 874 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
887 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
888 | gfs2_glock_queue_put(gl); | ||
889 | } | 875 | } |
890 | /* the list is empty now */ | ||
891 | } | 876 | } |
892 | 877 | ||
893 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, | 878 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index c700738de1f7..136484ef35d3 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -59,6 +59,7 @@ 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); | ||
62 | } | 63 | } |
63 | 64 | ||
64 | static void gfs2_init_gl_aspace_once(void *foo) | 65 | static void gfs2_init_gl_aspace_once(void *foo) |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index fbf6b1fd330b..2aa4dd050f3d 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1477,7 +1477,7 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip) | |||
1477 | truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0); | 1477 | truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0); |
1478 | truncate_inode_pages(&inode->i_data, 0); | 1478 | truncate_inode_pages(&inode->i_data, 0); |
1479 | 1479 | ||
1480 | if (!test_bit(GLF_REVOKES, &gl->gl_flags)) { | 1480 | if (atomic_read(&gl->gl_revokes) == 0) { |
1481 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | 1481 | clear_bit(GLF_LFLUSH, &gl->gl_flags); |
1482 | clear_bit(GLF_DIRTY, &gl->gl_flags); | 1482 | clear_bit(GLF_DIRTY, &gl->gl_flags); |
1483 | } | 1483 | } |