diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-20 12:50:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-20 12:50:11 -0400 |
commit | c2661b806092d8ea2dccb7b02b65776555e0ee47 (patch) | |
tree | ebc73fa58706e5a0a79235953c532ac6c6e2b539 /mm | |
parent | f114040e3ea6e07372334ade75d1ee0775c355e1 (diff) | |
parent | 813d32f91333e4c33d5a19b67167c4bae42dae75 (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o:
"A large number of cleanups and bug fixes, with some (minor) journal
optimizations"
[ This got sent to me before -rc1, but was stuck in my spam folder. - Linus ]
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (67 commits)
ext4: check s_chksum_driver when looking for bg csum presence
ext4: move error report out of atomic context in ext4_init_block_bitmap()
ext4: Replace open coded mdata csum feature to helper function
ext4: delete useless comments about ext4_move_extents
ext4: fix reservation overflow in ext4_da_write_begin
ext4: add ext4_iget_normal() which is to be used for dir tree lookups
ext4: don't orphan or truncate the boot loader inode
ext4: grab missed write_count for EXT4_IOC_SWAP_BOOT
ext4: optimize block allocation on grow indepth
ext4: get rid of code duplication
ext4: fix over-defensive complaint after journal abort
ext4: fix return value of ext4_do_update_inode
ext4: fix mmap data corruption when blocksize < pagesize
vfs: fix data corruption when blocksize < pagesize for mmaped data
ext4: fold ext4_nojournal_sops into ext4_sops
ext4: support freezing ext2 (nojournal) file systems
ext4: fold ext4_sync_fs_nojournal() into ext4_sync_fs()
ext4: don't check quota format when there are no quota files
jbd2: simplify calling convention around __jbd2_journal_clean_checkpoint_list
jbd2: avoid pointless scanning of checkpoint lists
...
Diffstat (limited to 'mm')
-rw-r--r-- | mm/truncate.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index 96d167372d89..261eaf6e5a19 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/buffer_head.h> /* grr. try_to_release_page, | 20 | #include <linux/buffer_head.h> /* grr. try_to_release_page, |
21 | do_invalidatepage */ | 21 | do_invalidatepage */ |
22 | #include <linux/cleancache.h> | 22 | #include <linux/cleancache.h> |
23 | #include <linux/rmap.h> | ||
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
25 | static void clear_exceptional_entry(struct address_space *mapping, | 26 | static void clear_exceptional_entry(struct address_space *mapping, |
@@ -719,12 +720,68 @@ EXPORT_SYMBOL(truncate_pagecache); | |||
719 | */ | 720 | */ |
720 | void truncate_setsize(struct inode *inode, loff_t newsize) | 721 | void truncate_setsize(struct inode *inode, loff_t newsize) |
721 | { | 722 | { |
723 | loff_t oldsize = inode->i_size; | ||
724 | |||
722 | i_size_write(inode, newsize); | 725 | i_size_write(inode, newsize); |
726 | if (newsize > oldsize) | ||
727 | pagecache_isize_extended(inode, oldsize, newsize); | ||
723 | truncate_pagecache(inode, newsize); | 728 | truncate_pagecache(inode, newsize); |
724 | } | 729 | } |
725 | EXPORT_SYMBOL(truncate_setsize); | 730 | EXPORT_SYMBOL(truncate_setsize); |
726 | 731 | ||
727 | /** | 732 | /** |
733 | * pagecache_isize_extended - update pagecache after extension of i_size | ||
734 | * @inode: inode for which i_size was extended | ||
735 | * @from: original inode size | ||
736 | * @to: new inode size | ||
737 | * | ||
738 | * Handle extension of inode size either caused by extending truncate or by | ||
739 | * write starting after current i_size. We mark the page straddling current | ||
740 | * i_size RO so that page_mkwrite() is called on the nearest write access to | ||
741 | * the page. This way filesystem can be sure that page_mkwrite() is called on | ||
742 | * the page before user writes to the page via mmap after the i_size has been | ||
743 | * changed. | ||
744 | * | ||
745 | * The function must be called after i_size is updated so that page fault | ||
746 | * coming after we unlock the page will already see the new i_size. | ||
747 | * The function must be called while we still hold i_mutex - this not only | ||
748 | * makes sure i_size is stable but also that userspace cannot observe new | ||
749 | * i_size value before we are prepared to store mmap writes at new inode size. | ||
750 | */ | ||
751 | void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to) | ||
752 | { | ||
753 | int bsize = 1 << inode->i_blkbits; | ||
754 | loff_t rounded_from; | ||
755 | struct page *page; | ||
756 | pgoff_t index; | ||
757 | |||
758 | WARN_ON(!mutex_is_locked(&inode->i_mutex)); | ||
759 | WARN_ON(to > inode->i_size); | ||
760 | |||
761 | if (from >= to || bsize == PAGE_CACHE_SIZE) | ||
762 | return; | ||
763 | /* Page straddling @from will not have any hole block created? */ | ||
764 | rounded_from = round_up(from, bsize); | ||
765 | if (to <= rounded_from || !(rounded_from & (PAGE_CACHE_SIZE - 1))) | ||
766 | return; | ||
767 | |||
768 | index = from >> PAGE_CACHE_SHIFT; | ||
769 | page = find_lock_page(inode->i_mapping, index); | ||
770 | /* Page not cached? Nothing to do */ | ||
771 | if (!page) | ||
772 | return; | ||
773 | /* | ||
774 | * See clear_page_dirty_for_io() for details why set_page_dirty() | ||
775 | * is needed. | ||
776 | */ | ||
777 | if (page_mkclean(page)) | ||
778 | set_page_dirty(page); | ||
779 | unlock_page(page); | ||
780 | page_cache_release(page); | ||
781 | } | ||
782 | EXPORT_SYMBOL(pagecache_isize_extended); | ||
783 | |||
784 | /** | ||
728 | * truncate_pagecache_range - unmap and remove pagecache that is hole-punched | 785 | * truncate_pagecache_range - unmap and remove pagecache that is hole-punched |
729 | * @inode: inode | 786 | * @inode: inode |
730 | * @lstart: offset of beginning of hole | 787 | * @lstart: offset of beginning of hole |