aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sync.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 22:37:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 22:37:45 -0400
commite8bebe2f71d26871b0970ae1d9cf0ed3cdd9569d (patch)
treec0d82cbd11daaf579b74121c6641d58947091094 /fs/sync.c
parent6109e2ce2600e2db26cd0424bb9c6ed019723288 (diff)
parent82f3952c02add60b15eea9151d4d99b6b82066c6 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (69 commits) fix handling of offsets in cris eeprom.c, get rid of fake on-stack files get rid of home-grown mutex in cris eeprom.c switch ecryptfs_write() to struct inode *, kill on-stack fake files switch ecryptfs_get_locked_page() to struct inode * simplify access to ecryptfs inodes in ->readpage() and friends AFS: Don't put struct file on the stack Ban ecryptfs over ecryptfs logfs: replace inode uid,gid,mode initialization with helper function ufs: replace inode uid,gid,mode initialization with helper function udf: replace inode uid,gid,mode init with helper ubifs: replace inode uid,gid,mode initialization with helper function sysv: replace inode uid,gid,mode initialization with helper function reiserfs: replace inode uid,gid,mode initialization with helper function ramfs: replace inode uid,gid,mode initialization with helper function omfs: replace inode uid,gid,mode initialization with helper function bfs: replace inode uid,gid,mode initialization with helper function ocfs2: replace inode uid,gid,mode initialization with helper function nilfs2: replace inode uid,gid,mode initialization with helper function minix: replace inode uid,gid,mode init with helper ext4: replace inode uid,gid,mode init with helper ... Trivial conflict in fs/fs-writeback.c (mark bitfields unsigned)
Diffstat (limited to 'fs/sync.c')
-rw-r--r--fs/sync.c86
1 files changed, 14 insertions, 72 deletions
diff --git a/fs/sync.c b/fs/sync.c
index de6a44192832..e8cbd415e50a 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -77,50 +77,18 @@ int sync_filesystem(struct super_block *sb)
77} 77}
78EXPORT_SYMBOL_GPL(sync_filesystem); 78EXPORT_SYMBOL_GPL(sync_filesystem);
79 79
80static void sync_one_sb(struct super_block *sb, void *arg)
81{
82 if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi)
83 __sync_filesystem(sb, *(int *)arg);
84}
80/* 85/*
81 * Sync all the data for all the filesystems (called by sys_sync() and 86 * Sync all the data for all the filesystems (called by sys_sync() and
82 * emergency sync) 87 * emergency sync)
83 *
84 * This operation is careful to avoid the livelock which could easily happen
85 * if two or more filesystems are being continuously dirtied. s_need_sync
86 * is used only here. We set it against all filesystems and then clear it as
87 * we sync them. So redirtied filesystems are skipped.
88 *
89 * But if process A is currently running sync_filesystems and then process B
90 * calls sync_filesystems as well, process B will set all the s_need_sync
91 * flags again, which will cause process A to resync everything. Fix that with
92 * a local mutex.
93 */ 88 */
94static void sync_filesystems(int wait) 89static void sync_filesystems(int wait)
95{ 90{
96 struct super_block *sb; 91 iterate_supers(sync_one_sb, &wait);
97 static DEFINE_MUTEX(mutex);
98
99 mutex_lock(&mutex); /* Could be down_interruptible */
100 spin_lock(&sb_lock);
101 list_for_each_entry(sb, &super_blocks, s_list)
102 sb->s_need_sync = 1;
103
104restart:
105 list_for_each_entry(sb, &super_blocks, s_list) {
106 if (!sb->s_need_sync)
107 continue;
108 sb->s_need_sync = 0;
109 sb->s_count++;
110 spin_unlock(&sb_lock);
111
112 down_read(&sb->s_umount);
113 if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
114 __sync_filesystem(sb, wait);
115 up_read(&sb->s_umount);
116
117 /* restart only when sb is no longer on the list */
118 spin_lock(&sb_lock);
119 if (__put_super_and_need_restart(sb))
120 goto restart;
121 }
122 spin_unlock(&sb_lock);
123 mutex_unlock(&mutex);
124} 92}
125 93
126/* 94/*
@@ -190,7 +158,6 @@ EXPORT_SYMBOL(file_fsync);
190/** 158/**
191 * vfs_fsync_range - helper to sync a range of data & metadata to disk 159 * vfs_fsync_range - helper to sync a range of data & metadata to disk
192 * @file: file to sync 160 * @file: file to sync
193 * @dentry: dentry of @file
194 * @start: offset in bytes of the beginning of data range to sync 161 * @start: offset in bytes of the beginning of data range to sync
195 * @end: offset in bytes of the end of data range (inclusive) 162 * @end: offset in bytes of the end of data range (inclusive)
196 * @datasync: perform only datasync 163 * @datasync: perform only datasync
@@ -198,32 +165,13 @@ EXPORT_SYMBOL(file_fsync);
198 * Write back data in range @start..@end and metadata for @file to disk. If 165 * Write back data in range @start..@end and metadata for @file to disk. If
199 * @datasync is set only metadata needed to access modified file data is 166 * @datasync is set only metadata needed to access modified file data is
200 * written. 167 * written.
201 *
202 * In case this function is called from nfsd @file may be %NULL and
203 * only @dentry is set. This can only happen when the filesystem
204 * implements the export_operations API.
205 */ 168 */
206int vfs_fsync_range(struct file *file, struct dentry *dentry, loff_t start, 169int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
207 loff_t end, int datasync)
208{ 170{
209 const struct file_operations *fop; 171 struct address_space *mapping = file->f_mapping;
210 struct address_space *mapping;
211 int err, ret; 172 int err, ret;
212 173
213 /* 174 if (!file->f_op || !file->f_op->fsync) {
214 * Get mapping and operations from the file in case we have
215 * as file, or get the default values for them in case we
216 * don't have a struct file available. Damn nfsd..
217 */
218 if (file) {
219 mapping = file->f_mapping;
220 fop = file->f_op;
221 } else {
222 mapping = dentry->d_inode->i_mapping;
223 fop = dentry->d_inode->i_fop;
224 }
225
226 if (!fop || !fop->fsync) {
227 ret = -EINVAL; 175 ret = -EINVAL;
228 goto out; 176 goto out;
229 } 177 }
@@ -235,7 +183,7 @@ int vfs_fsync_range(struct file *file, struct dentry *dentry, loff_t start,
235 * livelocks in fsync_buffers_list(). 183 * livelocks in fsync_buffers_list().
236 */ 184 */
237 mutex_lock(&mapping->host->i_mutex); 185 mutex_lock(&mapping->host->i_mutex);
238 err = fop->fsync(file, dentry, datasync); 186 err = file->f_op->fsync(file, file->f_path.dentry, datasync);
239 if (!ret) 187 if (!ret)
240 ret = err; 188 ret = err;
241 mutex_unlock(&mapping->host->i_mutex); 189 mutex_unlock(&mapping->host->i_mutex);
@@ -248,19 +196,14 @@ EXPORT_SYMBOL(vfs_fsync_range);
248/** 196/**
249 * vfs_fsync - perform a fsync or fdatasync on a file 197 * vfs_fsync - perform a fsync or fdatasync on a file
250 * @file: file to sync 198 * @file: file to sync
251 * @dentry: dentry of @file
252 * @datasync: only perform a fdatasync operation 199 * @datasync: only perform a fdatasync operation
253 * 200 *
254 * Write back data and metadata for @file to disk. If @datasync is 201 * Write back data and metadata for @file to disk. If @datasync is
255 * set only metadata needed to access modified file data is written. 202 * set only metadata needed to access modified file data is written.
256 *
257 * In case this function is called from nfsd @file may be %NULL and
258 * only @dentry is set. This can only happen when the filesystem
259 * implements the export_operations API.
260 */ 203 */
261int vfs_fsync(struct file *file, struct dentry *dentry, int datasync) 204int vfs_fsync(struct file *file, int datasync)
262{ 205{
263 return vfs_fsync_range(file, dentry, 0, LLONG_MAX, datasync); 206 return vfs_fsync_range(file, 0, LLONG_MAX, datasync);
264} 207}
265EXPORT_SYMBOL(vfs_fsync); 208EXPORT_SYMBOL(vfs_fsync);
266 209
@@ -271,7 +214,7 @@ static int do_fsync(unsigned int fd, int datasync)
271 214
272 file = fget(fd); 215 file = fget(fd);
273 if (file) { 216 if (file) {
274 ret = vfs_fsync(file, file->f_path.dentry, datasync); 217 ret = vfs_fsync(file, datasync);
275 fput(file); 218 fput(file);
276 } 219 }
277 return ret; 220 return ret;
@@ -299,8 +242,7 @@ int generic_write_sync(struct file *file, loff_t pos, loff_t count)
299{ 242{
300 if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host)) 243 if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
301 return 0; 244 return 0;
302 return vfs_fsync_range(file, file->f_path.dentry, pos, 245 return vfs_fsync_range(file, pos, pos + count - 1,
303 pos + count - 1,
304 (file->f_flags & __O_SYNC) ? 0 : 1); 246 (file->f_flags & __O_SYNC) ? 0 : 1);
305} 247}
306EXPORT_SYMBOL(generic_write_sync); 248EXPORT_SYMBOL(generic_write_sync);