aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-20 12:50:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-20 12:50:11 -0400
commitc2661b806092d8ea2dccb7b02b65776555e0ee47 (patch)
treeebc73fa58706e5a0a79235953c532ac6c6e2b539 /mm
parentf114040e3ea6e07372334ade75d1ee0775c355e1 (diff)
parent813d32f91333e4c33d5a19b67167c4bae42dae75 (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.c57
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
25static void clear_exceptional_entry(struct address_space *mapping, 26static void clear_exceptional_entry(struct address_space *mapping,
@@ -719,12 +720,68 @@ EXPORT_SYMBOL(truncate_pagecache);
719 */ 720 */
720void truncate_setsize(struct inode *inode, loff_t newsize) 721void 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}
725EXPORT_SYMBOL(truncate_setsize); 730EXPORT_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 */
751void 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}
782EXPORT_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