diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 24262ea8cc50..6d77ce9f54e5 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -327,31 +327,24 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync) | |||
327 | return ret; | 327 | return ret; |
328 | } | 328 | } |
329 | 329 | ||
330 | static long do_fsync(unsigned int fd, int datasync) | 330 | long do_fsync(struct file *file, int datasync) |
331 | { | 331 | { |
332 | struct file * file; | 332 | int ret; |
333 | struct address_space *mapping; | 333 | int err; |
334 | int ret, err; | 334 | struct address_space *mapping = file->f_mapping; |
335 | |||
336 | ret = -EBADF; | ||
337 | file = fget(fd); | ||
338 | if (!file) | ||
339 | goto out; | ||
340 | 335 | ||
341 | ret = -EINVAL; | ||
342 | if (!file->f_op || !file->f_op->fsync) { | 336 | if (!file->f_op || !file->f_op->fsync) { |
343 | /* Why? We can still call filemap_fdatawrite */ | 337 | /* Why? We can still call filemap_fdatawrite */ |
344 | goto out_putf; | 338 | ret = -EINVAL; |
339 | goto out; | ||
345 | } | 340 | } |
346 | 341 | ||
347 | mapping = file->f_mapping; | ||
348 | |||
349 | current->flags |= PF_SYNCWRITE; | 342 | current->flags |= PF_SYNCWRITE; |
350 | ret = filemap_fdatawrite(mapping); | 343 | ret = filemap_fdatawrite(mapping); |
351 | 344 | ||
352 | /* | 345 | /* |
353 | * We need to protect against concurrent writers, | 346 | * We need to protect against concurrent writers, which could cause |
354 | * which could cause livelocks in fsync_buffers_list | 347 | * livelocks in fsync_buffers_list(). |
355 | */ | 348 | */ |
356 | mutex_lock(&mapping->host->i_mutex); | 349 | mutex_lock(&mapping->host->i_mutex); |
357 | err = file->f_op->fsync(file, file->f_dentry, datasync); | 350 | err = file->f_op->fsync(file, file->f_dentry, datasync); |
@@ -362,21 +355,31 @@ static long do_fsync(unsigned int fd, int datasync) | |||
362 | if (!ret) | 355 | if (!ret) |
363 | ret = err; | 356 | ret = err; |
364 | current->flags &= ~PF_SYNCWRITE; | 357 | current->flags &= ~PF_SYNCWRITE; |
365 | |||
366 | out_putf: | ||
367 | fput(file); | ||
368 | out: | 358 | out: |
369 | return ret; | 359 | return ret; |
370 | } | 360 | } |
371 | 361 | ||
362 | static long __do_fsync(unsigned int fd, int datasync) | ||
363 | { | ||
364 | struct file *file; | ||
365 | int ret = -EBADF; | ||
366 | |||
367 | file = fget(fd); | ||
368 | if (file) { | ||
369 | ret = do_fsync(file, datasync); | ||
370 | fput(file); | ||
371 | } | ||
372 | return ret; | ||
373 | } | ||
374 | |||
372 | asmlinkage long sys_fsync(unsigned int fd) | 375 | asmlinkage long sys_fsync(unsigned int fd) |
373 | { | 376 | { |
374 | return do_fsync(fd, 0); | 377 | return __do_fsync(fd, 0); |
375 | } | 378 | } |
376 | 379 | ||
377 | asmlinkage long sys_fdatasync(unsigned int fd) | 380 | asmlinkage long sys_fdatasync(unsigned int fd) |
378 | { | 381 | { |
379 | return do_fsync(fd, 1); | 382 | return __do_fsync(fd, 1); |
380 | } | 383 | } |
381 | 384 | ||
382 | /* | 385 | /* |