aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2009-10-27 06:05:28 -0400
committerJan Kara <jack@suse.cz>2009-12-10 09:02:50 -0500
commit6b2f3d1f769be5779b479c37800229d9a4809fc3 (patch)
tree046ef6736ec6c25ab1c68741ba715d13645af336
parent59bc055211b8d266ab6089158058bf8268e02006 (diff)
vfs: Implement proper O_SYNC semantics
While Linux provided an O_SYNC flag basically since day 1, it took until Linux 2.4.0-test12pre2 to actually get it implemented for filesystems, since that day we had generic_osync_around with only minor changes and the great "For now, when the user asks for O_SYNC, we'll actually give O_DSYNC" comment. This patch intends to actually give us real O_SYNC semantics in addition to the O_DSYNC semantics. After Jan's O_SYNC patches which are required before this patch it's actually surprisingly simple, we just need to figure out when to set the datasync flag to vfs_fsync_range and when not. This patch renames the existing O_SYNC flag to O_DSYNC while keeping it's numerical value to keep binary compatibility, and adds a new real O_SYNC flag. To guarantee backwards compatiblity it is defined as expanding to both the O_DSYNC and the new additional binary flag (__O_SYNC) to make sure we are backwards-compatible when compiled against the new headers. This also means that all places that don't care about the differences can just check O_DSYNC and get the right behaviour for O_SYNC, too - only places that actuall care need to check __O_SYNC in addition. Drivers and network filesystems have been updated in a fail safe way to always do the full sync magic if O_DSYNC is set. The few places setting O_SYNC for lower layers are kept that way for now to stay failsafe. We enforce that O_DSYNC is set when __O_SYNC is set early in the open path to make sure we always get these sane options. Note that parisc really screwed up their headers as they already define a O_DSYNC that has always been a no-op. We try to repair it by using it for the new O_DSYNC and redefinining O_SYNC to send both the traditional O_SYNC numerical value _and_ the O_DSYNC one. Cc: Richard Henderson <rth@twiddle.net> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Grant Grundler <grundler@parisc-linux.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Ingo Molnar <mingo@elte.hu> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Andreas Dilger <adilger@sun.com> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Acked-by: Kyle McMartin <kyle@mcmartin.ca> Acked-by: Ulrich Drepper <drepper@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--arch/alpha/include/asm/fcntl.h19
-rw-r--r--arch/blackfin/include/asm/fcntl.h2
-rw-r--r--arch/mips/include/asm/fcntl.h17
-rw-r--r--arch/mips/kernel/kspd.c1
-rw-r--r--arch/mips/loongson/common/mem.c2
-rw-r--r--arch/mips/mm/cache.c2
-rw-r--r--arch/parisc/include/asm/fcntl.h5
-rw-r--r--arch/sparc/include/asm/fcntl.h19
-rw-r--r--arch/x86/mm/pat.c3
-rw-r--r--drivers/char/mem.c6
-rw-r--r--drivers/usb/gadget/file_storage.c2
-rw-r--r--fs/afs/write.c5
-rw-r--r--fs/btrfs/file.c4
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/namei.c9
-rw-r--r--fs/nfs/file.c4
-rw-r--r--fs/nfs/write.c2
-rw-r--r--fs/ocfs2/file.c2
-rw-r--r--fs/sync.c5
-rw-r--r--fs/ubifs/file.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c2
-rw-r--r--include/asm-generic/fcntl.h25
-rw-r--r--sound/core/rawmidi.c2
24 files changed, 109 insertions, 40 deletions
diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h
index 25da0017ec87..21b1117a0c61 100644
--- a/arch/alpha/include/asm/fcntl.h
+++ b/arch/alpha/include/asm/fcntl.h
@@ -1,8 +1,6 @@
1#ifndef _ALPHA_FCNTL_H 1#ifndef _ALPHA_FCNTL_H
2#define _ALPHA_FCNTL_H 2#define _ALPHA_FCNTL_H
3 3
4/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
5 located on an ext2 file system */
6#define O_CREAT 01000 /* not fcntl */ 4#define O_CREAT 01000 /* not fcntl */
7#define O_TRUNC 02000 /* not fcntl */ 5#define O_TRUNC 02000 /* not fcntl */
8#define O_EXCL 04000 /* not fcntl */ 6#define O_EXCL 04000 /* not fcntl */
@@ -10,13 +8,28 @@
10 8
11#define O_NONBLOCK 00004 9#define O_NONBLOCK 00004
12#define O_APPEND 00010 10#define O_APPEND 00010
13#define O_SYNC 040000 11#define O_DSYNC 040000 /* used to be O_SYNC, see below */
14#define O_DIRECTORY 0100000 /* must be a directory */ 12#define O_DIRECTORY 0100000 /* must be a directory */
15#define O_NOFOLLOW 0200000 /* don't follow links */ 13#define O_NOFOLLOW 0200000 /* don't follow links */
16#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */ 14#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */
17#define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */ 15#define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */
18#define O_NOATIME 04000000 16#define O_NOATIME 04000000
19#define O_CLOEXEC 010000000 /* set close_on_exec */ 17#define O_CLOEXEC 010000000 /* set close_on_exec */
18/*
19 * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
20 * the O_SYNC flag. We continue to use the existing numerical value
21 * for O_DSYNC semantics now, but using the correct symbolic name for it.
22 * This new value is used to request true Posix O_SYNC semantics. It is
23 * defined in this strange way to make sure applications compiled against
24 * new headers get at least O_DSYNC semantics on older kernels.
25 *
26 * This has the nice side-effect that we can simply test for O_DSYNC
27 * wherever we do not care if O_DSYNC or O_SYNC is used.
28 *
29 * Note: __O_SYNC must never be used directly.
30 */
31#define __O_SYNC 020000000
32#define O_SYNC (__O_SYNC|O_DSYNC)
20 33
21#define F_GETLK 7 34#define F_GETLK 7
22#define F_SETLK 8 35#define F_SETLK 8
diff --git a/arch/blackfin/include/asm/fcntl.h b/arch/blackfin/include/asm/fcntl.h
index 8727b2b382f1..251c911d59c1 100644
--- a/arch/blackfin/include/asm/fcntl.h
+++ b/arch/blackfin/include/asm/fcntl.h
@@ -7,8 +7,6 @@
7#ifndef _BFIN_FCNTL_H 7#ifndef _BFIN_FCNTL_H
8#define _BFIN_FCNTL_H 8#define _BFIN_FCNTL_H
9 9
10/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
11 located on an ext2 file system */
12#define O_DIRECTORY 040000 /* must be a directory */ 10#define O_DIRECTORY 040000 /* must be a directory */
13#define O_NOFOLLOW 0100000 /* don't follow links */ 11#define O_NOFOLLOW 0100000 /* don't follow links */
14#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ 12#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h
index 2a52333a062d..7c6681aa2ab8 100644
--- a/arch/mips/include/asm/fcntl.h
+++ b/arch/mips/include/asm/fcntl.h
@@ -10,7 +10,7 @@
10 10
11 11
12#define O_APPEND 0x0008 12#define O_APPEND 0x0008
13#define O_SYNC 0x0010 13#define O_DSYNC 0x0010 /* used to be O_SYNC, see below */
14#define O_NONBLOCK 0x0080 14#define O_NONBLOCK 0x0080
15#define O_CREAT 0x0100 /* not fcntl */ 15#define O_CREAT 0x0100 /* not fcntl */
16#define O_TRUNC 0x0200 /* not fcntl */ 16#define O_TRUNC 0x0200 /* not fcntl */
@@ -18,6 +18,21 @@
18#define O_NOCTTY 0x0800 /* not fcntl */ 18#define O_NOCTTY 0x0800 /* not fcntl */
19#define FASYNC 0x1000 /* fcntl, for BSD compatibility */ 19#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
20#define O_LARGEFILE 0x2000 /* allow large file opens */ 20#define O_LARGEFILE 0x2000 /* allow large file opens */
21/*
22 * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
23 * the O_SYNC flag. We continue to use the existing numerical value
24 * for O_DSYNC semantics now, but using the correct symbolic name for it.
25 * This new value is used to request true Posix O_SYNC semantics. It is
26 * defined in this strange way to make sure applications compiled against
27 * new headers get at least O_DSYNC semantics on older kernels.
28 *
29 * This has the nice side-effect that we can simply test for O_DSYNC
30 * wherever we do not care if O_DSYNC or O_SYNC is used.
31 *
32 * Note: __O_SYNC must never be used directly.
33 */
34#define __O_SYNC 0x4000
35#define O_SYNC (__O_SYNC|O_DSYNC)
21#define O_DIRECT 0x8000 /* direct disk access hint */ 36#define O_DIRECT 0x8000 /* direct disk access hint */
22 37
23#define F_GETLK 14 38#define F_GETLK 14
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index ad4e017ed2f3..80e2ba694bab 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -82,6 +82,7 @@ static int sp_stopping;
82#define MTSP_O_SHLOCK 0x0010 82#define MTSP_O_SHLOCK 0x0010
83#define MTSP_O_EXLOCK 0x0020 83#define MTSP_O_EXLOCK 0x0020
84#define MTSP_O_ASYNC 0x0040 84#define MTSP_O_ASYNC 0x0040
85/* XXX: check which of these is actually O_SYNC vs O_DSYNC */
85#define MTSP_O_FSYNC O_SYNC 86#define MTSP_O_FSYNC O_SYNC
86#define MTSP_O_NOFOLLOW 0x0100 87#define MTSP_O_NOFOLLOW 0x0100
87#define MTSP_O_SYNC 0x0080 88#define MTSP_O_SYNC 0x0080
diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
index 7c92f79b6480..e94ef158f980 100644
--- a/arch/mips/loongson/common/mem.c
+++ b/arch/mips/loongson/common/mem.c
@@ -26,7 +26,7 @@ void __init prom_init_memory(void)
26/* override of arch/mips/mm/cache.c: __uncached_access */ 26/* override of arch/mips/mm/cache.c: __uncached_access */
27int __uncached_access(struct file *file, unsigned long addr) 27int __uncached_access(struct file *file, unsigned long addr)
28{ 28{
29 if (file->f_flags & O_SYNC) 29 if (file->f_flags & O_DSYNC)
30 return 1; 30 return 1;
31 31
32 return addr >= __pa(high_memory) || 32 return addr >= __pa(high_memory) ||
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 694d51f523d1..102b2dfa542a 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -194,7 +194,7 @@ void __devinit cpu_cache_init(void)
194 194
195int __weak __uncached_access(struct file *file, unsigned long addr) 195int __weak __uncached_access(struct file *file, unsigned long addr)
196{ 196{
197 if (file->f_flags & O_SYNC) 197 if (file->f_flags & O_DSYNC)
198 return 1; 198 return 1;
199 199
200 return addr >= __pa(high_memory); 200 return addr >= __pa(high_memory);
diff --git a/arch/parisc/include/asm/fcntl.h b/arch/parisc/include/asm/fcntl.h
index 1e1c824764ee..f357fc693c89 100644
--- a/arch/parisc/include/asm/fcntl.h
+++ b/arch/parisc/include/asm/fcntl.h
@@ -1,14 +1,13 @@
1#ifndef _PARISC_FCNTL_H 1#ifndef _PARISC_FCNTL_H
2#define _PARISC_FCNTL_H 2#define _PARISC_FCNTL_H
3 3
4/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
5 located on an ext2 file system */
6#define O_APPEND 000000010 4#define O_APPEND 000000010
7#define O_BLKSEEK 000000100 /* HPUX only */ 5#define O_BLKSEEK 000000100 /* HPUX only */
8#define O_CREAT 000000400 /* not fcntl */ 6#define O_CREAT 000000400 /* not fcntl */
9#define O_EXCL 000002000 /* not fcntl */ 7#define O_EXCL 000002000 /* not fcntl */
10#define O_LARGEFILE 000004000 8#define O_LARGEFILE 000004000
11#define O_SYNC 000100000 9#define __O_SYNC 000100000
10#define O_SYNC (__O_SYNC|O_DSYNC)
12#define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */ 11#define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */
13#define O_NOCTTY 000400000 /* not fcntl */ 12#define O_NOCTTY 000400000 /* not fcntl */
14#define O_DSYNC 001000000 /* HPUX only */ 13#define O_DSYNC 001000000 /* HPUX only */
diff --git a/arch/sparc/include/asm/fcntl.h b/arch/sparc/include/asm/fcntl.h
index d4d9c9d852c3..3b9cfb39175e 100644
--- a/arch/sparc/include/asm/fcntl.h
+++ b/arch/sparc/include/asm/fcntl.h
@@ -1,14 +1,12 @@
1#ifndef _SPARC_FCNTL_H 1#ifndef _SPARC_FCNTL_H
2#define _SPARC_FCNTL_H 2#define _SPARC_FCNTL_H
3 3
4/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
5 located on an ext2 file system */
6#define O_APPEND 0x0008 4#define O_APPEND 0x0008
7#define FASYNC 0x0040 /* fcntl, for BSD compatibility */ 5#define FASYNC 0x0040 /* fcntl, for BSD compatibility */
8#define O_CREAT 0x0200 /* not fcntl */ 6#define O_CREAT 0x0200 /* not fcntl */
9#define O_TRUNC 0x0400 /* not fcntl */ 7#define O_TRUNC 0x0400 /* not fcntl */
10#define O_EXCL 0x0800 /* not fcntl */ 8#define O_EXCL 0x0800 /* not fcntl */
11#define O_SYNC 0x2000 9#define O_DSYNC 0x2000 /* used to be O_SYNC, see below */
12#define O_NONBLOCK 0x4000 10#define O_NONBLOCK 0x4000
13#if defined(__sparc__) && defined(__arch64__) 11#if defined(__sparc__) && defined(__arch64__)
14#define O_NDELAY 0x0004 12#define O_NDELAY 0x0004
@@ -20,6 +18,21 @@
20#define O_DIRECT 0x100000 /* direct disk access hint */ 18#define O_DIRECT 0x100000 /* direct disk access hint */
21#define O_NOATIME 0x200000 19#define O_NOATIME 0x200000
22#define O_CLOEXEC 0x400000 20#define O_CLOEXEC 0x400000
21/*
22 * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
23 * the O_SYNC flag. We continue to use the existing numerical value
24 * for O_DSYNC semantics now, but using the correct symbolic name for it.
25 * This new value is used to request true Posix O_SYNC semantics. It is
26 * defined in this strange way to make sure applications compiled against
27 * new headers get at least O_DSYNC semantics on older kernels.
28 *
29 * This has the nice side-effect that we can simply test for O_DSYNC
30 * wherever we do not care if O_DSYNC or O_SYNC is used.
31 *
32 * Note: __O_SYNC must never be used directly.
33 */
34#define __O_SYNC 0x800000
35#define O_SYNC (__O_SYNC|O_DSYNC)
23 36
24#define F_GETOWN 5 /* for sockets. */ 37#define F_GETOWN 5 /* for sockets. */
25#define F_SETOWN 6 /* for sockets. */ 38#define F_SETOWN 6 /* for sockets. */
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 66b55d6e69ed..ae9648eb1c7f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -704,9 +704,8 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
704 if (!range_is_allowed(pfn, size)) 704 if (!range_is_allowed(pfn, size))
705 return 0; 705 return 0;
706 706
707 if (file->f_flags & O_SYNC) { 707 if (file->f_flags & O_DSYNC)
708 flags = _PAGE_CACHE_UC_MINUS; 708 flags = _PAGE_CACHE_UC_MINUS;
709 }
710 709
711#ifdef CONFIG_X86_32 710#ifdef CONFIG_X86_32
712 /* 711 /*
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 30eff80fed6f..fba76fb55abf 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -43,7 +43,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
43{ 43{
44#if defined(CONFIG_IA64) 44#if defined(CONFIG_IA64)
45 /* 45 /*
46 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. 46 * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases.
47 */ 47 */
48 return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); 48 return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
49#elif defined(CONFIG_MIPS) 49#elif defined(CONFIG_MIPS)
@@ -56,9 +56,9 @@ static inline int uncached_access(struct file *file, unsigned long addr)
56#else 56#else
57 /* 57 /*
58 * Accessing memory above the top the kernel knows about or through a file pointer 58 * Accessing memory above the top the kernel knows about or through a file pointer
59 * that was marked O_SYNC will be done non-cached. 59 * that was marked O_DSYNC will be done non-cached.
60 */ 60 */
61 if (file->f_flags & O_SYNC) 61 if (file->f_flags & O_DSYNC)
62 return 1; 62 return 1;
63 return addr >= __pa(high_memory); 63 return addr >= __pa(high_memory);
64#endif 64#endif
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 1e6aa504d58a..5e14dbaf65bc 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1713,7 +1713,7 @@ static int do_write(struct fsg_dev *fsg)
1713 } 1713 }
1714 if (fsg->cmnd[1] & 0x08) { // FUA 1714 if (fsg->cmnd[1] & 0x08) { // FUA
1715 spin_lock(&curlun->filp->f_lock); 1715 spin_lock(&curlun->filp->f_lock);
1716 curlun->filp->f_flags |= O_SYNC; 1716 curlun->filp->f_flags |= O_DSYNC;
1717 spin_unlock(&curlun->filp->f_lock); 1717 spin_unlock(&curlun->filp->f_lock);
1718 } 1718 }
1719 } 1719 }
diff --git a/fs/afs/write.c b/fs/afs/write.c
index c63a3c8beb73..6be1bc31616a 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -692,8 +692,9 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
692 } 692 }
693 693
694 /* return error values for O_SYNC and IS_SYNC() */ 694 /* return error values for O_SYNC and IS_SYNC() */
695 if (IS_SYNC(&vnode->vfs_inode) || iocb->ki_filp->f_flags & O_SYNC) { 695 if (IS_SYNC(&vnode->vfs_inode) || iocb->ki_filp->f_flags & O_DSYNC) {
696 ret = afs_fsync(iocb->ki_filp, dentry, 1); 696 ret = afs_fsync(iocb->ki_filp, dentry,
697 (iocb->ki_filp->f_flags & __O_SYNC) ? 0 : 1);
697 if (ret < 0) 698 if (ret < 0)
698 result = ret; 699 result = ret;
699 } 700 }
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 06550affbd27..77f759302e12 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -909,7 +909,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
909 unsigned long last_index; 909 unsigned long last_index;
910 int will_write; 910 int will_write;
911 911
912 will_write = ((file->f_flags & O_SYNC) || IS_SYNC(inode) || 912 will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
913 (file->f_flags & O_DIRECT)); 913 (file->f_flags & O_DIRECT));
914 914
915 nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, 915 nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE,
@@ -1076,7 +1076,7 @@ out_nolock:
1076 if (err) 1076 if (err)
1077 num_written = err; 1077 num_written = err;
1078 1078
1079 if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { 1079 if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
1080 trans = btrfs_start_transaction(root, 1); 1080 trans = btrfs_start_transaction(root, 1);
1081 ret = btrfs_log_dentry_safe(trans, root, 1081 ret = btrfs_log_dentry_safe(trans, root,
1082 file->f_dentry); 1082 file->f_dentry);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1f42f772865a..6ccf7262d1b7 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -214,7 +214,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
214 posix_flags |= SMB_O_EXCL; 214 posix_flags |= SMB_O_EXCL;
215 if (oflags & O_TRUNC) 215 if (oflags & O_TRUNC)
216 posix_flags |= SMB_O_TRUNC; 216 posix_flags |= SMB_O_TRUNC;
217 if (oflags & O_SYNC) 217 /* be safe and imply O_SYNC for O_DSYNC */
218 if (oflags & O_DSYNC)
218 posix_flags |= SMB_O_SYNC; 219 posix_flags |= SMB_O_SYNC;
219 if (oflags & O_DIRECTORY) 220 if (oflags & O_DIRECTORY)
220 posix_flags |= SMB_O_DIRECTORY; 221 posix_flags |= SMB_O_DIRECTORY;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 429337eb7afe..057e1dae12ab 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -76,8 +76,10 @@ static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
76 reopening a file. They had their effect on the original open */ 76 reopening a file. They had their effect on the original open */
77 if (flags & O_APPEND) 77 if (flags & O_APPEND)
78 posix_flags |= (fmode_t)O_APPEND; 78 posix_flags |= (fmode_t)O_APPEND;
79 if (flags & O_SYNC) 79 if (flags & O_DSYNC)
80 posix_flags |= (fmode_t)O_SYNC; 80 posix_flags |= (fmode_t)O_DSYNC;
81 if (flags & __O_SYNC)
82 posix_flags |= (fmode_t)__O_SYNC;
81 if (flags & O_DIRECTORY) 83 if (flags & O_DIRECTORY)
82 posix_flags |= (fmode_t)O_DIRECTORY; 84 posix_flags |= (fmode_t)O_DIRECTORY;
83 if (flags & O_NOFOLLOW) 85 if (flags & O_NOFOLLOW)
diff --git a/fs/namei.c b/fs/namei.c
index d11f404667e9..b83d38f614ff 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1678,6 +1678,15 @@ struct file *do_filp_open(int dfd, const char *pathname,
1678 int will_write; 1678 int will_write;
1679 int flag = open_to_namei_flags(open_flag); 1679 int flag = open_to_namei_flags(open_flag);
1680 1680
1681 /*
1682 * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
1683 * check for O_DSYNC if the need any syncing at all we enforce it's
1684 * always set instead of having to deal with possibly weird behaviour
1685 * for malicious applications setting only __O_SYNC.
1686 */
1687 if (open_flag & __O_SYNC)
1688 open_flag |= O_DSYNC;
1689
1681 if (!acc_mode) 1690 if (!acc_mode)
1682 acc_mode = MAY_OPEN | ACC_MODE(flag); 1691 acc_mode = MAY_OPEN | ACC_MODE(flag);
1683 1692
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f5fdd39e037a..6b891328f332 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -581,7 +581,7 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
581{ 581{
582 struct nfs_open_context *ctx; 582 struct nfs_open_context *ctx;
583 583
584 if (IS_SYNC(inode) || (filp->f_flags & O_SYNC)) 584 if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC))
585 return 1; 585 return 1;
586 ctx = nfs_file_open_context(filp); 586 ctx = nfs_file_open_context(filp);
587 if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) 587 if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags))
@@ -622,7 +622,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
622 622
623 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); 623 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
624 result = generic_file_aio_write(iocb, iov, nr_segs, pos); 624 result = generic_file_aio_write(iocb, iov, nr_segs, pos);
625 /* Return error values for O_SYNC and IS_SYNC() */ 625 /* Return error values for O_DSYNC and IS_SYNC() */
626 if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { 626 if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
627 int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); 627 int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode);
628 if (err < 0) 628 if (err < 0)
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c84b5cc1a943..b1ce2ea9b93b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -774,7 +774,7 @@ int nfs_updatepage(struct file *file, struct page *page,
774 */ 774 */
775 if (nfs_write_pageuptodate(page, inode) && 775 if (nfs_write_pageuptodate(page, inode) &&
776 inode->i_flock == NULL && 776 inode->i_flock == NULL &&
777 !(file->f_flags & O_SYNC)) { 777 !(file->f_flags & O_DSYNC)) {
778 count = max(count + offset, nfs_page_length(page)); 778 count = max(count + offset, nfs_page_length(page));
779 offset = 0; 779 offset = 0;
780 } 780 }
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index de059f490586..3d30a1c974a8 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2006,7 +2006,7 @@ out_dio:
2006 /* buffered aio wouldn't have proper lock coverage today */ 2006 /* buffered aio wouldn't have proper lock coverage today */
2007 BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); 2007 BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
2008 2008
2009 if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) { 2009 if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode)) {
2010 ret = filemap_fdatawrite_range(file->f_mapping, pos, 2010 ret = filemap_fdatawrite_range(file->f_mapping, pos,
2011 pos + count - 1); 2011 pos + count - 1);
2012 if (ret < 0) 2012 if (ret < 0)
diff --git a/fs/sync.c b/fs/sync.c
index d104591b066b..b75ca68dc081 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -295,10 +295,11 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
295 */ 295 */
296int generic_write_sync(struct file *file, loff_t pos, loff_t count) 296int generic_write_sync(struct file *file, loff_t pos, loff_t count)
297{ 297{
298 if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host)) 298 if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
299 return 0; 299 return 0;
300 return vfs_fsync_range(file, file->f_path.dentry, pos, 300 return vfs_fsync_range(file, file->f_path.dentry, pos,
301 pos + count - 1, 1); 301 pos + count - 1,
302 (file->f_flags & __O_SYNC) ? 0 : 1);
302} 303}
303EXPORT_SYMBOL(generic_write_sync); 304EXPORT_SYMBOL(generic_write_sync);
304 305
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 1009adc8d602..eaa3d480bc20 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1401,7 +1401,7 @@ static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov,
1401 if (ret < 0) 1401 if (ret < 0)
1402 return ret; 1402 return ret;
1403 1403
1404 if (ret > 0 && (IS_SYNC(inode) || iocb->ki_filp->f_flags & O_SYNC)) { 1404 if (ret > 0 && (IS_SYNC(inode) || iocb->ki_filp->f_flags & O_DSYNC)) {
1405 err = ubifs_sync_wbufs_by_inode(c, inode); 1405 err = ubifs_sync_wbufs_by_inode(c, inode);
1406 if (err) 1406 if (err)
1407 return err; 1407 return err;
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 072050f8d346..339c52b1a434 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -811,7 +811,7 @@ write_retry:
811 XFS_STATS_ADD(xs_write_bytes, ret); 811 XFS_STATS_ADD(xs_write_bytes, ret);
812 812
813 /* Handle various SYNC-type writes */ 813 /* Handle various SYNC-type writes */
814 if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { 814 if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
815 loff_t end = pos + ret - 1; 815 loff_t end = pos + ret - 1;
816 int error2; 816 int error2;
817 817
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index 495dc8af4044..681ddf3e844c 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -3,8 +3,6 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
7 located on an ext2 file system */
8#define O_ACCMODE 00000003 6#define O_ACCMODE 00000003
9#define O_RDONLY 00000000 7#define O_RDONLY 00000000
10#define O_WRONLY 00000001 8#define O_WRONLY 00000001
@@ -27,8 +25,8 @@
27#ifndef O_NONBLOCK 25#ifndef O_NONBLOCK
28#define O_NONBLOCK 00004000 26#define O_NONBLOCK 00004000
29#endif 27#endif
30#ifndef O_SYNC 28#ifndef O_DSYNC
31#define O_SYNC 00010000 29#define O_DSYNC 00010000 /* used to be O_SYNC, see below */
32#endif 30#endif
33#ifndef FASYNC 31#ifndef FASYNC
34#define FASYNC 00020000 /* fcntl, for BSD compatibility */ 32#define FASYNC 00020000 /* fcntl, for BSD compatibility */
@@ -51,6 +49,25 @@
51#ifndef O_CLOEXEC 49#ifndef O_CLOEXEC
52#define O_CLOEXEC 02000000 /* set close_on_exec */ 50#define O_CLOEXEC 02000000 /* set close_on_exec */
53#endif 51#endif
52
53/*
54 * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
55 * the O_SYNC flag. We continue to use the existing numerical value
56 * for O_DSYNC semantics now, but using the correct symbolic name for it.
57 * This new value is used to request true Posix O_SYNC semantics. It is
58 * defined in this strange way to make sure applications compiled against
59 * new headers get at least O_DSYNC semantics on older kernels.
60 *
61 * This has the nice side-effect that we can simply test for O_DSYNC
62 * wherever we do not care if O_DSYNC or O_SYNC is used.
63 *
64 * Note: __O_SYNC must never be used directly.
65 */
66#ifndef O_SYNC
67#define __O_SYNC 04000000
68#define O_SYNC (__O_SYNC|O_DSYNC)
69#endif
70
54#ifndef O_NDELAY 71#ifndef O_NDELAY
55#define O_NDELAY O_NONBLOCK 72#define O_NDELAY O_NONBLOCK
56#endif 73#endif
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 2f766123b158..0f5a194695d9 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1257,7 +1257,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
1257 break; 1257 break;
1258 count -= count1; 1258 count -= count1;
1259 } 1259 }
1260 if (file->f_flags & O_SYNC) { 1260 if (file->f_flags & O_DSYNC) {
1261 spin_lock_irq(&runtime->lock); 1261 spin_lock_irq(&runtime->lock);
1262 while (runtime->avail != runtime->buffer_size) { 1262 while (runtime->avail != runtime->buffer_size) {
1263 wait_queue_t wait; 1263 wait_queue_t wait;