aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2014-11-13 21:42:04 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2014-11-17 05:36:39 -0500
commit2e60d7683c8d2ea21317f6d9f4cd3bf5428ce162 (patch)
treefc7900ad18814d1ea46879f93eab063ff5754d1e /fs/gfs2
parent48b6bca6b7b8309697fc8a101793befe92d249d9 (diff)
GFS2: update freeze code to use freeze/thaw_super on all nodes
The current gfs2 freezing code is considerably more complicated than it should be because it doesn't use the vfs freezing code on any node except the one that begins the freeze. This is because it needs to acquire a cluster glock before calling the vfs code to prevent a deadlock, and without the new freeze_super and thaw_super hooks, that was impossible. To deal with the issue, gfs2 had to do some hacky locking tricks to make sure that a frozen node couldn't be holding on a lock it needed to do the unfreeze ioctl. This patch makes use of the new hooks to simply the gfs2 locking code. Now, all the nodes in the cluster freeze and thaw in exactly the same way. Every node in the cluster caches the freeze glock in the shared state. The new freeze_super hook allows the freezing node to grab this freeze glock in the exclusive state without first calling the vfs freeze_super function. All the nodes in the cluster see this lock change, and call the vfs freeze_super function. The vfs locking code guarantees that the nodes can't get stuck holding the glocks necessary to unfreeze the system. To unfreeze, the freezing node uses the new thaw_super hook to drop the freeze glock. Again, all the nodes notice this, reacquire the glock in shared mode and call the vfs thaw_super function. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/glops.c26
-rw-r--r--fs/gfs2/glops.h2
-rw-r--r--fs/gfs2/incore.h18
-rw-r--r--fs/gfs2/inode.c40
-rw-r--r--fs/gfs2/log.c42
-rw-r--r--fs/gfs2/main.c11
-rw-r--r--fs/gfs2/ops_fstype.c18
-rw-r--r--fs/gfs2/super.c112
-rw-r--r--fs/gfs2/super.h1
-rw-r--r--fs/gfs2/trans.c17
10 files changed, 161 insertions, 126 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 1cc0bba6313f..fe91951c3361 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -28,6 +28,8 @@
28#include "trans.h" 28#include "trans.h"
29#include "dir.h" 29#include "dir.h"
30 30
31struct workqueue_struct *gfs2_freeze_wq;
32
31static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) 33static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
32{ 34{
33 fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n", 35 fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n",
@@ -94,11 +96,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
94 * on the stack */ 96 * on the stack */
95 tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); 97 tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64));
96 tr.tr_ip = _RET_IP_; 98 tr.tr_ip = _RET_IP_;
97 sb_start_intwrite(sdp->sd_vfs); 99 if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0)
98 if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0) {
99 sb_end_intwrite(sdp->sd_vfs);
100 return; 100 return;
101 }
102 WARN_ON_ONCE(current->journal_info); 101 WARN_ON_ONCE(current->journal_info);
103 current->journal_info = &tr; 102 current->journal_info = &tr;
104 103
@@ -469,20 +468,19 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
469 468
470static void freeze_go_sync(struct gfs2_glock *gl) 469static void freeze_go_sync(struct gfs2_glock *gl)
471{ 470{
471 int error = 0;
472 struct gfs2_sbd *sdp = gl->gl_sbd; 472 struct gfs2_sbd *sdp = gl->gl_sbd;
473 DEFINE_WAIT(wait);
474 473
475 if (gl->gl_state == LM_ST_SHARED && 474 if (gl->gl_state == LM_ST_SHARED &&
476 test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { 475 test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
477 atomic_set(&sdp->sd_log_freeze, 1); 476 atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
478 wake_up(&sdp->sd_logd_waitq); 477 error = freeze_super(sdp->sd_vfs);
479 do { 478 if (error) {
480 prepare_to_wait(&sdp->sd_log_frozen_wait, &wait, 479 printk(KERN_INFO "GFS2: couldn't freeze filesystem: %d\n", error);
481 TASK_UNINTERRUPTIBLE); 480 gfs2_assert_withdraw(sdp, 0);
482 if (atomic_read(&sdp->sd_log_freeze)) 481 }
483 io_schedule(); 482 queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
484 } while(atomic_read(&sdp->sd_log_freeze)); 483 gfs2_log_flush(sdp, NULL, FREEZE_FLUSH);
485 finish_wait(&sdp->sd_log_frozen_wait, &wait);
486 } 484 }
487} 485}
488 486
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h
index 7455d2629bcb..8ed1857c1a8d 100644
--- a/fs/gfs2/glops.h
+++ b/fs/gfs2/glops.h
@@ -12,6 +12,8 @@
12 12
13#include "incore.h" 13#include "incore.h"
14 14
15extern struct workqueue_struct *gfs2_freeze_wq;
16
15extern const struct gfs2_glock_operations gfs2_meta_glops; 17extern const struct gfs2_glock_operations gfs2_meta_glops;
16extern const struct gfs2_glock_operations gfs2_inode_glops; 18extern const struct gfs2_glock_operations gfs2_inode_glops;
17extern const struct gfs2_glock_operations gfs2_rgrp_glops; 19extern const struct gfs2_glock_operations gfs2_rgrp_glops;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 1b899187be5a..7a2dbbc0d634 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -588,6 +588,12 @@ enum {
588 SDF_SKIP_DLM_UNLOCK = 8, 588 SDF_SKIP_DLM_UNLOCK = 8,
589}; 589};
590 590
591enum gfs2_freeze_state {
592 SFS_UNFROZEN = 0,
593 SFS_STARTING_FREEZE = 1,
594 SFS_FROZEN = 2,
595};
596
591#define GFS2_FSNAME_LEN 256 597#define GFS2_FSNAME_LEN 256
592 598
593struct gfs2_inum_host { 599struct gfs2_inum_host {
@@ -685,6 +691,7 @@ struct gfs2_sbd {
685 struct gfs2_holder sd_live_gh; 691 struct gfs2_holder sd_live_gh;
686 struct gfs2_glock *sd_rename_gl; 692 struct gfs2_glock *sd_rename_gl;
687 struct gfs2_glock *sd_freeze_gl; 693 struct gfs2_glock *sd_freeze_gl;
694 struct work_struct sd_freeze_work;
688 wait_queue_head_t sd_glock_wait; 695 wait_queue_head_t sd_glock_wait;
689 atomic_t sd_glock_disposal; 696 atomic_t sd_glock_disposal;
690 struct completion sd_locking_init; 697 struct completion sd_locking_init;
@@ -789,6 +796,9 @@ struct gfs2_sbd {
789 wait_queue_head_t sd_log_flush_wait; 796 wait_queue_head_t sd_log_flush_wait;
790 int sd_log_error; 797 int sd_log_error;
791 798
799 atomic_t sd_reserving_log;
800 wait_queue_head_t sd_reserving_log_wait;
801
792 unsigned int sd_log_flush_head; 802 unsigned int sd_log_flush_head;
793 u64 sd_log_flush_wrapped; 803 u64 sd_log_flush_wrapped;
794 804
@@ -798,12 +808,8 @@ struct gfs2_sbd {
798 808
799 /* For quiescing the filesystem */ 809 /* For quiescing the filesystem */
800 struct gfs2_holder sd_freeze_gh; 810 struct gfs2_holder sd_freeze_gh;
801 struct gfs2_holder sd_freeze_root_gh; 811 atomic_t sd_freeze_state;
802 struct gfs2_holder sd_thaw_gh; 812 struct mutex sd_freeze_mutex;
803 atomic_t sd_log_freeze;
804 atomic_t sd_frozen_root;
805 wait_queue_head_t sd_frozen_root_wait;
806 wait_queue_head_t sd_log_frozen_wait;
807 813
808 char sd_fsname[GFS2_FSNAME_LEN]; 814 char sd_fsname[GFS2_FSNAME_LEN];
809 char sd_table_name[GFS2_FSNAME_LEN]; 815 char sd_table_name[GFS2_FSNAME_LEN];
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index b41b5c7898da..04065e5af4b6 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1618,26 +1618,18 @@ int gfs2_permission(struct inode *inode, int mask)
1618{ 1618{
1619 struct gfs2_inode *ip; 1619 struct gfs2_inode *ip;
1620 struct gfs2_holder i_gh; 1620 struct gfs2_holder i_gh;
1621 struct gfs2_sbd *sdp = GFS2_SB(inode);
1622 int error; 1621 int error;
1623 int unlock = 0; 1622 int unlock = 0;
1624 int frozen_root = 0;
1625 1623
1626 1624
1627 ip = GFS2_I(inode); 1625 ip = GFS2_I(inode);
1628 if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { 1626 if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
1629 if (unlikely(gfs2_glock_is_held_excl(sdp->sd_freeze_gl) && 1627 if (mask & MAY_NOT_BLOCK)
1630 inode == sdp->sd_root_dir->d_inode && 1628 return -ECHILD;
1631 atomic_inc_not_zero(&sdp->sd_frozen_root))) 1629 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
1632 frozen_root = 1; 1630 if (error)
1633 else { 1631 return error;
1634 if (mask & MAY_NOT_BLOCK) 1632 unlock = 1;
1635 return -ECHILD;
1636 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
1637 if (error)
1638 return error;
1639 unlock = 1;
1640 }
1641 } 1633 }
1642 1634
1643 if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) 1635 if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
@@ -1646,8 +1638,6 @@ int gfs2_permission(struct inode *inode, int mask)
1646 error = generic_permission(inode, mask); 1638 error = generic_permission(inode, mask);
1647 if (unlock) 1639 if (unlock)
1648 gfs2_glock_dq_uninit(&i_gh); 1640 gfs2_glock_dq_uninit(&i_gh);
1649 else if (frozen_root && atomic_dec_and_test(&sdp->sd_frozen_root))
1650 wake_up(&sdp->sd_frozen_root_wait);
1651 1641
1652 return error; 1642 return error;
1653} 1643}
@@ -1820,29 +1810,19 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
1820 struct inode *inode = dentry->d_inode; 1810 struct inode *inode = dentry->d_inode;