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

tmpfs: preliminary minor tidyups

Make a few cleanups in mm/shmem.c, before going on to complicate it.

shmem_alloc_page() will become more complicated: we can't afford to to
have that complication duplicated between a CONFIG_NUMA version and a
!CONFIG_NUMA version, so rearrange the #ifdef'ery there to yield a
single shmem_swapin() and a single shmem_alloc_page().

Yes, it's a shame to inflict the horrid pseudo-vma on non-NUMA
configurations, but eliminating it is a larger cleanup: I have an
alloc_pages_mpol() patchset not yet ready - mpol handling is subtle and
bug-prone, and changed yet again since my last version.

Move __SetPageLocked, __SetPageSwapBacked from shmem_getpage_gfp() to
shmem_alloc_page(): that SwapBacked flag will be useful in future, to
help to distinguish different cases appropriately.

And the SGP_DIRTY variant of SGP_CACHE is hard to understand and of
little use (IIRC it dates back to when shmem_getpage() returned the page
unlocked): kill it and do the necessary in shmem_file_read_iter().

But an arm64 build then complained that info may be uninitialized (where
shmem_getpage_gfp() deletes a freshly alloced page beyond eof), and
advancing to an "sgp <= SGP_CACHE" test jogged it back to reality.

Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Andres Lagar-Cavilla <andreslc@google.com>
Cc: Yang Shi <yang.shi@linaro.org>
Cc: Ning Qu <quning@gmail.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Hugh Dickins and committed by
Linus Torvalds
75edd345 fa9949da

+32 -43
+6
include/linux/mempolicy.h
··· 228 228 { 229 229 } 230 230 231 + static inline struct mempolicy * 232 + mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) 233 + { 234 + return NULL; 235 + } 236 + 231 237 #define vma_policy(vma) NULL 232 238 233 239 static inline int
+26 -43
mm/shmem.c
··· 101 101 enum sgp_type { 102 102 SGP_READ, /* don't exceed i_size, don't allocate page */ 103 103 SGP_CACHE, /* don't exceed i_size, may allocate page */ 104 - SGP_DIRTY, /* like SGP_CACHE, but set new page dirty */ 105 104 SGP_WRITE, /* may exceed i_size, may allocate !Uptodate page */ 106 105 SGP_FALLOC, /* like SGP_WRITE, but make existing page Uptodate */ 107 106 }; ··· 168 169 169 170 /* 170 171 * ... whereas tmpfs objects are accounted incrementally as 171 - * pages are allocated, in order to allow huge sparse files. 172 + * pages are allocated, in order to allow large sparse files. 172 173 * shmem_getpage reports shmem_acct_block failure as -ENOSPC not -ENOMEM, 173 174 * so that a failure on a sparse tmpfs mapping will give SIGBUS not OOM. 174 175 */ ··· 946 947 return 0; 947 948 } 948 949 949 - #ifdef CONFIG_NUMA 950 - #ifdef CONFIG_TMPFS 950 + #if defined(CONFIG_NUMA) && defined(CONFIG_TMPFS) 951 951 static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol) 952 952 { 953 953 char buffer[64]; ··· 970 972 } 971 973 return mpol; 972 974 } 973 - #endif /* CONFIG_TMPFS */ 975 + #else /* !CONFIG_NUMA || !CONFIG_TMPFS */ 976 + static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol) 977 + { 978 + } 979 + static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) 980 + { 981 + return NULL; 982 + } 983 + #endif /* CONFIG_NUMA && CONFIG_TMPFS */ 984 + #ifndef CONFIG_NUMA 985 + #define vm_policy vm_private_data 986 + #endif 974 987 975 988 static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp, 976 989 struct shmem_inode_info *info, pgoff_t index) ··· 1017 1008 pvma.vm_ops = NULL; 1018 1009 pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index); 1019 1010 1020 - page = alloc_page_vma(gfp, &pvma, 0); 1011 + page = alloc_pages_vma(gfp, 0, &pvma, 0, numa_node_id(), false); 1012 + if (page) { 1013 + __SetPageLocked(page); 1014 + __SetPageSwapBacked(page); 1015 + } 1021 1016 1022 1017 /* Drop reference taken by mpol_shared_policy_lookup() */ 1023 1018 mpol_cond_put(pvma.vm_policy); 1024 1019 1025 1020 return page; 1026 1021 } 1027 - #else /* !CONFIG_NUMA */ 1028 - #ifdef CONFIG_TMPFS 1029 - static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol) 1030 - { 1031 - } 1032 - #endif /* CONFIG_TMPFS */ 1033 - 1034 - static inline struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp, 1035 - struct shmem_inode_info *info, pgoff_t index) 1036 - { 1037 - return swapin_readahead(swap, gfp, NULL, 0); 1038 - } 1039 - 1040 - static inline struct page *shmem_alloc_page(gfp_t gfp, 1041 - struct shmem_inode_info *info, pgoff_t index) 1042 - { 1043 - return alloc_page(gfp); 1044 - } 1045 - #endif /* CONFIG_NUMA */ 1046 - 1047 - #if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS) 1048 - static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) 1049 - { 1050 - return NULL; 1051 - } 1052 - #endif 1053 1022 1054 1023 /* 1055 1024 * When a page is moved from swapcache to shmem filecache (either by the ··· 1071 1084 copy_highpage(newpage, oldpage); 1072 1085 flush_dcache_page(newpage); 1073 1086 1074 - __SetPageLocked(newpage); 1075 - __SetPageSwapBacked(newpage); 1076 1087 SetPageUptodate(newpage); 1077 1088 set_page_private(newpage, swap_index); 1078 1089 SetPageSwapCache(newpage); ··· 1140 1155 page = NULL; 1141 1156 } 1142 1157 1143 - if (sgp != SGP_WRITE && sgp != SGP_FALLOC && 1158 + if (sgp <= SGP_CACHE && 1144 1159 ((loff_t)index << PAGE_SHIFT) >= i_size_read(inode)) { 1145 1160 error = -EINVAL; 1146 1161 goto unlock; ··· 1260 1275 error = -ENOMEM; 1261 1276 goto decused; 1262 1277 } 1263 - 1264 - __SetPageLocked(page); 1265 - __SetPageSwapBacked(page); 1266 1278 if (sgp == SGP_WRITE) 1267 1279 __SetPageReferenced(page); 1268 1280 ··· 1303 1321 flush_dcache_page(page); 1304 1322 SetPageUptodate(page); 1305 1323 } 1306 - if (sgp == SGP_DIRTY) 1307 - set_page_dirty(page); 1308 1324 } 1309 1325 1310 1326 /* Perhaps the file has been truncated since we checked */ 1311 - if (sgp != SGP_WRITE && sgp != SGP_FALLOC && 1327 + if (sgp <= SGP_CACHE && 1312 1328 ((loff_t)index << PAGE_SHIFT) >= i_size_read(inode)) { 1313 1329 if (alloced) { 1314 1330 ClearPageDirty(page); ··· 1613 1633 * and even mark them dirty, so it cannot exceed the max_blocks limit. 1614 1634 */ 1615 1635 if (!iter_is_iovec(to)) 1616 - sgp = SGP_DIRTY; 1636 + sgp = SGP_CACHE; 1617 1637 1618 1638 index = *ppos >> PAGE_SHIFT; 1619 1639 offset = *ppos & ~PAGE_MASK; ··· 1639 1659 error = 0; 1640 1660 break; 1641 1661 } 1642 - if (page) 1662 + if (page) { 1663 + if (sgp == SGP_CACHE) 1664 + set_page_dirty(page); 1643 1665 unlock_page(page); 1666 + } 1644 1667 1645 1668 /* 1646 1669 * We must evaluate after, since reads (unlike writes)