Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

f2fs: check truncation of mapping after lock_page

We call lock_page when we need to update a page after readpage.
Between grab and lock page, the page can be truncated by other thread.
So, we should check the page after lock_page whether it was truncated or not.

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>

+39 -7
+4
fs/f2fs/checkpoint.c
··· 65 65 goto repeat; 66 66 67 67 lock_page(page); 68 + if (page->mapping != mapping) { 69 + f2fs_put_page(page, 1); 70 + goto repeat; 71 + } 68 72 out: 69 73 mark_page_accessed(page); 70 74 return page;
+15 -3
fs/f2fs/data.c
··· 240 240 241 241 if (dn.data_blkaddr == NULL_ADDR) 242 242 return ERR_PTR(-ENOENT); 243 - 243 + repeat: 244 244 page = grab_cache_page(mapping, index); 245 245 if (!page) 246 246 return ERR_PTR(-ENOMEM); ··· 259 259 if (!PageUptodate(page)) { 260 260 f2fs_put_page(page, 1); 261 261 return ERR_PTR(-EIO); 262 + } 263 + if (page->mapping != mapping) { 264 + f2fs_put_page(page, 1); 265 + goto repeat; 262 266 } 263 267 return page; 264 268 } ··· 295 291 } 296 292 } 297 293 f2fs_put_dnode(&dn); 298 - 294 + repeat: 299 295 page = grab_cache_page(mapping, index); 300 296 if (!page) 301 297 return ERR_PTR(-ENOMEM); ··· 314 310 if (!PageUptodate(page)) { 315 311 f2fs_put_page(page, 1); 316 312 return ERR_PTR(-EIO); 313 + } 314 + if (page->mapping != mapping) { 315 + f2fs_put_page(page, 1); 316 + goto repeat; 317 317 } 318 318 } 319 319 ··· 619 611 *fsdata = NULL; 620 612 621 613 f2fs_balance_fs(sbi); 622 - 614 + repeat: 623 615 page = grab_cache_page_write_begin(mapping, index, flags); 624 616 if (!page) 625 617 return -ENOMEM; ··· 663 655 if (!PageUptodate(page)) { 664 656 f2fs_put_page(page, 1); 665 657 return -EIO; 658 + } 659 + if (page->mapping != mapping) { 660 + f2fs_put_page(page, 1); 661 + goto repeat; 666 662 } 667 663 } 668 664 out:
+4
fs/f2fs/file.c
··· 217 217 return; 218 218 219 219 lock_page(page); 220 + if (page->mapping != inode->i_mapping) { 221 + f2fs_put_page(page, 1); 222 + return; 223 + } 220 224 wait_on_page_writeback(page); 221 225 zero_user(page, offset, PAGE_CACHE_SIZE - offset); 222 226 set_page_dirty(page);
+16 -4
fs/f2fs/node.c
··· 674 674 int truncate_inode_blocks(struct inode *inode, pgoff_t from) 675 675 { 676 676 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 677 + struct address_space *node_mapping = sbi->node_inode->i_mapping; 677 678 int err = 0, cont = 1; 678 679 int level, offset[4], noffset[4]; 679 680 unsigned int nofs = 0; ··· 685 684 trace_f2fs_truncate_inode_blocks_enter(inode, from); 686 685 687 686 level = get_node_path(from, offset, noffset); 688 - 687 + restart: 689 688 page = get_node_page(sbi, inode->i_ino); 690 689 if (IS_ERR(page)) { 691 690 trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); ··· 749 748 if (offset[1] == 0 && 750 749 rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) { 751 750 lock_page(page); 751 + if (page->mapping != node_mapping) { 752 + f2fs_put_page(page, 1); 753 + goto restart; 754 + } 752 755 wait_on_page_writeback(page); 753 756 rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; 754 757 set_page_dirty(page); ··· 921 916 struct address_space *mapping = sbi->node_inode->i_mapping; 922 917 struct page *page; 923 918 int err; 924 - 919 + repeat: 925 920 page = grab_cache_page(mapping, nid); 926 921 if (!page) 927 922 return ERR_PTR(-ENOMEM); ··· 936 931 if (!PageUptodate(page)) { 937 932 f2fs_put_page(page, 1); 938 933 return ERR_PTR(-EIO); 934 + } 935 + if (page->mapping != mapping) { 936 + f2fs_put_page(page, 1); 937 + goto repeat; 939 938 } 940 939 got_it: 941 940 BUG_ON(nid != nid_of_node(page)); ··· 964 955 nid = get_nid(parent, start, false); 965 956 if (!nid) 966 957 return ERR_PTR(-ENOENT); 967 - 958 + repeat: 968 959 page = grab_cache_page(mapping, nid); 969 960 if (!page) 970 961 return ERR_PTR(-ENOMEM); ··· 990 981 blk_finish_plug(&plug); 991 982 992 983 lock_page(page); 993 - 984 + if (page->mapping != mapping) { 985 + f2fs_put_page(page, 1); 986 + goto repeat; 987 + } 994 988 page_hit: 995 989 if (!PageUptodate(page)) { 996 990 f2fs_put_page(page, 1);