aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2011-03-10 14:31:30 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-21 00:40:29 -0400
commitb7ed78f56575074f29ec99d8984f347f6c99c914 (patch)
tree7bc901458a9f47b197052e98a25c4a4f10c52607
parent1bef82917c74249ff21982127e57defd6ca2bb1b (diff)
introduce sys_syncfs to sync a single file system
It is frequently useful to sync a single file system, instead of all mounted file systems via sync(2): - On machines with many mounts, it is not at all uncommon for some of them to hang (e.g. unresponsive NFS server). sync(2) will get stuck on those and may never get to the one you do care about (e.g., /). - Some applications write lots of data to the file system and then want to make sure it is flushed to disk. Calling fsync(2) on each file introduces unnecessary ordering constraints that result in a large amount of sub-optimal writeback/flush/commit behavior by the file system. There are currently two ways (that I know of) to sync a single super_block: - BLKFLSBUF ioctl on the block device: That also invalidates the bdev mapping, which isn't usually desirable, and doesn't work for non-block file systems. - 'mount -o remount,rw' will call sync_filesystem as an artifact of the current implemention. Relying on this little-known side effect for something like data safety sounds foolish. Both of these approaches require root privileges, which some applications do not have (nor should they need?) given that sync(2) is an unprivileged operation. This patch introduces a new system call syncfs(2) that takes an fd and syncs only the file system it references. Maybe someday we can $ sync /some/path and not get sync: ignoring all arguments The syscall is motivated by comments by Al and Christoph at the last LSF. syncfs(2) seems like an appropriate name given statfs(2). A similar ioctl was also proposed a while back, see http://marc.info/?l=linux-fsdevel&m=127970513829285&w=2 Signed-off-by: Sage Weil <sage@newdream.net> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/x86/ia32/ia32entry.S1
-rw-r--r--arch/x86/include/asm/unistd_32.h3
-rw-r--r--arch/x86/include/asm/unistd_64.h2
-rw-r--r--arch/x86/kernel/syscall_table_32.S1
-rw-r--r--fs/sync.c24
-rw-r--r--include/asm-generic/unistd.h4
-rw-r--r--include/linux/syscalls.h1
7 files changed, 34 insertions, 2 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 430312ba6e3f..849a9d23c71d 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -847,4 +847,5 @@ ia32_sys_call_table:
847 .quad sys_name_to_handle_at 847 .quad sys_name_to_handle_at
848 .quad compat_sys_open_by_handle_at 848 .quad compat_sys_open_by_handle_at
849 .quad compat_sys_clock_adjtime 849 .quad compat_sys_clock_adjtime
850 .quad sys_syncfs
850ia32_syscall_end: 851ia32_syscall_end:
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index ffaf183c619a..a755ef5e5977 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -349,10 +349,11 @@
349#define __NR_name_to_handle_at 341 349#define __NR_name_to_handle_at 341
350#define __NR_open_by_handle_at 342 350#define __NR_open_by_handle_at 342
351#define __NR_clock_adjtime 343 351#define __NR_clock_adjtime 343
352#define __NR_syncfs 344
352 353
353#ifdef __KERNEL__ 354#ifdef __KERNEL__
354 355
355#define NR_syscalls 344 356#define NR_syscalls 345
356 357
357#define __ARCH_WANT_IPC_PARSE_VERSION 358#define __ARCH_WANT_IPC_PARSE_VERSION
358#define __ARCH_WANT_OLD_READDIR 359#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index 5466bea670e7..160fa76bd578 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -675,6 +675,8 @@ __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
675__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) 675__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
676#define __NR_clock_adjtime 305 676#define __NR_clock_adjtime 305
677__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) 677__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
678#define __NR_syncfs 306
679__SYSCALL(__NR_syncfs, sys_syncfs)
678 680
679#ifndef __NO_STUBS 681#ifndef __NO_STUBS
680#define __ARCH_WANT_OLD_READDIR 682#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 5f181742e8f9..abce34d5c79d 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -343,3 +343,4 @@ ENTRY(sys_call_table)
343 .long sys_name_to_handle_at 343 .long sys_name_to_handle_at
344 .long sys_open_by_handle_at 344 .long sys_open_by_handle_at
345 .long sys_clock_adjtime 345 .long sys_clock_adjtime
346 .long sys_syncfs
diff --git a/fs/sync.c b/fs/sync.c
index ba76b9623e7e..92ca208777d5 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -7,6 +7,7 @@
7#include <linux/fs.h> 7#include <linux/fs.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/namei.h>
10#include <linux/sched.h> 11#include <linux/sched.h>
11#include <linux/writeback.h> 12#include <linux/writeback.h>
12#include <linux/syscalls.h> 13#include <linux/syscalls.h>
@@ -128,6 +129,29 @@ void emergency_sync(void)
128 } 129 }
129} 130}
130 131
132/*
133 * sync a single super
134 */
135SYSCALL_DEFINE1(syncfs, int, fd)
136{
137 struct file *file;
138 struct super_block *sb;
139 int ret;
140 int fput_needed;
141
142 file = fget_light(fd, &fput_needed);
143 if (!file)
144 return -EBADF;
145 sb = file->f_dentry->d_sb;
146
147 down_read(&sb->s_umount);
148 ret = sync_filesystem(sb);
149 up_read(&sb->s_umount);
150
151 fput_light(file, fput_needed);
152 return ret;
153}
154
131/** 155/**
132 * vfs_fsync_range - helper to sync a range of data & metadata to disk 156 * vfs_fsync_range - helper to sync a range of data & metadata to disk
133 * @file: file to sync 157 * @file: file to sync
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index d94f447c667a..176b825add52 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -652,9 +652,11 @@ __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
652__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) 652__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
653#define __NR_clock_adjtime 266 653#define __NR_clock_adjtime 266
654__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) 654__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
655#define __NR_syncfs 264
656__SYSCALL(__NR_syncfs, sys_syncfs)
655 657
656#undef __NR_syscalls 658#undef __NR_syscalls
657#define __NR_syscalls 267 659#define __NR_syscalls 268
658 660
659/* 661/*
660 * All syscalls below here should go away really, 662 * All syscalls below here should go away really,
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 1f5c18e6f4f1..83ecc1749ef6 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -825,6 +825,7 @@ asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags
825asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, 825asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
826 u64 mask, int fd, 826 u64 mask, int fd,
827 const char __user *pathname); 827 const char __user *pathname);
828asmlinkage long sys_syncfs(int fd);
828 829
829int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]); 830int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);
830 831