diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 20:15:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 20:15:20 -0400 |
| commit | 31453a9764f7e2a72a6e2c502ace586e2663a68c (patch) | |
| tree | 5d4db63de5b4b85d1ffdab4e95a75175a784a10a /mm/filemap.c | |
| parent | f9ba5375a8aae4aeea6be15df77e24707a429812 (diff) | |
| parent | 93ed0e2d07b25aff4db1d61bfbcd1e82074c0ad5 (diff) | |
Merge branch 'akpm-incoming-1'
* akpm-incoming-1: (176 commits)
scripts/checkpatch.pl: add check for declaration of pci_device_id
scripts/checkpatch.pl: add warnings for static char that could be static const char
checkpatch: version 0.31
checkpatch: statement/block context analyser should look at sanitised lines
checkpatch: handle EXPORT_SYMBOL for DEVICE_ATTR and similar
checkpatch: clean up structure definition macro handline
checkpatch: update copyright dates
checkpatch: Add additional attribute #defines
checkpatch: check for incorrect permissions
checkpatch: ensure kconfig help checks only apply when we are adding help
checkpatch: simplify and consolidate "missing space after" checks
checkpatch: add check for space after struct, union, and enum
checkpatch: returning errno typically should be negative
checkpatch: handle casts better fixing false categorisation of : as binary
checkpatch: ensure we do not collapse bracketed sections into constants
checkpatch: suggest cleanpatch and cleanfile when appropriate
checkpatch: types may sit on a line on their own
checkpatch: fix regressions in "fix handling of leading spaces"
div64_u64(): improve precision on 32bit platforms
lib/parser: cleanup match_number()
...
Diffstat (limited to 'mm/filemap.c')
| -rw-r--r-- | mm/filemap.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 3d4df44e4221..75572b5f2374 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -612,6 +612,19 @@ void __lock_page_nosync(struct page *page) | |||
| 612 | TASK_UNINTERRUPTIBLE); | 612 | TASK_UNINTERRUPTIBLE); |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | int __lock_page_or_retry(struct page *page, struct mm_struct *mm, | ||
| 616 | unsigned int flags) | ||
| 617 | { | ||
| 618 | if (!(flags & FAULT_FLAG_ALLOW_RETRY)) { | ||
| 619 | __lock_page(page); | ||
| 620 | return 1; | ||
| 621 | } else { | ||
| 622 | up_read(&mm->mmap_sem); | ||
| 623 | wait_on_page_locked(page); | ||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 615 | /** | 628 | /** |
| 616 | * find_get_page - find and get a page reference | 629 | * find_get_page - find and get a page reference |
| 617 | * @mapping: the address_space to search | 630 | * @mapping: the address_space to search |
| @@ -1539,25 +1552,28 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 1539 | * waiting for the lock. | 1552 | * waiting for the lock. |
| 1540 | */ | 1553 | */ |
| 1541 | do_async_mmap_readahead(vma, ra, file, page, offset); | 1554 | do_async_mmap_readahead(vma, ra, file, page, offset); |
| 1542 | lock_page(page); | ||
| 1543 | |||
| 1544 | /* Did it get truncated? */ | ||
| 1545 | if (unlikely(page->mapping != mapping)) { | ||
| 1546 | unlock_page(page); | ||
| 1547 | put_page(page); | ||
| 1548 | goto no_cached_page; | ||
| 1549 | } | ||
| 1550 | } else { | 1555 | } else { |
| 1551 | /* No page in the page cache at all */ | 1556 | /* No page in the page cache at all */ |
| 1552 | do_sync_mmap_readahead(vma, ra, file, offset); | 1557 | do_sync_mmap_readahead(vma, ra, file, offset); |
| 1553 | count_vm_event(PGMAJFAULT); | 1558 | count_vm_event(PGMAJFAULT); |
| 1554 | ret = VM_FAULT_MAJOR; | 1559 | ret = VM_FAULT_MAJOR; |
| 1555 | retry_find: | 1560 | retry_find: |
| 1556 | page = find_lock_page(mapping, offset); | 1561 | page = find_get_page(mapping, offset); |
| 1557 | if (!page) | 1562 | if (!page) |
| 1558 | goto no_cached_page; | 1563 | goto no_cached_page; |
| 1559 | } | 1564 | } |
| 1560 | 1565 | ||
| 1566 | if (!lock_page_or_retry(page, vma->vm_mm, vmf->flags)) | ||
| 1567 | return ret | VM_FAULT_RETRY; | ||
| 1568 | |||
| 1569 | /* Did it get truncated? */ | ||
| 1570 | if (unlikely(page->mapping != mapping)) { | ||
| 1571 | unlock_page(page); | ||
| 1572 | put_page(page); | ||
| 1573 | goto retry_find; | ||
| 1574 | } | ||
| 1575 | VM_BUG_ON(page->index != offset); | ||
| 1576 | |||
| 1561 | /* | 1577 | /* |
| 1562 | * We have a locked page in the page cache, now we need to check | 1578 | * We have a locked page in the page cache, now we need to check |
| 1563 | * that it's up-to-date. If not, it is going to be due to an error. | 1579 | * that it's up-to-date. If not, it is going to be due to an error. |
| @@ -2177,12 +2193,12 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2177 | } | 2193 | } |
| 2178 | 2194 | ||
| 2179 | if (written > 0) { | 2195 | if (written > 0) { |
| 2180 | loff_t end = pos + written; | 2196 | pos += written; |
| 2181 | if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) { | 2197 | if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) { |
| 2182 | i_size_write(inode, end); | 2198 | i_size_write(inode, pos); |
| 2183 | mark_inode_dirty(inode); | 2199 | mark_inode_dirty(inode); |
| 2184 | } | 2200 | } |
| 2185 | *ppos = end; | 2201 | *ppos = pos; |
| 2186 | } | 2202 | } |
| 2187 | out: | 2203 | out: |
| 2188 | return written; | 2204 | return written; |
