diff options
author | Jan Kara <jack@suse.cz> | 2009-04-27 10:43:51 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-11 21:36:03 -0400 |
commit | 5cee5815d1564bbbd505fea86f4550f1efdb5cd0 (patch) | |
tree | ba99c38932dc534bf56f0d7dcfeeca153f50b007 /fs/sync.c | |
parent | 429479f031322a0cc5c921ffb2321a51718dc875 (diff) |
vfs: Make sys_sync() use fsync_super() (version 4)
It is unnecessarily fragile to have two places (fsync_super() and do_sync())
doing data integrity sync of the filesystem. Alter __fsync_super() to
accommodate needs of both callers and use it. So after this patch
__fsync_super() is the only place where we gather all the calls needed to
properly send all data on a filesystem to disk.
Nice bonus is that we get a complete livelock avoidance and write_supers()
is now only used for periodic writeback of superblocks.
sync_blockdevs() introduced a couple of patches ago is gone now.
[build fixes folded]
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/sync.c')
-rw-r--r-- | fs/sync.c | 31 |
1 files changed, 10 insertions, 21 deletions
@@ -18,35 +18,24 @@ | |||
18 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ | 18 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ |
19 | SYNC_FILE_RANGE_WAIT_AFTER) | 19 | SYNC_FILE_RANGE_WAIT_AFTER) |
20 | 20 | ||
21 | /* | 21 | SYSCALL_DEFINE0(sync) |
22 | * sync everything. Start out by waking pdflush, because that writes back | ||
23 | * all queues in parallel. | ||
24 | */ | ||
25 | static void do_sync(unsigned long wait) | ||
26 | { | 22 | { |
27 | wakeup_pdflush(0); | 23 | sync_filesystems(0); |
28 | sync_inodes(0); /* All mappings, inodes and their blockdevs */ | 24 | sync_filesystems(1); |
29 | vfs_dq_sync(NULL); | ||
30 | sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */ | ||
31 | sync_supers(); /* Write the superblocks */ | ||
32 | sync_filesystems(0); /* Start syncing the filesystems */ | ||
33 | sync_filesystems(wait); /* Waitingly sync the filesystems */ | ||
34 | sync_blockdevs(); | ||
35 | if (!wait) | ||
36 | printk("Emergency Sync complete\n"); | ||
37 | if (unlikely(laptop_mode)) | 25 | if (unlikely(laptop_mode)) |
38 | laptop_sync_completion(); | 26 | laptop_sync_completion(); |
39 | } | ||
40 | |||
41 | SYSCALL_DEFINE0(sync) | ||
42 | { | ||
43 | do_sync(1); | ||
44 | return 0; | 27 | return 0; |
45 | } | 28 | } |
46 | 29 | ||
47 | static void do_sync_work(struct work_struct *work) | 30 | static void do_sync_work(struct work_struct *work) |
48 | { | 31 | { |
49 | do_sync(0); | 32 | /* |
33 | * Sync twice to reduce the possibility we skipped some inodes / pages | ||
34 | * because they were temporarily locked | ||
35 | */ | ||
36 | sync_filesystems(0); | ||
37 | sync_filesystems(0); | ||
38 | printk("Emergency Sync complete\n"); | ||
50 | kfree(work); | 39 | kfree(work); |
51 | } | 40 | } |
52 | 41 | ||