forked from luck/tmp_suning_uos_patched
fs/libfs.c: add generic data flush to fsync
Description by Jan Kara: "A lot of older filesystems don't properly flush volatile disk caches on fsync(2) which can lead to loss of fsynced data after power failure. This patch makes generic_file_fsync() issue proper cache flush to fix the problem. Sysadmin can use /sys/devices/.../cache_type to tell the system it should not send the cache flush." [akpm@linux-foundation.org: nuke ifdef] [akpm@linux-foundation.org: fix warning] Signed-off-by: Fabian Frederick <fabf@skynet.be> Suggested-by: Jan Kara <jack@suse.cz> Suggested-by: Christoph Hellwig <hch@infradead.org> Cc: Jan Kara <jack@suse.cz> Cc: Christoph Hellwig <hch@infradead.org> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
fd2916bd77
commit
ac13a829f6
34
fs/libfs.c
34
fs/libfs.c
|
@ -3,6 +3,7 @@
|
|||
* Library for filesystems writers.
|
||||
*/
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -923,16 +924,19 @@ struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|||
EXPORT_SYMBOL_GPL(generic_fh_to_parent);
|
||||
|
||||
/**
|
||||
* generic_file_fsync - generic fsync implementation for simple filesystems
|
||||
* __generic_file_fsync - generic fsync implementation for simple filesystems
|
||||
*
|
||||
* @file: file to synchronize
|
||||
* @start: start offset in bytes
|
||||
* @end: end offset in bytes (inclusive)
|
||||
* @datasync: only synchronize essential metadata if true
|
||||
*
|
||||
* This is a generic implementation of the fsync method for simple
|
||||
* filesystems which track all non-inode metadata in the buffers list
|
||||
* hanging off the address_space structure.
|
||||
*/
|
||||
int generic_file_fsync(struct file *file, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
int __generic_file_fsync(struct file *file, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
{
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
int err;
|
||||
|
@ -952,10 +956,34 @@ int generic_file_fsync(struct file *file, loff_t start, loff_t end,
|
|||
err = sync_inode_metadata(inode, 1);
|
||||
if (ret == 0)
|
||||
ret = err;
|
||||
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__generic_file_fsync);
|
||||
|
||||
/**
|
||||
* generic_file_fsync - generic fsync implementation for simple filesystems
|
||||
* with flush
|
||||
* @file: file to synchronize
|
||||
* @start: start offset in bytes
|
||||
* @end: end offset in bytes (inclusive)
|
||||
* @datasync: only synchronize essential metadata if true
|
||||
*
|
||||
*/
|
||||
|
||||
int generic_file_fsync(struct file *file, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
{
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
int err;
|
||||
|
||||
err = __generic_file_fsync(file, start, end, datasync);
|
||||
if (err)
|
||||
return err;
|
||||
return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_fsync);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1607,6 +1607,9 @@ struct block_device_operations {
|
|||
extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int,
|
||||
unsigned long);
|
||||
#else /* CONFIG_BLOCK */
|
||||
|
||||
struct block_device;
|
||||
|
||||
/*
|
||||
* stubs for when the block layer is configured out
|
||||
*/
|
||||
|
@ -1642,6 +1645,12 @@ static inline bool blk_needs_flush_plug(struct task_struct *tsk)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
|
||||
sector_t *error_sector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BLOCK */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2590,6 +2590,7 @@ extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
|
|||
extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
|
||||
const void __user *from, size_t count);
|
||||
|
||||
extern int __generic_file_fsync(struct file *, loff_t, loff_t, int);
|
||||
extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
|
||||
|
||||
extern int generic_check_addressable(unsigned, u64);
|
||||
|
|
Loading…
Reference in New Issue
Block a user