aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c35
1 files changed, 18 insertions, 17 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 4bf7d1ab6c2a..f74d05201862 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1838,16 +1838,15 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
1838 size_t count, ssize_t written) 1838 size_t count, ssize_t written)
1839{ 1839{
1840 struct file *file = iocb->ki_filp; 1840 struct file *file = iocb->ki_filp;
1841 struct address_space * mapping = file->f_mapping; 1841 struct address_space *mapping = file->f_mapping;
1842 const struct address_space_operations *a_ops = mapping->a_ops; 1842 const struct address_space_operations *a_ops = mapping->a_ops;
1843 struct inode *inode = mapping->host; 1843 struct inode *inode = mapping->host;
1844 long status = 0; 1844 long status = 0;
1845 struct page *page; 1845 struct page *page;
1846 struct page *cached_page = NULL; 1846 struct page *cached_page = NULL;
1847 size_t bytes;
1848 struct pagevec lru_pvec; 1847 struct pagevec lru_pvec;
1849 const struct iovec *cur_iov = iov; /* current iovec */ 1848 const struct iovec *cur_iov = iov; /* current iovec */
1850 size_t iov_base = 0; /* offset in the current iovec */ 1849 size_t iov_offset = 0; /* offset in the current iovec */
1851 char __user *buf; 1850 char __user *buf;
1852 1851
1853 pagevec_init(&lru_pvec, 0); 1852 pagevec_init(&lru_pvec, 0);
@@ -1858,31 +1857,33 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
1858 if (likely(nr_segs == 1)) 1857 if (likely(nr_segs == 1))
1859 buf = iov->iov_base + written; 1858 buf = iov->iov_base + written;
1860 else { 1859 else {
1861 filemap_set_next_iovec(&cur_iov, &iov_base, written); 1860 filemap_set_next_iovec(&cur_iov, &iov_offset, written);
1862 buf = cur_iov->iov_base + iov_base; 1861 buf = cur_iov->iov_base + iov_offset;
1863 } 1862 }
1864 1863
1865 do { 1864 do {
1866 unsigned long index; 1865 pgoff_t index; /* Pagecache index for current page */
1867 unsigned long offset; 1866 unsigned long offset; /* Offset into pagecache page */
1868 unsigned long maxlen; 1867 unsigned long maxlen; /* Bytes remaining in current iovec */
1869 size_t copied; 1868 size_t bytes; /* Bytes to write to page */
1869 size_t copied; /* Bytes copied from user */
1870 1870
1871 offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */ 1871 offset = (pos & (PAGE_CACHE_SIZE - 1));
1872 index = pos >> PAGE_CACHE_SHIFT; 1872 index = pos >> PAGE_CACHE_SHIFT;
1873 bytes = PAGE_CACHE_SIZE - offset; 1873 bytes = PAGE_CACHE_SIZE - offset;
1874 if (bytes > count) 1874 if (bytes > count)
1875 bytes = count; 1875 bytes = count;
1876 1876
1877 maxlen = cur_iov->iov_len - iov_offset;
1878 if (maxlen > bytes)
1879 maxlen = bytes;
1880
1877 /* 1881 /*
1878 * Bring in the user page that we will copy from _first_. 1882 * Bring in the user page that we will copy from _first_.
1879 * Otherwise there's a nasty deadlock on copying from the 1883 * Otherwise there's a nasty deadlock on copying from the
1880 * same page as we're writing to, without it being marked 1884 * same page as we're writing to, without it being marked
1881 * up-to-date. 1885 * up-to-date.
1882 */ 1886 */
1883 maxlen = cur_iov->iov_len - iov_base;
1884 if (maxlen > bytes)
1885 maxlen = bytes;
1886 fault_in_pages_readable(buf, maxlen); 1887 fault_in_pages_readable(buf, maxlen);
1887 1888
1888 page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec); 1889 page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
@@ -1913,7 +1914,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
1913 buf, bytes); 1914 buf, bytes);
1914 else 1915 else
1915 copied = filemap_copy_from_user_iovec(page, offset, 1916 copied = filemap_copy_from_user_iovec(page, offset,
1916 cur_iov, iov_base, bytes); 1917 cur_iov, iov_offset, bytes);
1917 flush_dcache_page(page); 1918 flush_dcache_page(page);
1918 status = a_ops->commit_write(file, page, offset, offset+bytes); 1919 status = a_ops->commit_write(file, page, offset, offset+bytes);
1919 if (status == AOP_TRUNCATED_PAGE) { 1920 if (status == AOP_TRUNCATED_PAGE) {
@@ -1931,12 +1932,12 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
1931 buf += status; 1932 buf += status;
1932 if (unlikely(nr_segs > 1)) { 1933 if (unlikely(nr_segs > 1)) {
1933 filemap_set_next_iovec(&cur_iov, 1934 filemap_set_next_iovec(&cur_iov,
1934 &iov_base, status); 1935 &iov_offset, status);
1935 if (count) 1936 if (count)
1936 buf = cur_iov->iov_base + 1937 buf = cur_iov->iov_base +
1937 iov_base; 1938 iov_offset;
1938 } else { 1939 } else {
1939 iov_base += status; 1940 iov_offset += status;
1940 } 1941 }
1941 } 1942 }
1942 } 1943 }