diff options
-rw-r--r-- | fs/gfs2/aops.c | 2 | ||||
-rw-r--r-- | fs/gfs2/file.c | 2 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 51 | ||||
-rw-r--r-- | fs/gfs2/glops.h | 2 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 12 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 40 | ||||
-rw-r--r-- | fs/gfs2/log.c | 93 | ||||
-rw-r--r-- | fs/gfs2/log.h | 11 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 22 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 2 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 22 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 2 | ||||
-rw-r--r-- | fs/gfs2/super.c | 69 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 4 | ||||
-rw-r--r-- | fs/gfs2/trans.c | 44 | ||||
-rw-r--r-- | include/uapi/linux/gfs2_ondisk.h | 2 |
16 files changed, 227 insertions, 153 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index ce62dcac90b6..5a49b037da81 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -431,7 +431,7 @@ static int gfs2_jdata_writepages(struct address_space *mapping, | |||
431 | 431 | ||
432 | ret = gfs2_write_cache_jdata(mapping, wbc); | 432 | ret = gfs2_write_cache_jdata(mapping, wbc); |
433 | if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) { | 433 | if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) { |
434 | gfs2_log_flush(sdp, ip->i_gl); | 434 | gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); |
435 | ret = gfs2_write_cache_jdata(mapping, wbc); | 435 | ret = gfs2_write_cache_jdata(mapping, wbc); |
436 | } | 436 | } |
437 | return ret; | 437 | return ret; |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 80d67253623c..606525215acc 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -256,7 +256,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) | |||
256 | } | 256 | } |
257 | if ((flags ^ new_flags) & GFS2_DIF_JDATA) { | 257 | if ((flags ^ new_flags) & GFS2_DIF_JDATA) { |
258 | if (flags & GFS2_DIF_JDATA) | 258 | if (flags & GFS2_DIF_JDATA) |
259 | gfs2_log_flush(sdp, ip->i_gl); | 259 | gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); |
260 | error = filemap_fdatawrite(inode->i_mapping); | 260 | error = filemap_fdatawrite(inode->i_mapping); |
261 | if (error) | 261 | if (error) |
262 | goto out; | 262 | goto out; |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 54b66809e818..0b527939c46f 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -89,18 +89,23 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
89 | if (!tr.tr_revokes) | 89 | if (!tr.tr_revokes) |
90 | return; | 90 | return; |
91 | 91 | ||
92 | /* A shortened, inline version of gfs2_trans_begin() */ | 92 | /* A shortened, inline version of gfs2_trans_begin() |
93 | * tr->alloced is not set since the transaction structure is | ||
94 | * on the stack */ | ||
93 | tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); | 95 | tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); |
94 | tr.tr_ip = (unsigned long)__builtin_return_address(0); | 96 | tr.tr_ip = (unsigned long)__builtin_return_address(0); |
95 | sb_start_intwrite(sdp->sd_vfs); | 97 | sb_start_intwrite(sdp->sd_vfs); |
96 | gfs2_log_reserve(sdp, tr.tr_reserved); | 98 | if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0) { |
99 | sb_end_intwrite(sdp->sd_vfs); | ||
100 | return; | ||
101 | } | ||
97 | WARN_ON_ONCE(current->journal_info); | 102 | WARN_ON_ONCE(current->journal_info); |
98 | current->journal_info = &tr; | 103 | current->journal_info = &tr; |
99 | 104 | ||
100 | __gfs2_ail_flush(gl, 0, tr.tr_revokes); | 105 | __gfs2_ail_flush(gl, 0, tr.tr_revokes); |
101 | 106 | ||
102 | gfs2_trans_end(sdp); | 107 | gfs2_trans_end(sdp); |
103 | gfs2_log_flush(sdp, NULL); | 108 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
104 | } | 109 | } |
105 | 110 | ||
106 | void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | 111 | void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) |
@@ -121,7 +126,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | |||
121 | return; | 126 | return; |
122 | __gfs2_ail_flush(gl, fsync, max_revokes); | 127 | __gfs2_ail_flush(gl, fsync, max_revokes); |
123 | gfs2_trans_end(sdp); | 128 | gfs2_trans_end(sdp); |
124 | gfs2_log_flush(sdp, NULL); | 129 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
125 | } | 130 | } |
126 | 131 | ||
127 | /** | 132 | /** |
@@ -144,7 +149,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl) | |||
144 | return; | 149 | return; |
145 | GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); | 150 | GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); |
146 | 151 | ||
147 | gfs2_log_flush(sdp, gl); | 152 | gfs2_log_flush(sdp, gl, NORMAL_FLUSH); |
148 | filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end); | 153 | filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end); |
149 | error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end); | 154 | error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end); |
150 | mapping_set_error(mapping, error); | 155 | mapping_set_error(mapping, error); |
@@ -206,7 +211,7 @@ static void inode_go_sync(struct gfs2_glock *gl) | |||
206 | 211 | ||
207 | GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); | 212 | GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); |
208 | 213 | ||
209 | gfs2_log_flush(gl->gl_sbd, gl); | 214 | gfs2_log_flush(gl->gl_sbd, gl, NORMAL_FLUSH); |
210 | filemap_fdatawrite(metamapping); | 215 | filemap_fdatawrite(metamapping); |
211 | if (ip) { | 216 | if (ip) { |
212 | struct address_space *mapping = ip->i_inode.i_mapping; | 217 | struct address_space *mapping = ip->i_inode.i_mapping; |
@@ -253,7 +258,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
253 | } | 258 | } |
254 | 259 | ||
255 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) { | 260 | if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) { |
256 | gfs2_log_flush(gl->gl_sbd, NULL); | 261 | gfs2_log_flush(gl->gl_sbd, NULL, NORMAL_FLUSH); |
257 | gl->gl_sbd->sd_rindex_uptodate = 0; | 262 | gl->gl_sbd->sd_rindex_uptodate = 0; |
258 | } | 263 | } |
259 | if (ip && S_ISREG(ip->i_inode.i_mode)) | 264 | if (ip && S_ISREG(ip->i_inode.i_mode)) |
@@ -455,31 +460,39 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
455 | } | 460 | } |
456 | 461 | ||
457 | /** | 462 | /** |
458 | * trans_go_sync - promote/demote the transaction glock | 463 | * freeze_go_sync - promote/demote the freeze glock |
459 | * @gl: the glock | 464 | * @gl: the glock |
460 | * @state: the requested state | 465 | * @state: the requested state |
461 | * @flags: | 466 | * @flags: |
462 | * | 467 | * |
463 | */ | 468 | */ |
464 | 469 | ||
465 | static void trans_go_sync(struct gfs2_glock *gl) | 470 | static void freeze_go_sync(struct gfs2_glock *gl) |
466 | { | 471 | { |
467 | struct gfs2_sbd *sdp = gl->gl_sbd; | 472 | struct gfs2_sbd *sdp = gl->gl_sbd; |
473 | DEFINE_WAIT(wait); | ||
468 | 474 | ||
469 | if (gl->gl_state != LM_ST_UNLOCKED && | 475 | if (gl->gl_state == LM_ST_SHARED && |
470 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { | 476 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
471 | gfs2_meta_syncfs(sdp); | 477 | atomic_set(&sdp->sd_log_freeze, 1); |
472 | gfs2_log_shutdown(sdp); | 478 | wake_up(&sdp->sd_logd_waitq); |
479 | do { | ||
480 | prepare_to_wait(&sdp->sd_log_frozen_wait, &wait, | ||
481 | TASK_UNINTERRUPTIBLE); | ||
482 | if (atomic_read(&sdp->sd_log_freeze)) | ||
483 | io_schedule(); | ||
484 | } while(atomic_read(&sdp->sd_log_freeze)); | ||
485 | finish_wait(&sdp->sd_log_frozen_wait, &wait); | ||
473 | } | 486 | } |
474 | } | 487 | } |
475 | 488 | ||
476 | /** | 489 | /** |
477 | * trans_go_xmote_bh - After promoting/demoting the transaction glock | 490 | * freeze_go_xmote_bh - After promoting/demoting the freeze glock |
478 | * @gl: the glock | 491 | * @gl: the glock |
479 | * | 492 | * |
480 | */ | 493 | */ |
481 | 494 | ||
482 | static int trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) | 495 | static int freeze_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) |
483 | { | 496 | { |
484 | struct gfs2_sbd *sdp = gl->gl_sbd; | 497 | struct gfs2_sbd *sdp = gl->gl_sbd; |
485 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); | 498 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); |
@@ -512,7 +525,7 @@ static int trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) | |||
512 | * Always returns 0 | 525 | * Always returns 0 |
513 | */ | 526 | */ |
514 | 527 | ||
515 | static int trans_go_demote_ok(const struct gfs2_glock *gl) | 528 | static int freeze_go_demote_ok(const struct gfs2_glock *gl) |
516 | { | 529 | { |
517 | return 0; | 530 | return 0; |
518 | } | 531 | } |
@@ -563,10 +576,10 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { | |||
563 | .go_flags = GLOF_LVB, | 576 | .go_flags = GLOF_LVB, |
564 | }; | 577 | }; |
565 | 578 | ||
566 | const struct gfs2_glock_operations gfs2_trans_glops = { | 579 | const struct gfs2_glock_operations gfs2_freeze_glops = { |
567 | .go_sync = trans_go_sync, | 580 | .go_sync = freeze_go_sync, |
568 | .go_xmote_bh = trans_go_xmote_bh, | 581 | .go_xmote_bh = freeze_go_xmote_bh, |
569 | .go_demote_ok = trans_go_demote_ok, | 582 | .go_demote_ok = freeze_go_demote_ok, |
570 | .go_type = LM_TYPE_NONDISK, | 583 | .go_type = LM_TYPE_NONDISK, |
571 | }; | 584 | }; |
572 | 585 | ||
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h index bf95a2dc1662..7455d2629bcb 100644 --- a/fs/gfs2/glops.h +++ b/fs/gfs2/glops.h | |||
@@ -15,7 +15,7 @@ | |||
15 | extern const struct gfs2_glock_operations gfs2_meta_glops; | 15 | extern const struct gfs2_glock_operations gfs2_meta_glops; |
16 | extern const struct gfs2_glock_operations gfs2_inode_glops; | 16 | extern const struct gfs2_glock_operations gfs2_inode_glops; |
17 | extern const struct gfs2_glock_operations gfs2_rgrp_glops; | 17 | extern const struct gfs2_glock_operations gfs2_rgrp_glops; |
18 | extern const struct gfs2_glock_operations gfs2_trans_glops; | 18 | extern const struct gfs2_glock_operations gfs2_freeze_glops; |
19 | extern const struct gfs2_glock_operations gfs2_iopen_glops; | 19 | extern const struct gfs2_glock_operations gfs2_iopen_glops; |
20 | extern const struct gfs2_glock_operations gfs2_flock_glops; | 20 | extern const struct gfs2_glock_operations gfs2_flock_glops; |
21 | extern const struct gfs2_glock_operations gfs2_nondisk_glops; | 21 | extern const struct gfs2_glock_operations gfs2_nondisk_glops; |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index bdf70c18610c..2434a96f95df 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -465,9 +465,7 @@ struct gfs2_trans { | |||
465 | unsigned int tr_reserved; | 465 | unsigned int tr_reserved; |
466 | unsigned int tr_touched:1; | 466 | unsigned int tr_touched:1; |
467 | unsigned int tr_attached:1; | 467 | unsigned int tr_attached:1; |
468 | 468 | unsigned int tr_alloced:1; | |
469 | struct gfs2_holder tr_t_gh; | ||
470 | |||
471 | 469 | ||
472 | unsigned int tr_num_buf_new; | 470 | unsigned int tr_num_buf_new; |
473 | unsigned int tr_num_databuf_new; | 471 | unsigned int tr_num_databuf_new; |
@@ -682,7 +680,7 @@ struct gfs2_sbd { | |||
682 | struct lm_lockstruct sd_lockstruct; | 680 | struct lm_lockstruct sd_lockstruct; |
683 | struct gfs2_holder sd_live_gh; | 681 | struct gfs2_holder sd_live_gh; |
684 | struct gfs2_glock *sd_rename_gl; | 682 | struct gfs2_glock *sd_rename_gl; |
685 | struct gfs2_glock *sd_trans_gl; | 683 | struct gfs2_glock *sd_freeze_gl; |
686 | wait_queue_head_t sd_glock_wait; | 684 | wait_queue_head_t sd_glock_wait; |
687 | atomic_t sd_glock_disposal; | 685 | atomic_t sd_glock_disposal; |
688 | struct completion sd_locking_init; | 686 | struct completion sd_locking_init; |
@@ -794,6 +792,12 @@ struct gfs2_sbd { | |||
794 | 792 | ||
795 | /* For quiescing the filesystem */ | 793 | /* For quiescing the filesystem */ |
796 | struct gfs2_holder sd_freeze_gh; | 794 | struct gfs2_holder sd_freeze_gh; |
795 | struct gfs2_holder sd_freeze_root_gh; | ||
796 | struct gfs2_holder sd_thaw_gh; | ||
797 | atomic_t sd_log_freeze; | ||
798 | atomic_t sd_frozen_root; | ||
799 | wait_queue_head_t sd_frozen_root_wait; | ||
800 | wait_queue_head_t sd_log_frozen_wait; | ||
797 | 801 | ||
798 | char sd_fsname[GFS2_FSNAME_LEN]; | 802 | char sd_fsname[GFS2_FSNAME_LEN]; |
799 | char sd_table_name[GFS2_FSNAME_LEN]; | 803 | char sd_table_name[GFS2_FSNAME_LEN]; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 28cc7bf6575a..e62e59477884 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -1613,18 +1613,26 @@ int gfs2_permission(struct inode *inode, int mask) | |||
1613 | { | 1613 | { |
1614 | struct gfs2_inode *ip; | 1614 | struct gfs2_inode *ip; |
1615 | struct gfs2_holder i_gh; | 1615 | struct gfs2_holder i_gh; |
1616 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1616 | int error; | 1617 | int error; |
1617 | int unlock = 0; | 1618 | int unlock = 0; |
1619 | int frozen_root = 0; | ||
1618 | 1620 | ||
1619 | 1621 | ||
1620 | ip = GFS2_I(inode); | 1622 | ip = GFS2_I(inode); |
1621 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | 1623 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
1622 | if (mask & MAY_NOT_BLOCK) | 1624 | if (unlikely(gfs2_glock_is_held_excl(sdp->sd_freeze_gl) && |
1623 | return -ECHILD; | 1625 | inode == sdp->sd_root_dir->d_inode && |
1624 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | 1626 | atomic_inc_not_zero(&sdp->sd_frozen_root))) |
1625 | if (error) | 1627 | frozen_root = 1; |
1626 | return error; | 1628 | else { |
1627 | unlock = 1; | 1629 | if (mask & MAY_NOT_BLOCK) |
1630 | return -ECHILD; | ||
1631 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | ||
1632 | if (error) | ||
1633 | return error; | ||
1634 | unlock = 1; | ||
1635 | } | ||
1628 | } | 1636 | } |
1629 | 1637 | ||
1630 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | 1638 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) |
@@ -1633,6 +1641,8 @@ int gfs2_permission(struct inode *inode, int mask) | |||
1633 | error = generic_permission(inode, mask); | 1641 | error = generic_permission(inode, mask); |
1634 | if (unlock) | 1642 | if (unlock) |
1635 | gfs2_glock_dq_uninit(&i_gh); | 1643 | gfs2_glock_dq_uninit(&i_gh); |
1644 | else if (frozen_root && atomic_dec_and_test(&sdp->sd_frozen_root)) | ||
1645 | wake_up(&sdp->sd_frozen_root_wait); | ||
1636 | 1646 | ||
1637 | return error; | 1647 | return error; |
1638 | } | 1648 | } |
@@ -1805,19 +1815,29 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1805 | struct inode *inode = dentry->d_inode; | 1815 | struct inode *inode = dentry->d_inode; |
1806 | struct gfs2_inode *ip = GFS2_I(inode); | 1816 | struct gfs2_inode *ip = GFS2_I(inode); |
1807 | struct gfs2_holder gh; | 1817 | struct gfs2_holder gh; |
1818 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1808 | int error; | 1819 | int error; |
1809 | int unlock = 0; | 1820 | int unlock = 0; |
1821 | int frozen_root = 0; | ||
1810 | 1822 | ||
1811 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | 1823 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
1812 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | 1824 | if (unlikely(gfs2_glock_is_held_excl(sdp->sd_freeze_gl) && |
1813 | if (error) | 1825 | inode == sdp->sd_root_dir->d_inode && |
1814 | return error; | 1826 | atomic_inc_not_zero(&sdp->sd_frozen_root))) |
1815 | unlock = 1; | 1827 | frozen_root = 1; |
1828 | else { | ||
1829 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
1830 | if (error) | ||
1831 | return error; | ||
1832 | unlock = 1; | ||
1833 | } | ||
1816 | } | 1834 | } |
1817 | 1835 | ||
1818 | generic_fillattr(inode, stat); | 1836 | generic_fillattr(inode, stat); |
1819 | if (unlock) | 1837 | if (unlock) |
1820 | gfs2_glock_dq_uninit(&gh); | 1838 | gfs2_glock_dq_uninit(&gh); |
1839 | else if (frozen_root && atomic_dec_and_test(&sdp->sd_frozen_root)) | ||
1840 | wake_up(&sdp->sd_frozen_root_wait); | ||
1821 | 1841 | ||
1822 | return 0; | 1842 | return 0; |
1823 | } | 1843 | } |
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 | |||
310 | void 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 | ||
674 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | 694 | void 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 | ||
814 | void gfs2_log_shutdown(struct gfs2_sbd *sdp) | 871 | void 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 | |||
844 | void 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 | ||
856 | static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) | 889 | static 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 | ||
861 | static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp) | 894 | static 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)) |
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 37216634f0aa..9499a6049212 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h | |||
@@ -63,14 +63,21 @@ extern void gfs2_ordered_del_inode(struct gfs2_inode *ip); | |||
63 | extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, | 63 | extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, |
64 | unsigned int ssize); | 64 | unsigned int ssize); |
65 | 65 | ||
66 | extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); | ||
66 | extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); | 67 | extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); |
67 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); | 68 | enum gfs2_flush_type { |
69 | NORMAL_FLUSH = 0, | ||
70 | SYNC_FLUSH, | ||
71 | SHUTDOWN_FLUSH, | ||
72 | FREEZE_FLUSH | ||
73 | }; | ||
74 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, | ||
75 | enum gfs2_flush_type type); | ||
68 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | 76 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); |
69 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); | 77 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); |
70 | extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc); | 78 | extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc); |
71 | 79 | ||
72 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); | 80 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); |
73 | extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); | ||
74 | extern int gfs2_logd(void *data); | 81 | extern int gfs2_logd(void *data); |
75 | extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); | 82 | extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); |
76 | extern void gfs2_write_revokes(struct gfs2_sbd *sdp); | 83 | extern void gfs2_write_revokes(struct gfs2_sbd *sdp); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 22f954051bb8..be45c79f6745 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -129,6 +129,10 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
129 | init_rwsem(&sdp->sd_log_flush_lock); | 129 | init_rwsem(&sdp->sd_log_flush_lock); |
130 | atomic_set(&sdp->sd_log_in_flight, 0); | 130 | atomic_set(&sdp->sd_log_in_flight, 0); |
131 | init_waitqueue_head(&sdp->sd_log_flush_wait); | 131 | init_waitqueue_head(&sdp->sd_log_flush_wait); |
132 | init_waitqueue_head(&sdp->sd_log_frozen_wait); | ||
133 | atomic_set(&sdp->sd_log_freeze, 0); | ||
134 | atomic_set(&sdp->sd_frozen_root, 0); | ||
135 | init_waitqueue_head(&sdp->sd_frozen_root_wait); | ||
132 | 136 | ||
133 | return sdp; | 137 | return sdp; |
134 | } | 138 | } |
@@ -419,8 +423,8 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, | |||
419 | goto fail_live; | 423 | goto fail_live; |
420 | } | 424 | } |
421 | 425 | ||
422 | error = gfs2_glock_get(sdp, GFS2_TRANS_LOCK, &gfs2_trans_glops, | 426 | error = gfs2_glock_get(sdp, GFS2_FREEZE_LOCK, &gfs2_freeze_glops, |
423 | CREATE, &sdp->sd_trans_gl); | 427 | CREATE, &sdp->sd_freeze_gl); |
424 | if (error) { | 428 | if (error) { |
425 | fs_err(sdp, "can't create transaction glock: %d\n", error); | 429 | fs_err(sdp, "can't create transaction glock: %d\n", error); |
426 | goto fail_rename; | 430 | goto fail_rename; |
@@ -429,7 +433,7 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, | |||
429 | return 0; | 433 | return 0; |
430 | 434 | ||
431 | fail_trans: | 435 | fail_trans: |
432 | gfs2_glock_put(sdp->sd_trans_gl); | 436 | gfs2_glock_put(sdp->sd_freeze_gl); |
433 | fail_rename: | 437 | fail_rename: |
434 | gfs2_glock_put(sdp->sd_rename_gl); | 438 | gfs2_glock_put(sdp->sd_rename_gl); |
435 | fail_live: | 439 | fail_live: |
@@ -755,7 +759,15 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
755 | set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); | 759 | set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); |
756 | gfs2_glock_dq_uninit(&ji_gh); | 760 | gfs2_glock_dq_uninit(&ji_gh); |
757 | jindex = 0; | 761 | jindex = 0; |
758 | 762 | if (!sdp->sd_args.ar_spectator) { | |
763 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, | ||
764 | &sdp->sd_thaw_gh); | ||
765 | if (error) { | ||
766 | fs_err(sdp, "can't acquire freeze glock: %d\n", error); | ||
767 | goto fail_jinode_gh; | ||
768 | } | ||
769 | } | ||
770 | gfs2_glock_dq_uninit(&sdp->sd_thaw_gh); | ||
759 | return 0; | 771 | return 0; |
760 | 772 | ||
761 | fail_jinode_gh: | 773 | fail_jinode_gh: |
@@ -1380,7 +1392,7 @@ static void gfs2_kill_sb(struct super_block *sb) | |||
1380 | return; | 1392 | return; |
1381 | } | 1393 | } |
1382 | 1394 | ||
1383 | gfs2_meta_syncfs(sdp); | 1395 | gfs2_log_flush(sdp, NULL, SYNC_FLUSH); |
1384 | dput(sdp->sd_root_dir); | 1396 | dput(sdp->sd_root_dir); |
1385 | dput(sdp->sd_master_dir); | 1397 | dput(sdp->sd_master_dir); |
1386 | sdp->sd_root_dir = NULL; | 1398 | sdp->sd_root_dir = NULL; |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 619389649d03..64b29f7f6b4c 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -880,7 +880,7 @@ out: | |||
880 | gfs2_glock_dq_uninit(&ghs[qx]); | 880 | gfs2_glock_dq_uninit(&ghs[qx]); |
881 | mutex_unlock(&ip->i_inode.i_mutex); | 881 | mutex_unlock(&ip->i_inode.i_mutex); |
882 | kfree(ghs); | 882 | kfree(ghs); |
883 | gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); | 883 | gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl, NORMAL_FLUSH); |
884 | return error; | 884 | return error; |
885 | } | 885 | } |
886 | 886 | ||
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 7ad4094d68c0..a4ed78b5f47e 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
@@ -454,7 +454,7 @@ void gfs2_recover_func(struct work_struct *work) | |||
454 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | 454 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); |
455 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); | 455 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); |
456 | struct gfs2_log_header_host head; | 456 | struct gfs2_log_header_host head; |
457 | struct gfs2_holder j_gh, ji_gh, t_gh; | 457 | struct gfs2_holder j_gh, ji_gh, thaw_gh; |
458 | unsigned long t; | 458 | unsigned long t; |
459 | int ro = 0; | 459 | int ro = 0; |
460 | unsigned int pass; | 460 | unsigned int pass; |
@@ -508,11 +508,11 @@ void gfs2_recover_func(struct work_struct *work) | |||
508 | 508 | ||
509 | t = jiffies; | 509 | t = jiffies; |
510 | 510 | ||
511 | /* Acquire a shared hold on the transaction lock */ | 511 | /* Acquire a shared hold on the freeze lock */ |
512 | 512 | ||
513 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, | 513 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, |
514 | LM_FLAG_NOEXP | LM_FLAG_PRIORITY | | 514 | LM_FLAG_NOEXP | LM_FLAG_PRIORITY, |
515 | GL_NOCACHE, &t_gh); | 515 | &thaw_gh); |
516 | if (error) | 516 | if (error) |
517 | goto fail_gunlock_ji; | 517 | goto fail_gunlock_ji; |
518 | 518 | ||
@@ -538,7 +538,7 @@ void gfs2_recover_func(struct work_struct *work) | |||
538 | fs_warn(sdp, "jid=%u: Can't replay: read-only block " | 538 | fs_warn(sdp, "jid=%u: Can't replay: read-only block " |
539 | "device\n", jd->jd_jid); | 539 | "device\n", jd->jd_jid); |
540 | error = -EROFS; | 540 | error = -EROFS; |
541 | goto fail_gunlock_tr; | 541 | goto fail_gunlock_thaw; |
542 | } | 542 | } |
543 | 543 | ||
544 | fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid); | 544 | fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid); |
@@ -549,14 +549,14 @@ void gfs2_recover_func(struct work_struct *work) | |||
549 | head.lh_blkno, pass); | 549 | head.lh_blkno, pass); |
550 | lops_after_scan(jd, error, pass); | 550 | lops_after_scan(jd, error, pass); |
551 | if (error) | 551 | if (error) |
552 | goto fail_gunlock_tr; | 552 | goto fail_gunlock_thaw; |
553 | } | 553 | } |
554 | 554 | ||
555 | error = clean_journal(jd, &head); | 555 | error = clean_journal(jd, &head); |
556 | if (error) | 556 | if (error) |
557 | goto fail_gunlock_tr; | 557 | goto fail_gunlock_thaw; |
558 | 558 | ||
559 | gfs2_glock_dq_uninit(&t_gh); | 559 | gfs2_glock_dq_uninit(&thaw_gh); |
560 | t = DIV_ROUND_UP(jiffies - t, HZ); | 560 | t = DIV_ROUND_UP(jiffies - t, HZ); |
561 | fs_info(sdp, "jid=%u: Journal replayed in %lus\n", | 561 | fs_info(sdp, "jid=%u: Journal replayed in %lus\n", |
562 | jd->jd_jid, t); | 562 | jd->jd_jid, t); |
@@ -572,8 +572,8 @@ void gfs2_recover_func(struct work_struct *work) | |||
572 | fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); | 572 | fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); |
573 | goto done; | 573 | goto done; |
574 | 574 | ||
575 | fail_gunlock_tr: | 575 | fail_gunlock_thaw: |
576 | gfs2_glock_dq_uninit(&t_gh); | 576 | gfs2_glock_dq_uninit(&thaw_gh); |
577 | fail_gunlock_ji: | 577 | fail_gunlock_ji: |
578 | if (jlocked) { | 578 | if (jlocked) { |
579 | gfs2_glock_dq_uninit(&ji_gh); | 579 | gfs2_glock_dq_uninit(&ji_gh); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 281a7716e3f3..db629d1bd1bd 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -2001,7 +2001,7 @@ next_rgrp: | |||
2001 | } | 2001 | } |
2002 | /* Flushing the log may release space */ | 2002 | /* Flushing the log may release space */ |
2003 | if (loops == 2) | 2003 | if (loops == 2) |
2004 | gfs2_log_flush(sdp, NULL); | 2004 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | return -ENOSPC; | 2007 | return -ENOSPC; |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index de8afad89e51..1319b5c4ec68 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -399,7 +399,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) | |||
399 | { | 399 | { |
400 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); | 400 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); |
401 | struct gfs2_glock *j_gl = ip->i_gl; | 401 | struct gfs2_glock *j_gl = ip->i_gl; |
402 | struct gfs2_holder t_gh; | 402 | struct gfs2_holder thaw_gh; |
403 | struct gfs2_log_header_host head; | 403 | struct gfs2_log_header_host head; |
404 | int error; | 404 | int error; |
405 | 405 | ||
@@ -407,7 +407,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) | |||
407 | if (error) | 407 | if (error) |
408 | return error; | 408 | return error; |
409 | 409 | ||
410 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh); | 410 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, |
411 | &thaw_gh); | ||
411 | if (error) | 412 | if (error) |
412 | goto fail_threads; | 413 | goto fail_threads; |
413 | 414 | ||
@@ -433,13 +434,13 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) | |||
433 | 434 | ||
434 | set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); | 435 | set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); |
435 | 436 | ||
436 | gfs2_glock_dq_uninit(&t_gh); | 437 | gfs2_glock_dq_uninit(&thaw_gh); |
437 | 438 | ||
438 | return 0; | 439 | return 0; |
439 | 440 | ||
440 | fail: | 441 | fail: |
441 | t_gh.gh_flags |= GL_NOCACHE; | 442 | thaw_gh.gh_flags |= GL_NOCACHE; |
442 | gfs2_glock_dq_uninit(&t_gh); | 443 | gfs2_glock_dq_uninit(&thaw_gh); |
443 | fail_threads: | 444 | fail_threads: |
444 | kthread_stop(sdp->sd_quotad_process); | 445 | kthread_stop(sdp->sd_quotad_process); |
445 | kthread_stop(sdp->sd_logd_process); | 446 | kthread_stop(sdp->sd_logd_process); |
@@ -635,15 +636,21 @@ struct lfcc { | |||
635 | */ | 636 | */ |
636 | 637 | ||
637 | static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, | 638 | static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, |
638 | struct gfs2_holder *t_gh) | 639 | struct gfs2_holder *freeze_gh) |
639 | { | 640 | { |
640 | struct gfs2_inode *ip; | 641 | struct gfs2_inode *ip; |
641 | struct gfs2_jdesc *jd; | 642 | struct gfs2_jdesc *jd; |
642 | struct lfcc *lfcc; | 643 | struct lfcc *lfcc; |
643 | LIST_HEAD(list); | 644 | LIST_HEAD(list); |
644 | struct gfs2_log_header_host lh; | 645 | struct gfs2_log_header_host lh; |
646 | struct gfs2_inode *dip = GFS2_I(sdp->sd_root_dir->d_inode); | ||
645 | int error; | 647 | int error; |
646 | 648 | ||
649 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, | ||
650 | &sdp->sd_freeze_root_gh); | ||
651 | if (error) | ||
652 | return error; | ||
653 | atomic_set(&sdp->sd_frozen_root, 1); | ||
647 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { | 654 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { |
648 | lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL); | 655 | lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL); |
649 | if (!lfcc) { | 656 | if (!lfcc) { |
@@ -659,8 +666,8 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, | |||
659 | list_add(&lfcc->list, &list); | 666 | list_add(&lfcc->list, &list); |
660 | } | 667 | } |
661 | 668 | ||
662 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_DEFERRED, | 669 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE, |
663 | GL_NOCACHE, t_gh); | 670 | GL_NOCACHE, freeze_gh); |
664 | 671 | ||
665 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { | 672 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { |
666 | error = gfs2_jdesc_check(jd); | 673 | error = gfs2_jdesc_check(jd); |
@@ -676,7 +683,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, | |||
676 | } | 683 | } |
677 | 684 | ||
678 | if (error) | 685 | if (error) |
679 | gfs2_glock_dq_uninit(t_gh); | 686 | gfs2_glock_dq_uninit(freeze_gh); |
680 | 687 | ||
681 | out: | 688 | out: |
682 | while (!list_empty(&list)) { | 689 | while (!list_empty(&list)) { |
@@ -685,6 +692,11 @@ out: | |||
685 | gfs2_glock_dq_uninit(&lfcc->gh); | 692 | gfs2_glock_dq_uninit(&lfcc->gh); |
686 | kfree(lfcc); | 693 | kfree(lfcc); |
687 | } | 694 | } |
695 | if (error) { | ||
696 | atomic_dec(&sdp->sd_frozen_root); | ||
697 | wait_event(sdp->sd_frozen_root_wait, atomic_read(&sdp->sd_frozen_root) == 0); | ||
698 | gfs2_glock_dq_uninit(&sdp->sd_freeze_root_gh); | ||
699 | } | ||
688 | return error; | 700 | return error; |
689 | } | 701 | } |
690 | 702 | ||
@@ -742,7 +754,7 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
742 | int ret = 0; | 754 | int ret = 0; |
743 | 755 | ||
744 | if (wbc->sync_mode == WB_SYNC_ALL) | 756 | if (wbc->sync_mode == WB_SYNC_ALL) |
745 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 757 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl, NORMAL_FLUSH); |
746 | if (bdi->dirty_exceeded) | 758 | if (bdi->dirty_exceeded) |
747 | gfs2_ail1_flush(sdp, wbc); | 759 | gfs2_ail1_flush(sdp, wbc); |
748 | else | 760 | else |
@@ -822,9 +834,18 @@ out: | |||
822 | 834 | ||
823 | static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | 835 | static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) |
824 | { | 836 | { |
825 | struct gfs2_holder t_gh; | 837 | struct gfs2_holder thaw_gh; |
826 | int error; | 838 | int error; |
827 | 839 | ||
840 | error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, GL_NOCACHE, | ||
841 | &thaw_gh); | ||
842 | if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
843 | return error; | ||
844 | |||
845 | down_write(&sdp->sd_log_flush_lock); | ||
846 | clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); | ||
847 | up_write(&sdp->sd_log_flush_lock); | ||
848 | |||
828 | kthread_stop(sdp->sd_quotad_process); | 849 | kthread_stop(sdp->sd_quotad_process); |
829 | kthread_stop(sdp->sd_logd_process); | 850 | kthread_stop(sdp->sd_logd_process); |
830 | 851 | ||
@@ -832,18 +853,11 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
832 | gfs2_quota_sync(sdp->sd_vfs, 0); | 853 | gfs2_quota_sync(sdp->sd_vfs, 0); |
833 | gfs2_statfs_sync(sdp->sd_vfs, 0); | 854 | gfs2_statfs_sync(sdp->sd_vfs, 0); |
834 | 855 | ||
835 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, | 856 | gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH); |
836 | &t_gh); | 857 | gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); |
837 | if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
838 | return error; | ||
839 | |||
840 | gfs2_meta_syncfs(sdp); | ||
841 | gfs2_log_shutdown(sdp); | ||
842 | |||
843 | clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); | ||
844 | 858 | ||
845 | if (t_gh.gh_gl) | 859 | if (thaw_gh.gh_gl) |
846 | gfs2_glock_dq_uninit(&t_gh); | 860 | gfs2_glock_dq_uninit(&thaw_gh); |
847 | 861 | ||
848 | gfs2_quota_cleanup(sdp); | 862 | gfs2_quota_cleanup(sdp); |
849 | 863 | ||
@@ -900,7 +914,7 @@ restart: | |||
900 | iput(sdp->sd_quota_inode); | 914 | iput(sdp->sd_quota_inode); |
901 | 915 | ||
902 | gfs2_glock_put(sdp->sd_rename_gl); | 916 | gfs2_glock_put(sdp->sd_rename_gl); |
903 | gfs2_glock_put(sdp->sd_trans_gl); | 917 | gfs2_glock_put(sdp->sd_freeze_gl); |
904 | 918 | ||
905 | if (!sdp->sd_args.ar_spectator) { | 919 | if (!sdp->sd_args.ar_spectator) { |
906 | gfs2_glock_dq_uninit(&sdp->sd_journal_gh); | 920 | gfs2_glock_dq_uninit(&sdp->sd_journal_gh); |
@@ -935,8 +949,8 @@ static int gfs2_sync_fs(struct super_block *sb, int wait) | |||
935 | struct gfs2_sbd *sdp = sb->s_fs_info; | 949 | struct gfs2_sbd *sdp = sb->s_fs_info; |
936 | 950 | ||
937 | gfs2_quota_sync(sb, -1); | 951 | gfs2_quota_sync(sb, -1); |
938 | if (wait && sdp) | 952 | if (wait && sdp && !atomic_read(&sdp->sd_log_freeze)) |
939 | gfs2_log_flush(sdp, NULL); | 953 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
940 | return 0; | 954 | return 0; |
941 | } | 955 | } |
942 | 956 | ||
@@ -986,6 +1000,9 @@ static int gfs2_unfreeze(struct super_block *sb) | |||
986 | struct gfs2_sbd *sdp = sb->s_fs_info; | 1000 | struct gfs2_sbd *sdp = sb->s_fs_info; |
987 | 1001 | ||
988 | gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); | 1002 | gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); |
1003 | atomic_dec(&sdp->sd_frozen_root); | ||
1004 | wait_event(sdp->sd_frozen_root_wait, atomic_read(&sdp->sd_frozen_root) == 0); | ||
1005 | gfs2_glock_dq_uninit(&sdp->sd_freeze_root_gh); | ||
989 | return 0; | 1006 | return 0; |
990 | } | 1007 | } |
991 | 1008 | ||
@@ -1525,7 +1542,7 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1525 | goto out_unlock; | 1542 | goto out_unlock; |
1526 | 1543 | ||
1527 | out_truncate: | 1544 | out_truncate: |
1528 | gfs2_log_flush(sdp, ip->i_gl); | 1545 | gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); |
1529 | if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) { | 1546 | if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) { |
1530 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); | 1547 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); |
1531 | filemap_fdatawrite(metamapping); | 1548 | filemap_fdatawrite(metamapping); |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index de25d5577e5d..7bc17edcb51f 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -240,8 +240,8 @@ static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len | |||
240 | 240 | ||
241 | if (gltype > LM_TYPE_JOURNAL) | 241 | if (gltype > LM_TYPE_JOURNAL) |
242 | return -EINVAL; | 242 | return -EINVAL; |
243 | if (gltype == LM_TYPE_NONDISK && glnum == GFS2_TRANS_LOCK) | 243 | if (gltype == LM_TYPE_NONDISK && glnum == GFS2_FREEZE_LOCK) |
244 | glops = &gfs2_trans_glops; | 244 | glops = &gfs2_freeze_glops; |
245 | else | 245 | else |
246 | glops = gfs2_glops_list[gltype]; | 246 | glops = gfs2_glops_list[gltype]; |
247 | if (glops == NULL) | 247 | if (glops == NULL) |
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index bead90d27bad..0546ab4e28e8 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
@@ -48,6 +48,7 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, | |||
48 | tr->tr_blocks = blocks; | 48 | tr->tr_blocks = blocks; |
49 | tr->tr_revokes = revokes; | 49 | tr->tr_revokes = revokes; |
50 | tr->tr_reserved = 1; | 50 | tr->tr_reserved = 1; |
51 | tr->tr_alloced = 1; | ||
51 | if (blocks) | 52 | if (blocks) |
52 | tr->tr_reserved += 6 + blocks; | 53 | tr->tr_reserved += 6 + blocks; |
53 | if (revokes) | 54 | if (revokes) |
@@ -57,48 +58,22 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, | |||
57 | INIT_LIST_HEAD(&tr->tr_buf); | 58 | INIT_LIST_HEAD(&tr->tr_buf); |
58 | 59 | ||
59 | sb_start_intwrite(sdp->sd_vfs); | 60 | sb_start_intwrite(sdp->sd_vfs); |
60 | gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); | ||
61 | |||
62 | error = gfs2_glock_nq(&tr->tr_t_gh); | ||
63 | if (error) | ||
64 | goto fail_holder_uninit; | ||
65 | 61 | ||
66 | error = gfs2_log_reserve(sdp, tr->tr_reserved); | 62 | error = gfs2_log_reserve(sdp, tr->tr_reserved); |
67 | if (error) | 63 | if (error) |
68 | goto fail_gunlock; | 64 | goto fail; |
69 | 65 | ||
70 | current->journal_info = tr; | 66 | current->journal_info = tr; |
71 | 67 | ||
72 | return 0; | 68 | return 0; |
73 | 69 | ||
74 | fail_gunlock: | 70 | fail: |
75 | gfs2_glock_dq(&tr->tr_t_gh); | ||
76 | |||
77 | fail_holder_uninit: | ||
78 | sb_end_intwrite(sdp->sd_vfs); | 71 | sb_end_intwrite(sdp->sd_vfs); |
79 | gfs2_holder_uninit(&tr->tr_t_gh); | ||
80 | kfree(tr); | 72 | kfree(tr); |
81 | 73 | ||
82 | return error; | 74 | return error; |
83 | } | 75 | } |
84 | 76 | ||
85 | /** | ||
86 | * gfs2_log_release - Release a given number of log blocks | ||
87 | * @sdp: The GFS2 superblock | ||
88 | * @blks: The number of blocks | ||
89 | * | ||
90 | */ | ||
91 | |||
92 | static void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) | ||
93 | { | ||
94 | |||
95 | atomic_add(blks, &sdp->sd_log_blks_free); | ||
96 | trace_gfs2_log_blocks(sdp, blks); | ||
97 | gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= | ||
98 | sdp->sd_jdesc->jd_blocks); | ||
99 | up_read(&sdp->sd_log_flush_lock); | ||
100 | } | ||
101 | |||
102 | static void gfs2_print_trans(const struct gfs2_trans *tr) | 77 | static void gfs2_print_trans(const struct gfs2_trans *tr) |
103 | { | 78 | { |
104 | pr_warn("Transaction created at: %pSR\n", (void *)tr->tr_ip); | 79 | pr_warn("Transaction created at: %pSR\n", (void *)tr->tr_ip); |
@@ -119,11 +94,8 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
119 | 94 | ||
120 | if (!tr->tr_touched) { | 95 | if (!tr->tr_touched) { |
121 | gfs2_log_release(sdp, tr->tr_reserved); | 96 | gfs2_log_release(sdp, tr->tr_reserved); |
122 | if (tr->tr_t_gh.gh_gl) { | 97 | if (tr->tr_alloced) |
123 | gfs2_glock_dq(&tr->tr_t_gh); | ||
124 | gfs2_holder_uninit(&tr->tr_t_gh); | ||
125 | kfree(tr); | 98 | kfree(tr); |
126 | } | ||
127 | sb_end_intwrite(sdp->sd_vfs); | 99 | sb_end_intwrite(sdp->sd_vfs); |
128 | return; | 100 | return; |
129 | } | 101 | } |
@@ -137,16 +109,12 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
137 | gfs2_print_trans(tr); | 109 | gfs2_print_trans(tr); |
138 | 110 | ||
139 | gfs2_log_commit(sdp, tr); | 111 | gfs2_log_commit(sdp, tr); |
140 | if (tr->tr_t_gh.gh_gl) { | 112 | if (tr->tr_alloced && !tr->tr_attached) |
141 | gfs2_glock_dq(&tr->tr_t_gh); | ||
142 | gfs2_holder_uninit(&tr->tr_t_gh); | ||
143 | if (!tr->tr_attached) | ||
144 | kfree(tr); | 113 | kfree(tr); |
145 | } | ||
146 | up_read(&sdp->sd_log_flush_lock); | 114 | up_read(&sdp->sd_log_flush_lock); |
147 | 115 | ||
148 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) | 116 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) |
149 | gfs2_log_flush(sdp, NULL); | 117 | gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
150 | sb_end_intwrite(sdp->sd_vfs); | 118 | sb_end_intwrite(sdp->sd_vfs); |
151 | } | 119 | } |
152 | 120 | ||
diff --git a/include/uapi/linux/gfs2_ondisk.h b/include/uapi/linux/gfs2_ondisk.h index db3fdd083882..1a763eaae0bb 100644 --- a/include/uapi/linux/gfs2_ondisk.h +++ b/include/uapi/linux/gfs2_ondisk.h | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | #define GFS2_MOUNT_LOCK 0 | 21 | #define GFS2_MOUNT_LOCK 0 |
22 | #define GFS2_LIVE_LOCK 1 | 22 | #define GFS2_LIVE_LOCK 1 |
23 | #define GFS2_TRANS_LOCK 2 | 23 | #define GFS2_FREEZE_LOCK 2 |
24 | #define GFS2_RENAME_LOCK 3 | 24 | #define GFS2_RENAME_LOCK 3 |
25 | #define GFS2_CONTROL_LOCK 4 | 25 | #define GFS2_CONTROL_LOCK 4 |
26 | #define GFS2_MOUNTED_LOCK 5 | 26 | #define GFS2_MOUNTED_LOCK 5 |