diff options
| -rw-r--r-- | fs/gfs2/glops.c | 26 | ||||
| -rw-r--r-- | fs/gfs2/glops.h | 2 | ||||
| -rw-r--r-- | fs/gfs2/incore.h | 18 | ||||
| -rw-r--r-- | fs/gfs2/inode.c | 40 | ||||
| -rw-r--r-- | fs/gfs2/log.c | 42 | ||||
| -rw-r--r-- | fs/gfs2/main.c | 11 | ||||
| -rw-r--r-- | fs/gfs2/ops_fstype.c | 18 | ||||
| -rw-r--r-- | fs/gfs2/super.c | 112 | ||||
| -rw-r--r-- | fs/gfs2/super.h | 1 | ||||
| -rw-r--r-- | fs/gfs2/trans.c | 17 |
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 | ||
| 31 | struct workqueue_struct *gfs2_freeze_wq; | ||
| 32 | |||
| 31 | static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) | 33 | static 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 | ||
| 470 | static void freeze_go_sync(struct gfs2_glock *gl) | 469 | static 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 | ||
| 15 | extern struct workqueue_struct *gfs2_freeze_wq; | ||
| 16 | |||
| 15 | extern const struct gfs2_glock_operations gfs2_meta_glops; | 17 | extern const struct gfs2_glock_operations gfs2_meta_glops; |
| 16 | extern const struct gfs2_glock_operations gfs2_inode_glops; | 18 | extern const struct gfs2_glock_operations gfs2_inode_glops; |
| 17 | extern const struct gfs2_glock_operations gfs2_rgrp_glops; | 19 | extern 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 | ||
| 591 | enum 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 | ||
| 593 | struct gfs2_inum_host { | 599 | struct 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; |
| 1821 | struct gfs2_inode *ip = GFS2_I(inode); | 1811 | struct gfs2_inode *ip = GFS2_I(inode); |
| 1822 | struct gfs2_holder gh; | 1812 | struct gfs2_holder gh; |
| 1823 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 1824 | int error; | 1813 | int error; |
| 1825 | int unlock = 0; | 1814 | int unlock = 0; |
| 1826 | int frozen_root = 0; | ||
| 1827 | 1815 | ||
| 1828 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | 1816 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
| 1829 | if (unlikely(gfs2_glock_is_held_excl(sdp->sd_freeze_gl) && | 1817 | |
