diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 22:37:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 22:37:45 -0400 |
commit | e8bebe2f71d26871b0970ae1d9cf0ed3cdd9569d (patch) | |
tree | c0d82cbd11daaf579b74121c6641d58947091094 /fs/sync.c | |
parent | 6109e2ce2600e2db26cd0424bb9c6ed019723288 (diff) | |
parent | 82f3952c02add60b15eea9151d4d99b6b82066c6 (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.c | 86 |
1 files changed, 14 insertions, 72 deletions
@@ -77,50 +77,18 @@ int sync_filesystem(struct super_block *sb) | |||
77 | } | 77 | } |
78 | EXPORT_SYMBOL_GPL(sync_filesystem); | 78 | EXPORT_SYMBOL_GPL(sync_filesystem); |
79 | 79 | ||
80 | static 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 | */ |
94 | static void sync_filesystems(int wait) | 89 | static 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 | |||
104 | restart: | ||
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 | */ |
206 | int vfs_fsync_range(struct file *file, struct dentry *dentry, loff_t start, | 169 | int 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 | */ |
261 | int vfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 204 | int 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 | } |
265 | EXPORT_SYMBOL(vfs_fsync); | 208 | EXPORT_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 | } |
306 | EXPORT_SYMBOL(generic_write_sync); | 248 | EXPORT_SYMBOL(generic_write_sync); |