Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11475975 authored by Ryusuke Konishi's avatar Ryusuke Konishi Committed by Linus Torvalds
Browse files

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: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a1d49449
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -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);
			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;
}

+7 −1
Original line number Diff line number Diff line
@@ -692,8 +692,14 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
	if (ret < 0)
		return ret;

	if (argp != NULL) {
	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) {
		down_read(&nilfs->ns_segctor_sem);
		cno = nilfs->ns_cno - 1;
		up_read(&nilfs->ns_segctor_sem);