aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sync.c')
-rw-r--r--fs/sync.c85
1 files changed, 66 insertions, 19 deletions
diff --git a/fs/sync.c b/fs/sync.c
index 3422ba61d86d..c08467a5d7cb 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -19,20 +19,29 @@
19 SYNC_FILE_RANGE_WAIT_AFTER) 19 SYNC_FILE_RANGE_WAIT_AFTER)
20 20
21/* 21/*
22 * Do the filesystem syncing work. For simple filesystems sync_inodes_sb(sb, 0) 22 * Do the filesystem syncing work. For simple filesystems
23 * just dirties buffers with inodes so we have to submit IO for these buffers 23 * writeback_inodes_sb(sb) just dirties buffers with inodes so we have to
24 * via __sync_blockdev(). This also speeds up the wait == 1 case since in that 24 * submit IO for these buffers via __sync_blockdev(). This also speeds up the
25 * case write_inode() functions do sync_dirty_buffer() and thus effectively 25 * wait == 1 case since in that case write_inode() functions do
26 * write one block at a time. 26 * sync_dirty_buffer() and thus effectively write one block at a time.
27 */ 27 */
28static int __sync_filesystem(struct super_block *sb, int wait) 28static int __sync_filesystem(struct super_block *sb, int wait)
29{ 29{
30 /*
31 * This should be safe, as we require bdi backing to actually
32 * write out data in the first place
33 */
34 if (!sb->s_bdi)
35 return 0;
36
30 /* Avoid doing twice syncing and cache pruning for quota sync */ 37 /* Avoid doing twice syncing and cache pruning for quota sync */
31 if (!wait) 38 if (!wait) {
32 writeout_quota_sb(sb, -1); 39 writeout_quota_sb(sb, -1);
33 else 40 writeback_inodes_sb(sb);
41 } else {
34 sync_quota_sb(sb, -1); 42 sync_quota_sb(sb, -1);
35 sync_inodes_sb(sb, wait); 43 sync_inodes_sb(sb);
44 }
36 if (sb->s_op->sync_fs) 45 if (sb->s_op->sync_fs)
37 sb->s_op->sync_fs(sb, wait); 46 sb->s_op->sync_fs(sb, wait);
38 return __sync_blockdev(sb->s_bdev, wait); 47 return __sync_blockdev(sb->s_bdev, wait);
@@ -99,7 +108,7 @@ restart:
99 spin_unlock(&sb_lock); 108 spin_unlock(&sb_lock);
100 109
101 down_read(&sb->s_umount); 110 down_read(&sb->s_umount);
102 if (!(sb->s_flags & MS_RDONLY) && sb->s_root) 111 if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
103 __sync_filesystem(sb, wait); 112 __sync_filesystem(sb, wait);
104 up_read(&sb->s_umount); 113 up_read(&sb->s_umount);
105 114
@@ -118,7 +127,7 @@ restart:
118 */ 127 */
119SYSCALL_DEFINE0(sync) 128SYSCALL_DEFINE0(sync)
120{ 129{
121 wakeup_pdflush(0); 130 wakeup_flusher_threads(0);
122 sync_filesystems(0); 131 sync_filesystems(0);
123 sync_filesystems(1); 132 sync_filesystems(1);
124 if (unlikely(laptop_mode)) 133 if (unlikely(laptop_mode))
@@ -176,19 +185,23 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
176} 185}
177 186
178/** 187/**
179 * vfs_fsync - perform a fsync or fdatasync on a file 188 * vfs_fsync_range - helper to sync a range of data & metadata to disk
180 * @file: file to sync 189 * @file: file to sync
181 * @dentry: dentry of @file 190 * @dentry: dentry of @file
182 * @data: only perform a fdatasync operation 191 * @start: offset in bytes of the beginning of data range to sync
192 * @end: offset in bytes of the end of data range (inclusive)
193 * @datasync: perform only datasync
183 * 194 *
184 * Write back data and metadata for @file to disk. If @datasync is 195 * Write back data in range @start..@end and metadata for @file to disk. If
185 * set only metadata needed to access modified file data is written. 196 * @datasync is set only metadata needed to access modified file data is
197 * written.
186 * 198 *
187 * In case this function is called from nfsd @file may be %NULL and 199 * In case this function is called from nfsd @file may be %NULL and
188 * only @dentry is set. This can only happen when the filesystem 200 * only @dentry is set. This can only happen when the filesystem
189 * implements the export_operations API. 201 * implements the export_operations API.
190 */ 202 */
191int vfs_fsync(struct file *file, struct dentry *dentry, int datasync) 203int vfs_fsync_range(struct file *file, struct dentry *dentry, loff_t start,
204 loff_t end, int datasync)
192{ 205{
193 const struct file_operations *fop; 206 const struct file_operations *fop;
194 struct address_space *mapping; 207 struct address_space *mapping;
@@ -212,7 +225,7 @@ int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
212 goto out; 225 goto out;
213 } 226 }
214 227
215 ret = filemap_fdatawrite(mapping); 228 ret = filemap_write_and_wait_range(mapping, start, end);
216 229
217 /* 230 /*
218 * We need to protect against concurrent writers, which could cause 231 * We need to protect against concurrent writers, which could cause
@@ -223,12 +236,29 @@ int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
223 if (!ret) 236 if (!ret)
224 ret = err; 237 ret = err;
225 mutex_unlock(&mapping->host->i_mutex); 238 mutex_unlock(&mapping->host->i_mutex);
226 err = filemap_fdatawait(mapping); 239
227 if (!ret)
228 ret = err;
229out: 240out:
230 return ret; 241 return ret;
231} 242}
243EXPORT_SYMBOL(vfs_fsync_range);
244
245/**
246 * vfs_fsync - perform a fsync or fdatasync on a file
247 * @file: file to sync
248 * @dentry: dentry of @file
249 * @datasync: only perform a fdatasync operation
250 *
251 * Write back data and metadata for @file to disk. If @datasync is
252 * set only metadata needed to access modified file data is written.
253 *
254 * In case this function is called from nfsd @file may be %NULL and
255 * only @dentry is set. This can only happen when the filesystem
256 * implements the export_operations API.
257 */
258int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
259{
260 return vfs_fsync_range(file, dentry, 0, LLONG_MAX, datasync);
261}
232EXPORT_SYMBOL(vfs_fsync); 262EXPORT_SYMBOL(vfs_fsync);
233 263
234static int do_fsync(unsigned int fd, int datasync) 264static int do_fsync(unsigned int fd, int datasync)
@@ -254,6 +284,23 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
254 return do_fsync(fd, 1); 284 return do_fsync(fd, 1);
255} 285}
256 286
287/**
288 * generic_write_sync - perform syncing after a write if file / inode is sync
289 * @file: file to which the write happened
290 * @pos: offset where the write started
291 * @count: length of the write
292 *
293 * This is just a simple wrapper about our general syncing function.
294 */
295int generic_write_sync(struct file *file, loff_t pos, loff_t count)
296{
297 if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host))
298 return 0;
299 return vfs_fsync_range(file, file->f_path.dentry, pos,
300 pos + count - 1, 1);
301}
302EXPORT_SYMBOL(generic_write_sync);
303
257/* 304/*
258 * sys_sync_file_range() permits finely controlled syncing over a segment of 305 * sys_sync_file_range() permits finely controlled syncing over a segment of
259 * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is 306 * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is