diff options
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r-- | fs/gfs2/log.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 0cace3da9dbb..291415ddfe51 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/gfs2_ondisk.h> | 15 | #include <linux/gfs2_ondisk.h> |
16 | #include <linux/crc32.h> | 16 | #include <linux/crc32.h> |
17 | #include <linux/lm_interface.h> | 17 | #include <linux/lm_interface.h> |
18 | #include <linux/delay.h> | ||
18 | 19 | ||
19 | #include "gfs2.h" | 20 | #include "gfs2.h" |
20 | #include "incore.h" | 21 | #include "incore.h" |
@@ -142,7 +143,7 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl | |||
142 | return list_empty(&ai->ai_ail1_list); | 143 | return list_empty(&ai->ai_ail1_list); |
143 | } | 144 | } |
144 | 145 | ||
145 | void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) | 146 | static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) |
146 | { | 147 | { |
147 | struct list_head *head = &sdp->sd_ail1_list; | 148 | struct list_head *head = &sdp->sd_ail1_list; |
148 | u64 sync_gen; | 149 | u64 sync_gen; |
@@ -261,6 +262,12 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
261 | * @sdp: The GFS2 superblock | 262 | * @sdp: The GFS2 superblock |
262 | * @blks: The number of blocks to reserve | 263 | * @blks: The number of blocks to reserve |
263 | * | 264 | * |
265 | * Note that we never give out the last 6 blocks of the journal. Thats | ||
266 | * due to the fact that there is are a small number of header blocks | ||
267 | * associated with each log flush. The exact number can't be known until | ||
268 | * flush time, so we ensure that we have just enough free blocks at all | ||
269 | * times to avoid running out during a log flush. | ||
270 | * | ||
264 | * Returns: errno | 271 | * Returns: errno |
265 | */ | 272 | */ |
266 | 273 | ||
@@ -274,7 +281,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | |||
274 | 281 | ||
275 | mutex_lock(&sdp->sd_log_reserve_mutex); | 282 | mutex_lock(&sdp->sd_log_reserve_mutex); |
276 | gfs2_log_lock(sdp); | 283 | gfs2_log_lock(sdp); |
277 | while(sdp->sd_log_blks_free <= blks) { | 284 | while(sdp->sd_log_blks_free <= (blks + 6)) { |
278 | gfs2_log_unlock(sdp); | 285 | gfs2_log_unlock(sdp); |
279 | gfs2_ail1_empty(sdp, 0); | 286 | gfs2_ail1_empty(sdp, 0); |
280 | gfs2_log_flush(sdp, NULL); | 287 | gfs2_log_flush(sdp, NULL); |
@@ -319,7 +326,8 @@ static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) | |||
319 | bh_map.b_size = 1 << inode->i_blkbits; | 326 | bh_map.b_size = 1 << inode->i_blkbits; |
320 | error = gfs2_block_map(inode, lbn, 0, &bh_map); | 327 | error = gfs2_block_map(inode, lbn, 0, &bh_map); |
321 | if (error || !bh_map.b_blocknr) | 328 | if (error || !bh_map.b_blocknr) |
322 | printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, bh_map.b_blocknr, lbn); | 329 | printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, |
330 | (unsigned long long)bh_map.b_blocknr, lbn); | ||
323 | gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr); | 331 | gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr); |
324 | 332 | ||
325 | return bh_map.b_blocknr; | 333 | return bh_map.b_blocknr; |
@@ -643,12 +651,9 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
643 | up_read(&sdp->sd_log_flush_lock); | 651 | up_read(&sdp->sd_log_flush_lock); |
644 | 652 | ||
645 | gfs2_log_lock(sdp); | 653 | gfs2_log_lock(sdp); |
646 | if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) { | 654 | if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) |
647 | gfs2_log_unlock(sdp); | 655 | wake_up_process(sdp->sd_logd_process); |
648 | gfs2_log_flush(sdp, NULL); | 656 | gfs2_log_unlock(sdp); |
649 | } else { | ||
650 | gfs2_log_unlock(sdp); | ||
651 | } | ||
652 | } | 657 | } |
653 | 658 | ||
654 | /** | 659 | /** |
@@ -686,3 +691,21 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) | |||
686 | up_write(&sdp->sd_log_flush_lock); | 691 | up_write(&sdp->sd_log_flush_lock); |
687 | } | 692 | } |
688 | 693 | ||
694 | |||
695 | /** | ||
696 | * gfs2_meta_syncfs - sync all the buffers in a filesystem | ||
697 | * @sdp: the filesystem | ||
698 | * | ||
699 | */ | ||
700 | |||
701 | void gfs2_meta_syncfs(struct gfs2_sbd *sdp) | ||
702 | { | ||
703 | gfs2_log_flush(sdp, NULL); | ||
704 | for (;;) { | ||
705 | gfs2_ail1_start(sdp, DIO_ALL); | ||
706 | if (gfs2_ail1_empty(sdp, DIO_ALL)) | ||
707 | break; | ||
708 | msleep(10); | ||
709 | } | ||
710 | } | ||
711 | |||