[PATCH] add -o flush for fat

Fat is commonly used on removable media.  Mounting with -o flush tells the
FS to write things to disk as quickly as possible.  It is like -o sync, but
much faster (and not as safe).

Signed-off-by: Chris Mason <mason@suse.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Chris Mason
2006-09-29 02:00:03 -07:00
committed by Linus Torvalds
parent 6b77df08a3
commit ae78bf9c4f
4 changed files with 83 additions and 3 deletions

View File

@@ -24,6 +24,7 @@
#include <linux/vfs.h>
#include <linux/parser.h>
#include <linux/uio.h>
#include <linux/writeback.h>
#include <asm/unaligned.h>
#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -853,7 +854,7 @@ enum {
Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
Opt_obsolate, Opt_err,
Opt_obsolate, Opt_flush, Opt_err,
};
static match_table_t fat_tokens = {
@@ -885,7 +886,8 @@ static match_table_t fat_tokens = {
{Opt_obsolate, "cvf_format=%20s"},
{Opt_obsolate, "cvf_options=%100s"},
{Opt_obsolate, "posix"},
{Opt_err, NULL}
{Opt_flush, "flush"},
{Opt_err, NULL},
};
static match_table_t msdos_tokens = {
{Opt_nodots, "nodots"},
@@ -1026,6 +1028,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
return 0;
opts->codepage = option;
break;
case Opt_flush:
opts->flush = 1;
break;
/* msdos specific */
case Opt_dots:
@@ -1425,6 +1430,56 @@ out_fail:
EXPORT_SYMBOL_GPL(fat_fill_super);
/*
* helper function for fat_flush_inodes. This writes both the inode
* and the file data blocks, waiting for in flight data blocks before
* the start of the call. It does not wait for any io started
* during the call
*/
static int writeback_inode(struct inode *inode)
{
int ret;
struct address_space *mapping = inode->i_mapping;
struct writeback_control wbc = {
.sync_mode = WB_SYNC_NONE,
.nr_to_write = 0,
};
/* if we used WB_SYNC_ALL, sync_inode waits for the io for the
* inode to finish. So WB_SYNC_NONE is sent down to sync_inode
* and filemap_fdatawrite is used for the data blocks
*/
ret = sync_inode(inode, &wbc);
if (!ret)
ret = filemap_fdatawrite(mapping);
return ret;
}
/*
* write data and metadata corresponding to i1 and i2. The io is
* started but we do not wait for any of it to finish.
*
* filemap_flush is used for the block device, so if there is a dirty
* page for a block already in flight, we will not wait and start the
* io over again
*/
int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2)
{
int ret = 0;
if (!MSDOS_SB(sb)->options.flush)
return 0;
if (i1)
ret = writeback_inode(i1);
if (!ret && i2)
ret = writeback_inode(i2);
if (!ret && sb) {
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
ret = filemap_flush(mapping);
}
return ret;
}
EXPORT_SYMBOL_GPL(fat_flush_inodes);
static int __init init_fat_fs(void)
{
int err;