diff options
Diffstat (limited to 'mm/filemap.c')
| -rw-r--r-- | mm/filemap.c | 109 |
1 files changed, 75 insertions, 34 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 3464b681f844..7b84dc814347 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -75,8 +75,8 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
| 75 | * ->mmap_sem | 75 | * ->mmap_sem |
| 76 | * ->lock_page (access_process_vm) | 76 | * ->lock_page (access_process_vm) |
| 77 | * | 77 | * |
| 78 | * ->mmap_sem | 78 | * ->i_mutex (generic_file_buffered_write) |
| 79 | * ->i_mutex (msync) | 79 | * ->mmap_sem (fault_in_pages_readable->do_page_fault) |
| 80 | * | 80 | * |
| 81 | * ->i_mutex | 81 | * ->i_mutex |
| 82 | * ->i_alloc_sem (various) | 82 | * ->i_alloc_sem (various) |
| @@ -467,25 +467,15 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping, | |||
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | #ifdef CONFIG_NUMA | 469 | #ifdef CONFIG_NUMA |
| 470 | struct page *page_cache_alloc(struct address_space *x) | 470 | struct page *__page_cache_alloc(gfp_t gfp) |
| 471 | { | 471 | { |
| 472 | if (cpuset_do_page_mem_spread()) { | 472 | if (cpuset_do_page_mem_spread()) { |
| 473 | int n = cpuset_mem_spread_node(); | 473 | int n = cpuset_mem_spread_node(); |
| 474 | return alloc_pages_node(n, mapping_gfp_mask(x), 0); | 474 | return alloc_pages_node(n, gfp, 0); |
| 475 | } | 475 | } |
| 476 | return alloc_pages(mapping_gfp_mask(x), 0); | 476 | return alloc_pages(gfp, 0); |
| 477 | } | 477 | } |
| 478 | EXPORT_SYMBOL(page_cache_alloc); | 478 | EXPORT_SYMBOL(__page_cache_alloc); |
| 479 | |||
| 480 | struct page *page_cache_alloc_cold(struct address_space *x) | ||
| 481 | { | ||
| 482 | if (cpuset_do_page_mem_spread()) { | ||
| 483 | int n = cpuset_mem_spread_node(); | ||
| 484 | return alloc_pages_node(n, mapping_gfp_mask(x)|__GFP_COLD, 0); | ||
| 485 | } | ||
| 486 | return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0); | ||
| 487 | } | ||
| 488 | EXPORT_SYMBOL(page_cache_alloc_cold); | ||
| 489 | #endif | 479 | #endif |
| 490 | 480 | ||
| 491 | static int __sleep_on_page_lock(void *word) | 481 | static int __sleep_on_page_lock(void *word) |
| @@ -826,7 +816,6 @@ struct page * | |||
| 826 | grab_cache_page_nowait(struct address_space *mapping, unsigned long index) | 816 | grab_cache_page_nowait(struct address_space *mapping, unsigned long index) |
| 827 | { | 817 | { |
| 828 | struct page *page = find_get_page(mapping, index); | 818 | struct page *page = find_get_page(mapping, index); |
| 829 | gfp_t gfp_mask; | ||
| 830 | 819 | ||
| 831 | if (page) { | 820 | if (page) { |
| 832 | if (!TestSetPageLocked(page)) | 821 | if (!TestSetPageLocked(page)) |
| @@ -834,9 +823,8 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index) | |||
| 834 | page_cache_release(page); | 823 | page_cache_release(page); |
| 835 | return NULL; | 824 | return NULL; |
| 836 | } | 825 | } |
| 837 | gfp_mask = mapping_gfp_mask(mapping) & ~__GFP_FS; | 826 | page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~__GFP_FS); |
| 838 | page = alloc_pages(gfp_mask, 0); | 827 | if (page && add_to_page_cache_lru(page, mapping, index, GFP_KERNEL)) { |
| 839 | if (page && add_to_page_cache_lru(page, mapping, index, gfp_mask)) { | ||
| 840 | page_cache_release(page); | 828 | page_cache_release(page); |
| 841 | page = NULL; | 829 | page = NULL; |
| 842 | } | 830 | } |
| @@ -1884,11 +1872,10 @@ repeat: | |||
| 1884 | * if suid or (sgid and xgrp) | 1872 | * if suid or (sgid and xgrp) |
| 1885 | * remove privs | 1873 | * remove privs |
| 1886 | */ | 1874 | */ |
| 1887 | int remove_suid(struct dentry *dentry) | 1875 | int should_remove_suid(struct dentry *dentry) |
| 1888 | { | 1876 | { |
| 1889 | mode_t mode = dentry->d_inode->i_mode; | 1877 | mode_t mode = dentry->d_inode->i_mode; |
| 1890 | int kill = 0; | 1878 | int kill = 0; |
| 1891 | int result = 0; | ||
| 1892 | 1879 | ||
| 1893 | /* suid always must be killed */ | 1880 | /* suid always must be killed */ |
| 1894 | if (unlikely(mode & S_ISUID)) | 1881 | if (unlikely(mode & S_ISUID)) |
| @@ -1901,13 +1888,28 @@ int remove_suid(struct dentry *dentry) | |||
| 1901 | if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) | 1888 | if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) |
| 1902 | kill |= ATTR_KILL_SGID; | 1889 | kill |= ATTR_KILL_SGID; |
| 1903 | 1890 | ||
| 1904 | if (unlikely(kill && !capable(CAP_FSETID))) { | 1891 | if (unlikely(kill && !capable(CAP_FSETID))) |
| 1905 | struct iattr newattrs; | 1892 | return kill; |
| 1906 | 1893 | ||
| 1907 | newattrs.ia_valid = ATTR_FORCE | kill; | 1894 | return 0; |
| 1908 | result = notify_change(dentry, &newattrs); | 1895 | } |
| 1909 | } | 1896 | |
| 1910 | return result; | 1897 | int __remove_suid(struct dentry *dentry, int kill) |
| 1898 | { | ||
| 1899 | struct iattr newattrs; | ||
| 1900 | |||
| 1901 | newattrs.ia_valid = ATTR_FORCE | kill; | ||
| 1902 | return notify_change(dentry, &newattrs); | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | int remove_suid(struct dentry *dentry) | ||
| 1906 | { | ||
| 1907 | int kill = should_remove_suid(dentry); | ||
| 1908 | |||
| 1909 | if (unlikely(kill)) | ||
| 1910 | return __remove_suid(dentry, kill); | ||
| 1911 | |||
| 1912 | return 0; | ||
| 1911 | } | 1913 | } |
| 1912 | EXPORT_SYMBOL(remove_suid); | 1914 | EXPORT_SYMBOL(remove_suid); |
| 1913 | 1915 | ||
| @@ -2222,7 +2224,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, | |||
| 2222 | unsigned long nr_segs, loff_t *ppos) | 2224 | unsigned long nr_segs, loff_t *ppos) |
| 2223 | { | 2225 | { |
| 2224 | struct file *file = iocb->ki_filp; | 2226 | struct file *file = iocb->ki_filp; |
| 2225 | const struct address_space * mapping = file->f_mapping; | 2227 | struct address_space * mapping = file->f_mapping; |
| 2226 | size_t ocount; /* original count */ | 2228 | size_t ocount; /* original count */ |
| 2227 | size_t count; /* after file limit checks */ | 2229 | size_t count; /* after file limit checks */ |
| 2228 | struct inode *inode = mapping->host; | 2230 | struct inode *inode = mapping->host; |
| @@ -2275,8 +2277,11 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, | |||
| 2275 | 2277 | ||
| 2276 | /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ | 2278 | /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ |
| 2277 | if (unlikely(file->f_flags & O_DIRECT)) { | 2279 | if (unlikely(file->f_flags & O_DIRECT)) { |
| 2278 | written = generic_file_direct_write(iocb, iov, | 2280 | loff_t endbyte; |
| 2279 | &nr_segs, pos, ppos, count, ocount); | 2281 | ssize_t written_buffered; |
| 2282 | |||
| 2283 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, | ||
| 2284 | ppos, count, ocount); | ||
| 2280 | if (written < 0 || written == count) | 2285 | if (written < 0 || written == count) |
| 2281 | goto out; | 2286 | goto out; |
| 2282 | /* | 2287 | /* |
| @@ -2285,10 +2290,46 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, | |||
| 2285 | */ | 2290 | */ |
| 2286 | pos += written; | 2291 | pos += written; |
| 2287 | count -= written; | 2292 | count -= written; |
| 2288 | } | 2293 | written_buffered = generic_file_buffered_write(iocb, iov, |
| 2294 | nr_segs, pos, ppos, count, | ||
| 2295 | written); | ||
| 2296 | /* | ||
| 2297 | * If generic_file_buffered_write() retuned a synchronous error | ||
| 2298 | * then we want to return the number of bytes which were | ||
| 2299 | * direct-written, or the error code if that was zero. Note | ||
| 2300 | * that this differs from normal direct-io semantics, which | ||
| 2301 | * will return -EFOO even if some bytes were written. | ||
| 2302 | */ | ||
| 2303 | if (written_buffered < 0) { | ||
| 2304 | err = written_buffered; | ||
| 2305 | goto out; | ||
| 2306 | } | ||
| 2289 | 2307 | ||
| 2290 | written = generic_file_buffered_write(iocb, iov, nr_segs, | 2308 | /* |
| 2291 | pos, ppos, count, written); | 2309 | * We need to ensure that the page cache pages are written to |
| 2310 | * disk and invalidated to preserve the expected O_DIRECT | ||
| 2311 | * semantics. | ||
| 2312 | */ | ||
| 2313 | endbyte = pos + written_buffered - written - 1; | ||
| 2314 | err = do_sync_file_range(file, pos, endbyte, | ||
| 2315 | SYNC_FILE_RANGE_WAIT_BEFORE| | ||
| 2316 | SYNC_FILE_RANGE_WRITE| | ||
| 2317 | SYNC_FILE_RANGE_WAIT_AFTER); | ||
| 2318 | if (err == 0) { | ||
| 2319 | written = written_buffered; | ||
| 2320 | invalidate_mapping_pages(mapping, | ||
| 2321 | pos >> PAGE_CACHE_SHIFT, | ||
| 2322 | endbyte >> PAGE_CACHE_SHIFT); | ||
| 2323 | } else { | ||
| 2324 | /* | ||
| 2325 | * We don't know how much we wrote, so just return | ||
| 2326 | * the number of bytes which were direct-written | ||
| 2327 | */ | ||
| 2328 | } | ||
| 2329 | } else { | ||
| 2330 | written = generic_file_buffered_write(iocb, iov, nr_segs, | ||
| 2331 | pos, ppos, count, written); | ||
| 2332 | } | ||
| 2292 | out: | 2333 | out: |
| 2293 | current->backing_dev_info = NULL; | 2334 | current->backing_dev_info = NULL; |
| 2294 | return written ? written : err; | 2335 | return written ? written : err; |
