diff options
author | Andreas Rohner <andreas.rohner@gmx.net> | 2014-10-13 18:53:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 20:18:20 -0400 |
commit | e2c7617ae36b27f97643bfa08aabe27e630c1a76 (patch) | |
tree | 306dc0642ffbd8c4f837b7fbae960a49116053e6 /fs/nilfs2 | |
parent | 0f2a84f41aff6cefd1bc768738159d0cacea2f2d (diff) |
nilfs2: add missing blkdev_issue_flush() to nilfs_sync_fs()
Under normal circumstances nilfs_sync_fs() writes out the super block,
which causes a flush of the underlying block device. But this depends
on the THE_NILFS_SB_DIRTY flag, which is only set if the pointer to the
last segment crosses a segment boundary. So if only a small amount of
data is written before the call to nilfs_sync_fs(), no flush of the
block device occurs.
In the above case an additional call to blkdev_issue_flush() is needed.
To prevent unnecessary overhead, the new flag nilfs->ns_flushed_device
is introduced, which is cleared whenever new logs are written and set
whenever the block device is flushed. For convenience the function
nilfs_flush_device() is added, which contains the above logic.
Signed-off-by: Andreas Rohner <andreas.rohner@gmx.net>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/file.c | 8 | ||||
-rw-r--r-- | fs/nilfs2/ioctl.c | 8 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 3 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 6 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.h | 22 |
5 files changed, 37 insertions, 10 deletions
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 24978153c0c4..e9e3325f29f3 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c | |||
@@ -56,11 +56,9 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
56 | mutex_unlock(&inode->i_mutex); | 56 | mutex_unlock(&inode->i_mutex); |
57 | 57 | ||
58 | nilfs = inode->i_sb->s_fs_info; | 58 | nilfs = inode->i_sb->s_fs_info; |
59 | if (!err && nilfs_test_opt(nilfs, BARRIER)) { | 59 | if (!err) |
60 | err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); | 60 | err = nilfs_flush_device(nilfs); |
61 | if (err != -EIO) | 61 | |
62 | err = 0; | ||
63 | } | ||
64 | return err; | 62 | return err; |
65 | } | 63 | } |
66 | 64 | ||
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 422fb54b7377..9a20e513d7eb 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -1022,11 +1022,9 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, | |||
1022 | return ret; | 1022 | return ret; |
1023 | 1023 | ||
1024 | nilfs = inode->i_sb->s_fs_info; | 1024 | nilfs = inode->i_sb->s_fs_info; |
1025 | if (nilfs_test_opt(nilfs, BARRIER)) { | 1025 | ret = nilfs_flush_device(nilfs); |
1026 | ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); | 1026 | if (ret < 0) |
1027 | if (ret == -EIO) | 1027 | return ret; |
1028 | return ret; | ||
1029 | } | ||
1030 | 1028 | ||
1031 | if (argp != NULL) { | 1029 | if (argp != NULL) { |
1032 | down_read(&nilfs->ns_segctor_sem); | 1030 | down_read(&nilfs->ns_segctor_sem); |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index a1a191634abc..0b7d2cad0426 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -1833,6 +1833,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1833 | nilfs_set_next_segment(nilfs, segbuf); | 1833 | nilfs_set_next_segment(nilfs, segbuf); |
1834 | 1834 | ||
1835 | if (update_sr) { | 1835 | if (update_sr) { |
1836 | nilfs->ns_flushed_device = 0; | ||
1836 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, | 1837 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, |
1837 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); | 1838 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); |
1838 | 1839 | ||
@@ -2216,6 +2217,8 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, | |||
2216 | sci->sc_dsync_end = end; | 2217 | sci->sc_dsync_end = end; |
2217 | 2218 | ||
2218 | err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC); | 2219 | err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC); |
2220 | if (!err) | ||
2221 | nilfs->ns_flushed_device = 0; | ||
2219 | 2222 | ||
2220 | nilfs_transaction_unlock(sb); | 2223 | nilfs_transaction_unlock(sb); |
2221 | return err; | 2224 | return err; |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 228f5bdf0772..2e5b3ec85b8f 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -310,6 +310,9 @@ int nilfs_commit_super(struct super_block *sb, int flag) | |||
310 | nilfs->ns_sbsize)); | 310 | nilfs->ns_sbsize)); |
311 | } | 311 | } |
312 | clear_nilfs_sb_dirty(nilfs); | 312 | clear_nilfs_sb_dirty(nilfs); |
313 | nilfs->ns_flushed_device = 1; | ||
314 | /* make sure store to ns_flushed_device cannot be reordered */ | ||
315 | smp_wmb(); | ||
313 | return nilfs_sync_super(sb, flag); | 316 | return nilfs_sync_super(sb, flag); |
314 | } | 317 | } |
315 | 318 | ||
@@ -514,6 +517,9 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
514 | } | 517 | } |
515 | up_write(&nilfs->ns_sem); | 518 | up_write(&nilfs->ns_sem); |
516 | 519 | ||
520 | if (!err) | ||
521 | err = nilfs_flush_device(nilfs); | ||
522 | |||
517 | return err; | 523 | return err; |
518 | } | 524 | } |
519 | 525 | ||
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index d01ead1bea9a..23778d385836 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -46,6 +46,7 @@ enum { | |||
46 | /** | 46 | /** |
47 | * struct the_nilfs - struct to supervise multiple nilfs mount points | 47 | * struct the_nilfs - struct to supervise multiple nilfs mount points |
48 | * @ns_flags: flags | 48 | * @ns_flags: flags |
49 | * @ns_flushed_device: flag indicating if all volatile data was flushed | ||
49 | * @ns_bdev: block device | 50 | * @ns_bdev: block device |
50 | * @ns_sem: semaphore for shared states | 51 | * @ns_sem: semaphore for shared states |
51 | * @ns_snapshot_mount_mutex: mutex to protect snapshot mounts | 52 | * @ns_snapshot_mount_mutex: mutex to protect snapshot mounts |
@@ -103,6 +104,7 @@ enum { | |||
103 | */ | 104 | */ |
104 | struct the_nilfs { | 105 | struct the_nilfs { |
105 | unsigned long ns_flags; | 106 | unsigned long ns_flags; |
107 | int ns_flushed_device; | ||
106 | 108 | ||
107 | struct block_device *ns_bdev; | 109 | struct block_device *ns_bdev; |
108 | struct rw_semaphore ns_sem; | 110 | struct rw_semaphore ns_sem; |
@@ -371,4 +373,24 @@ static inline int nilfs_segment_is_active(struct the_nilfs *nilfs, __u64 n) | |||
371 | return n == nilfs->ns_segnum || n == nilfs->ns_nextnum; | 373 | return n == nilfs->ns_segnum || n == nilfs->ns_nextnum; |
372 | } | 374 | } |
373 | 375 | ||
376 | static inline int nilfs_flush_device(struct the_nilfs *nilfs) | ||
377 | { | ||
378 | int err; | ||
379 | |||
380 | if (!nilfs_test_opt(nilfs, BARRIER) || nilfs->ns_flushed_device) | ||
381 | return 0; | ||
382 | |||
383 | nilfs->ns_flushed_device = 1; | ||
384 | /* | ||
385 | * the store to ns_flushed_device must not be reordered after | ||
386 | * blkdev_issue_flush(). | ||
387 | */ | ||
388 | smp_wmb(); | ||
389 | |||
390 | err = blkdev_issue_flush(nilfs->ns_bdev, GFP_KERNEL, NULL); | ||
391 | if (err != -EIO) | ||
392 | err = 0; | ||
393 | return err; | ||
394 | } | ||
395 | |||
374 | #endif /* _THE_NILFS_H */ | 396 | #endif /* _THE_NILFS_H */ |