All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Mason <mason@suse.com>
To: Andrew Morton <akpm@osdl.org>
Cc: col-pepper@piments.com, linux-kernel@vger.kernel.org
Subject: Re: o_sync in vfat driver
Date: Tue, 28 Feb 2006 13:47:43 -0500	[thread overview]
Message-ID: <200602281347.46169.mason@suse.com> (raw)
In-Reply-To: <20060227151230.695de2af.akpm@osdl.org>

On Monday 27 February 2006 18:12, Andrew Morton wrote:

> We don't know that the same number of same-sized write()s were happening in
> each case.
>
> There's been some talk about implementing fsync()-on-file-close for this
> problem, and some protopatches.  But nothing final yet.

Here's the patch I'm using in -suse right now.  What I want to do is make a 
much more generic -o flush, but it'll still need a few bits in individual 
filesystem to kick off metadata writes quickly.

The basic goal behind the code is to trigger writes without waiting for both
data and metadata.  If the user is watching the memory stick, when the 
little light stops flashing all the data and metadata will be on disk.

It also generally throttles userland a little during file release.  This 
could be changed to throttle for each page dirtied, but most users I 
asked liked the current setup better.

-chris

From: Chris Mason <mason@suse.com>
Subject: 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).

diff -r a06cef570da0 fs/fat/file.c
--- a/fs/fat/file.c	Sun Jan 15 11:59:32 2006 -0500
+++ b/fs/fat/file.c	Sun Jan 15 13:00:35 2006 -0500
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/blkdev.h>
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg)
@@ -112,6 +113,19 @@ int fat_generic_ioctl(struct inode *inod
 	}
 }
 
+static int
+fat_file_release(struct inode *inode, struct file *filp)
+{
+
+	if ((filp->f_mode & FMODE_WRITE) &&
+	     MSDOS_SB(inode->i_sb)->options.flush) {
+		writeback_inode(inode);
+		writeback_bdev(inode->i_sb);
+		blk_congestion_wait(WRITE, HZ/10);
+	}
+	return 0;
+}
+
 struct file_operations fat_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
@@ -121,6 +135,7 @@ struct file_operations fat_file_operatio
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
+	.release	= fat_file_release,
 	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
 	.sendfile	= generic_file_sendfile,
@@ -293,6 +308,10 @@ void fat_truncate(struct inode *inode)
 	lock_kernel();
 	fat_free(inode, nr_clusters);
 	unlock_kernel();
+	if (MSDOS_SB(inode->i_sb)->options.flush) {
+		writeback_inode(inode);
+		writeback_bdev(inode->i_sb);
+	}
 }
 
 struct inode_operations fat_file_inode_operations = {
diff -r a06cef570da0 fs/fat/inode.c
--- a/fs/fat/inode.c	Sun Jan 15 11:59:32 2006 -0500
+++ b/fs/fat/inode.c	Sun Jan 15 13:00:35 2006 -0500
@@ -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
@@ -860,7 +861,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 = {
@@ -892,7 +893,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"},
@@ -1033,6 +1035,9 @@ static int parse_options(char *options, 
 				return 0;
 			opts->codepage = option;
 			break;
+		case Opt_flush:
+			opts->flush = 1;
+			break;
 
 		/* msdos specific */
 		case Opt_dots:
diff -r a06cef570da0 fs/fs-writeback.c
--- a/fs/fs-writeback.c	Sun Jan 15 11:59:32 2006 -0500
+++ b/fs/fs-writeback.c	Sun Jan 15 13:00:35 2006 -0500
@@ -390,6 +390,29 @@ sync_sb_inodes(struct super_block *sb, s
 	return;		/* Leave any unwritten inodes on s_io */
 }
 
+void
+writeback_bdev(struct super_block *sb)
+{
+	struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+	filemap_flush(mapping);
+	blk_run_address_space(mapping);
+}
+EXPORT_SYMBOL_GPL(writeback_bdev);
+
+void
+writeback_inode(struct inode *inode)
+{
+
+	struct address_space *mapping = inode->i_mapping;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_NONE,
+		.nr_to_write = 0,
+	};
+	sync_inode(inode, &wbc);
+	filemap_fdatawrite(mapping);
+}
+EXPORT_SYMBOL_GPL(writeback_inode);
+
 /*
  * Start writeback of dirty pagecache data against all unlocked inodes.
  *
diff -r a06cef570da0 fs/msdos/namei.c
--- a/fs/msdos/namei.c	Sun Jan 15 11:59:32 2006 -0500
+++ b/fs/msdos/namei.c	Sun Jan 15 13:00:35 2006 -0500
@@ -11,6 +11,7 @@
 #include <linux/buffer_head.h>
 #include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
+#include <linux/writeback.h>
 
 /* MS-DOS "device special files" */
 static const unsigned char *reserved_names[] = {
@@ -293,7 +294,7 @@ static int msdos_create(struct inode *di
 			struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
-	struct inode *inode;
+	struct inode *inode = NULL;
 	struct fat_slot_info sinfo;
 	struct timespec ts;
 	unsigned char msdos_name[MSDOS_NAME];
@@ -329,6 +330,11 @@ static int msdos_create(struct inode *di
 	d_instantiate(dentry, inode);
 out:
 	unlock_kernel();
+	if (!err && MSDOS_SB(sb)->options.flush) {
+		writeback_inode(dir);
+		writeback_inode(inode);
+		writeback_bdev(sb);
+	}
 	return err;
 }
 
@@ -361,6 +367,11 @@ static int msdos_rmdir(struct inode *dir
 	fat_detach(inode);
 out:
 	unlock_kernel();
+	if (!err && MSDOS_SB(inode->i_sb)->options.flush) {
+		writeback_inode(dir);
+		writeback_inode(inode);
+		writeback_bdev(inode->i_sb);
+	}
 
 	return err;
 }
@@ -414,6 +425,11 @@ static int msdos_mkdir(struct inode *dir
 	d_instantiate(dentry, inode);
 
 	unlock_kernel();
+	if (MSDOS_SB(sb)->options.flush) {
+		writeback_inode(dir);
+		writeback_inode(inode);
+		writeback_bdev(sb);
+	}
 	return 0;
 
 out_free:
@@ -443,6 +459,11 @@ static int msdos_unlink(struct inode *di
 	fat_detach(inode);
 out:
 	unlock_kernel();
+	if (!err && MSDOS_SB(inode->i_sb)->options.flush) {
+		writeback_inode(dir);
+		writeback_inode(inode);
+		writeback_bdev(inode->i_sb);
+	}
 
 	return err;
 }
@@ -648,6 +669,11 @@ static int msdos_rename(struct inode *ol
 			      new_dir, new_msdos_name, new_dentry, is_hid);
 out:
 	unlock_kernel();
+	if (!err && MSDOS_SB(old_dir->i_sb)->options.flush) {
+		writeback_inode(old_dir);
+		writeback_inode(new_dir);
+		writeback_bdev(old_dir->i_sb);
+	}
 	return err;
 }
 
diff -r a06cef570da0 include/linux/msdos_fs.h
--- a/include/linux/msdos_fs.h	Sun Jan 15 11:59:32 2006 -0500
+++ b/include/linux/msdos_fs.h	Sun Jan 15 13:00:35 2006 -0500
@@ -203,6 +203,7 @@ struct fat_mount_options {
 		 unicode_xlate:1, /* create escape sequences for unhandled Unicode */
 		 numtail:1,       /* Does first alias have a numeric '~1' type tail? */
 		 atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */
+		 flush:1,	  /* write things quickly */
 		 nocase:1;	  /* Does this need case conversion? 0=need case conversion*/
 };
 
diff -r a06cef570da0 include/linux/writeback.h
--- a/include/linux/writeback.h	Sun Jan 15 11:59:32 2006 -0500
+++ b/include/linux/writeback.h	Sun Jan 15 13:00:35 2006 -0500
@@ -68,6 +68,8 @@ int inode_wait(void *);
 int inode_wait(void *);
 void sync_inodes_sb(struct super_block *, int wait);
 void sync_inodes(int wait);
+void writeback_bdev(struct super_block *);
+void writeback_inode(struct inode *);
 
 /* writeback.h requires fs.h; it, too, is not included from here. */
 static inline void wait_on_inode(struct inode *inode)

  reply	other threads:[~2006-02-28 18:48 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-26 23:08 o_sync in vfat driver col-pepper
2006-02-27  0:51 ` Andrew Morton
2006-02-27 22:19   ` col-pepper
2006-02-27 23:12     ` Andrew Morton
2006-02-28 18:47       ` Chris Mason [this message]
2006-02-28 19:10         ` Andrew Morton
2006-02-28 19:48           ` Chris Mason
     [not found]         ` <87u0aiw6pi.fsf@duaron.myhome.or.jp>
2006-03-01 15:23           ` Chris Mason
     [not found]             ` <87mzg9wst0.fsf@duaron.myhome.or.jp>
2006-03-02 13:45               ` Chris Mason
2006-03-02 14:07                 ` OGAWA Hirofumi
2006-03-02 17:01                   ` Chris Mason
2006-03-02 18:14                     ` OGAWA Hirofumi
2006-03-29  2:13         ` Mathis Ahrens
2006-03-30 17:35           ` col-pepper
2006-02-28  0:52     ` Machida, Hiroyuki
  -- strict thread matches above, loose matches on Subject: below --
2006-02-26 22:55 col-pepper
     [not found] <op.s5cj47sxj68xd1@mail.piments.com>
     [not found] ` <op.s5jpqvwhui3qek@mail.piments.com>
     [not found]   ` <op.s5kxhyzgfx0war@mail.piments.com>
     [not found]     ` <op.s5kx7xhfj68xd1@mail.piments.com>
     [not found]       ` <op.s5kya3t0j68xd1@mail.piments.com>
     [not found]         ` <op.s5ky2dbcj68xd1@mail.piments.com>
     [not found]           ` <op.s5ky71nwj68xd1@mail.piments.com>
     [not found]             ` <op.s5kzao2jj68xd1@mail.piments.com>
2006-02-26 22:50               ` col-pepper
2006-02-27 13:28                 ` Lennart Sorensen
2006-02-27 13:50                   ` Arjan van de Ven
2006-02-27 14:06                     ` Anton Altaparmakov
2006-02-27 14:27                       ` Arjan van de Ven
2006-02-27 14:41                         ` Anton Altaparmakov
2006-02-27 21:04                           ` col-pepper
2006-02-27 21:17                             ` Arjan van de Ven
2006-02-27 23:21                               ` col-pepper
2006-02-27 21:32                             ` linux-os (Dick Johnson)
2006-02-27 23:21                               ` col-pepper
2006-02-28 13:10                                 ` linux-os (Dick Johnson)
2006-02-28 13:52                                   ` Sergei Organov
2006-02-28 15:18                                   ` Lennart Sorensen
2006-02-28 16:16                                     ` linux-os (Dick Johnson)
2006-02-28 17:23                                       ` Sergei Organov
2006-02-28 18:09                                       ` Krzysztof Halasa
2006-02-28 17:16                                   ` col-pepper
2006-02-28 22:38                                 ` Pavel Machek
2006-03-01  4:28                                   ` Kyle Moffett
2006-03-02  8:23                                   ` col-pepper
2006-03-02  8:32                                     ` Pavel Machek
2006-02-28 16:11                             ` Helge Hafting
2006-02-28 22:37                             ` Pavel Machek
2006-02-27 14:26                   ` linux-os (Dick Johnson)
2006-02-27 18:53                     ` Jan Engelhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200602281347.46169.mason@suse.com \
    --to=mason@suse.com \
    --cc=akpm@osdl.org \
    --cc=col-pepper@piments.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.