From 11475975dd3c0a8e639f1544ef6530373de5979e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 31 May 2012 16:26:11 -0700 Subject: nilfs2: flush disk caches in syncing There are two cases that the cache flush is needed to avoid data loss against unexpected hang or power failure. One is sync file function (i.e. nilfs_sync_file) and another is checkpointing ioctl. This issues a cache flush request to device for such cases if barrier mount option is enabled, and makes sure data really is on persistent storage on their completion. Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/file.c | 24 ++++++++++++++---------- fs/nilfs2/ioctl.c | 8 +++++++- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 26601529dc17..62cebc8e1a1f 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -37,6 +37,7 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) * This function should be implemented when the writeback function * will be implemented. */ + struct the_nilfs *nilfs; struct inode *inode = file->f_mapping->host; int err; @@ -45,18 +46,21 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) return err; mutex_lock(&inode->i_mutex); - if (!nilfs_inode_dirty(inode)) { - mutex_unlock(&inode->i_mutex); - return 0; + if (nilfs_inode_dirty(inode)) { + if (datasync) + err = nilfs_construct_dsync_segment(inode->i_sb, inode, + 0, LLONG_MAX); + else + err = nilfs_construct_segment(inode->i_sb); } - - if (datasync) - err = nilfs_construct_dsync_segment(inode->i_sb, inode, 0, - LLONG_MAX); - else - err = nilfs_construct_segment(inode->i_sb); - mutex_unlock(&inode->i_mutex); + + nilfs = inode->i_sb->s_fs_info; + if (!err && nilfs_test_opt(nilfs, BARRIER)) { + err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + if (err != -EIO) + err = 0; + } return err; } diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 2a70fce70c65..06658caa18bd 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -692,8 +692,14 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, if (ret < 0) return ret; + nilfs = inode->i_sb->s_fs_info; + if (nilfs_test_opt(nilfs, BARRIER)) { + ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + if (ret == -EIO) + return ret; + } + if (argp != NULL) { - nilfs = inode->i_sb->s_fs_info; down_read(&nilfs->ns_segctor_sem); cno = nilfs->ns_cno - 1; up_read(&nilfs->ns_segctor_sem); -- cgit v1.2.3-58-ga151