aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-06-12 10:20:37 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-31 01:45:47 -0400
commit14da9200140f8d722ad1767dfabadebd8b34f2ad (patch)
treeea5d88b091999f7a64af0b9d335d7cad4c79edfb /fs/splice.c
parent5d37e9e6dec65cd21be68ee92de99686213e916b (diff)
fs: Protect write paths by sb_start_write - sb_end_write
There are several entry points which dirty pages in a filesystem. mmap (handled by block_page_mkwrite()), buffered write (handled by __generic_file_aio_write()), splice write (generic_file_splice_write), truncate, and fallocate (these can dirty last partial page - handled inside each filesystem separately). Protect these places with sb_start_write() and sb_end_write(). ->page_mkwrite() calls are particularly complex since they are called with mmap_sem held and thus we cannot use standard sb_start_write() due to lock ordering constraints. We solve the problem by using a special freeze protection sb_start_pagefault() which ranks below mmap_sem. BugLink: https://bugs.launchpad.net/bugs/897421 Tested-by: Kamal Mostafa <kamal@canonical.com> Tested-by: Peter M. Petrakis <peter.petrakis@canonical.com> Tested-by: Dann Frazier <dann.frazier@canonical.com> Tested-by: Massimo Morana <massimo.morana@canonical.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 7bf08fa22ec9..41514dd89462 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -996,6 +996,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
996 }; 996 };
997 ssize_t ret; 997 ssize_t ret;
998 998
999 sb_start_write(inode->i_sb);
1000
999 pipe_lock(pipe); 1001 pipe_lock(pipe);
1000 1002
1001 splice_from_pipe_begin(&sd); 1003 splice_from_pipe_begin(&sd);
@@ -1034,6 +1036,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
1034 *ppos += ret; 1036 *ppos += ret;
1035 balance_dirty_pages_ratelimited_nr(mapping, nr_pages); 1037 balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
1036 } 1038 }
1039 sb_end_write(inode->i_sb);
1037 1040
1038 return ret; 1041 return ret;
1039} 1042}