summaryrefslogtreecommitdiffstats
path: root/fs/gfs2/log.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-11-23 10:51:34 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-11-30 10:36:42 -0500
commitb004157ab5b374a498a5874cda68c389219d23e7 (patch)
tree1e7d7d5c62f3e12cc453e763bbff139b47458be4 /fs/gfs2/log.c
parentae619320b22f8e0b2bbe4a3a5ac2f9ccf08d7ec2 (diff)
downloadlinux-b004157ab5b374a498a5874cda68c389219d23e7.tar.gz
linux-b004157ab5b374a498a5874cda68c389219d23e7.tar.bz2
linux-b004157ab5b374a498a5874cda68c389219d23e7.zip
[GFS2] Fix journal flush problem
This fixes a bug which resulted in poor performance due to flushing the journal too often. The code path in question was via the inode_go_sync() function in glops.c. The solution is not to flush the journal immediately when inodes are ejected from memory, but batch up the work for glockd to deal with later on. This means that glocks may now live on beyond the end of the lifetime of their inodes (but not very much longer in the normal case). Also fixed in this patch is a bug (which was hidden by the bug mentioned above) in calculation of the number of free journal blocks. The gfs2_logd process has been altered to be more responsive to the journal filling up. We now wake it up when the number of uncommitted journal blocks has reached the threshold level rather than trying to flush directly at the end of each transaction. This again means doing fewer, but larger, log flushes in general. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r--fs/gfs2/log.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 0cace3da9dbb..6456fc39aace 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -261,6 +261,12 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
* @sdp: The GFS2 superblock
* @blks: The number of blocks to reserve
*
+ * Note that we never give out the last 6 blocks of the journal. Thats
+ * due to the fact that there is are a small number of header blocks
+ * associated with each log flush. The exact number can't be known until
+ * flush time, so we ensure that we have just enough free blocks at all
+ * times to avoid running out during a log flush.
+ *
* Returns: errno
*/
@@ -274,7 +280,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
mutex_lock(&sdp->sd_log_reserve_mutex);
gfs2_log_lock(sdp);
- while(sdp->sd_log_blks_free <= blks) {
+ while(sdp->sd_log_blks_free <= (blks + 6)) {
gfs2_log_unlock(sdp);
gfs2_ail1_empty(sdp, 0);
gfs2_log_flush(sdp, NULL);
@@ -643,12 +649,9 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
up_read(&sdp->sd_log_flush_lock);
gfs2_log_lock(sdp);
- if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) {
- gfs2_log_unlock(sdp);
- gfs2_log_flush(sdp, NULL);
- } else {
- gfs2_log_unlock(sdp);
- }
+ if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks))
+ wake_up_process(sdp->sd_logd_process);
+ gfs2_log_unlock(sdp);
}
/**