aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2014-05-01 23:26:55 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2014-05-14 05:04:34 -0400
commit24972557b12ce8fd5b6c6847d0e2ee1837ddc13b (patch)
treefb82edff8bfab9d4d1c4df6dd7784dd3c9f85c1b /fs/gfs2/log.c
parent5a7c6690c2759d686d2c299402327e92ed92ab6c (diff)
GFS2: remove transaction glock
GFS2 has a transaction glock, which must be grabbed for every transaction, whose purpose is to deal with freezing the filesystem. Aside from this involving a large amount of locking, it is very easy to make the current fsfreeze code hang on unfreezing. This patch rewrites how gfs2 handles freezing the filesystem. The transaction glock is removed. In it's place is a freeze glock, which is cached (but not held) in a shared state by every node in the cluster when the filesystem is mounted. This lock only needs to be grabbed on freezing, and actions which need to be safe from freezing, like recovery. When a node wants to freeze the filesystem, it grabs this glock exclusively. When the freeze glock state changes on the nodes (either from shared to unlocked, or shared to exclusive), the filesystem does a special log flush. gfs2_log_flush() does all the work for flushing out the and shutting down the incore log, and then it tries to grab the freeze glock in a shared state again. Since the filesystem is stuck in gfs2_log_flush, no new transaction can start, and nothing can be written to disk. Unfreezing the filesytem simply involes dropping the freeze glock, allowing gfs2_log_flush() to grab and then release the shared lock, so it is cached for next time. However, in order for the unfreezing ioctl to occur, gfs2 needs to get a shared lock on the filesystem root directory inode to check permissions. If that glock has already been grabbed exclusively, fsfreeze will be unable to get the shared lock and unfreeze the filesystem. In order to allow the unfreeze, this patch makes gfs2 grab a shared lock on the filesystem root directory during the freeze, and hold it until it unfreezes the filesystem. The functions which need to grab a shared lock in order to allow the unfreeze ioctl to be issued now use the lock grabbed by the freeze code instead. The freeze and unfreeze code take care to make sure that this shared lock will not be dropped while another process is using it. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 4a14d504ef83..3966fadbcebd 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -301,6 +301,23 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
301} 301}
302 302
303/** 303/**
304 * gfs2_log_release - Release a given number of log blocks
305 * @sdp: The GFS2 superblock
306 * @blks: The number of blocks
307 *
308 */
309
310void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
311{
312
313 atomic_add(blks, &sdp->sd_log_blks_free);
314 trace_gfs2_log_blocks(sdp, blks);
315 gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
316 sdp->sd_jdesc->jd_blocks);
317 up_read(&sdp->sd_log_flush_lock);
318}
319
320/**
304 * gfs2_log_reserve - Make a log reservation 321 * gfs2_log_reserve - Make a log reservation
305 * @sdp: The GFS2 superblock 322 * @sdp: The GFS2 superblock
306 * @blks: The number of blocks to reserve 323 * @blks: The number of blocks to reserve
@@ -358,7 +375,10 @@ retry:
358 wake_up(&sdp->sd_log_waitq); 375 wake_up(&sdp->sd_log_waitq);
359 376
360 down_read(&sdp->sd_log_flush_lock); 377 down_read(&sdp->sd_log_flush_lock);
361 378 if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) {
379 gfs2_log_release(sdp, blks);
380 return -EROFS;
381 }
362 return 0; 382 return 0;
363} 383}
364 384
@@ -671,7 +691,8 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
671 * 691 *
672 */ 692 */
673 693
674void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) 694void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
695 enum gfs2_flush_type type)
675{ 696{
676 struct gfs2_trans *tr; 697 struct gfs2_trans *tr;
677 698
@@ -723,6 +744,42 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
723 } 744 }
724 spin_unlock(&sdp->sd_ail_lock); 745 spin_unlock(&sdp->sd_ail_lock);
725 gfs2_log_unlock(sdp); 746 gfs2_log_unlock(sdp);
747
748 if (atomic_read(&sdp->sd_log_freeze))
749 type = FREEZE_FLUSH;
750 if (type != NORMAL_FLUSH) {
751 if (!sdp->sd_log_idle) {
752 for (;;) {
753 gfs2_ail1_start(sdp);
754 gfs2_ail1_wait(sdp);
755 if (gfs2_ail1_empty(sdp))
756 break;
757 }
758 atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
759 trace_gfs2_log_blocks(sdp, -1);
760 sdp->sd_log_flush_wrapped = 0;
761 log_write_header(sdp, 0);
762 sdp->sd_log_head = sdp->sd_log_flush_head;
763 }
764 if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH)
765 gfs2_log_shutdown(sdp);
766 if (type == FREEZE_FLUSH) {
767 int error;
768
769 atomic_set(&sdp->sd_log_freeze, 0);
770 wake_up(&sdp->sd_log_frozen_wait);
771 error = gfs2_glock_nq_init(sdp->sd_freeze_gl,
772 LM_ST_SHARED, 0,
773 &sdp->sd_thaw_gh);
774 if (error) {
775 printk(KERN_INFO "GFS2: couln't get freeze lock : %d\n", error);
776 gfs2_assert_withdraw(sdp, 0);
777 }
778 else
779 gfs2_glock_dq_uninit(&sdp->sd_thaw_gh);
780 }
781 }
782
726 trace_gfs2_log_flush(sdp, 0); 783 trace_gfs2_log_flush(sdp, 0);
727 up_write(&sdp->sd_log_flush_lock); 784 up_write(&sdp->sd_log_flush_lock);
728 785
@@ -761,7 +818,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
761 if (sdp->sd_log_tr) { 818 if (sdp->sd_log_tr) {
762 gfs2_merge_trans(sdp->sd_log_tr, tr); 819 gfs2_merge_trans(sdp->sd_log_tr, tr);
763 } else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) { 820 } else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) {
764 gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl); 821 gfs2_assert_withdraw(sdp, tr->tr_alloced);
765 sdp->sd_log_tr = tr; 822 sdp->sd_log_tr = tr;
766 tr->tr_attached = 1; 823 tr->tr_attached = 1;
767 } 824 }
@@ -813,8 +870,6 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
813 870
814void gfs2_log_shutdown(struct gfs2_sbd *sdp) 871void gfs2_log_shutdown(struct gfs2_sbd *sdp)
815{ 872{
816 down_write(&sdp->sd_log_flush_lock);
817
818 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); 873 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
819 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); 874 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
820 gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); 875 gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
@@ -824,38 +879,16 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
824 879
825 log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT); 880 log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT);
826 881
827 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
828 gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); 882 gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
829 gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list)); 883 gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
830 884
831 sdp->sd_log_head = sdp->sd_log_flush_head; 885 sdp->sd_log_head = sdp->sd_log_flush_head;
832 sdp->sd_log_tail = sdp->sd_log_head; 886 sdp->sd_log_tail = sdp->sd_log_head;
833
834 up_write(&sdp->sd_log_flush_lock);
835}
836
837
838/**
839 * gfs2_meta_syncfs - sync all the buffers in a filesystem
840 * @sdp: the filesystem
841 *
842 */
843
844void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
845{
846 gfs2_log_flush(sdp, NULL);
847 for (;;) {
848 gfs2_ail1_start(sdp);
849 gfs2_ail1_wait(sdp);
850 if (gfs2_ail1_empty(sdp))
851 break;
852 }
853 gfs2_log_flush(sdp, NULL);
854} 887}
855 888
856static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) 889static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp)
857{ 890{
858 return (atomic_read(&sdp->sd_log_pinned) >= atomic_read(&sdp->sd_log_thresh1)); 891 return (atomic_read(&sdp->sd_log_pinned) >= atomic_read(&sdp->sd_log_thresh1) || atomic_read(&sdp->sd_log_freeze));
859} 892}
860 893
861static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp) 894static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp)
@@ -882,14 +915,14 @@ int gfs2_logd(void *data)
882 915
883 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { 916 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
884 gfs2_ail1_empty(sdp); 917 gfs2_ail1_empty(sdp);
885 gfs2_log_flush(sdp, NULL); 918 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
886 } 919 }
887 920
888 if (gfs2_ail_flush_reqd(sdp)) { 921 if (gfs2_ail_flush_reqd(sdp)) {
889 gfs2_ail1_start(sdp); 922 gfs2_ail1_start(sdp);
890 gfs2_ail1_wait(sdp); 923 gfs2_ail1_wait(sdp);
891 gfs2_ail1_empty(sdp); 924 gfs2_ail1_empty(sdp);
892 gfs2_log_flush(sdp, NULL); 925 gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
893 } 926 }
894 927
895 if (!gfs2_ail_flush_reqd(sdp)) 928 if (!gfs2_ail_flush_reqd(sdp))