diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index fcd19d323f9f..8a82342a8595 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/ctype.h> | 49 | #include <linux/ctype.h> |
50 | #include <linux/migrate.h> | 50 | #include <linux/migrate.h> |
51 | #include <linux/highmem.h> | 51 | #include <linux/highmem.h> |
52 | #include <linux/backing-dev.h> | ||
53 | 52 | ||
54 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
55 | #include <asm/div64.h> | 54 | #include <asm/div64.h> |
@@ -96,9 +95,9 @@ static inline struct page *shmem_dir_alloc(gfp_t gfp_mask) | |||
96 | * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE: | 95 | * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE: |
97 | * might be reconsidered if it ever diverges from PAGE_SIZE. | 96 | * might be reconsidered if it ever diverges from PAGE_SIZE. |
98 | * | 97 | * |
99 | * __GFP_MOVABLE is masked out as swap vectors cannot move | 98 | * Mobility flags are masked out as swap vectors cannot move |
100 | */ | 99 | */ |
101 | return alloc_pages((gfp_mask & ~__GFP_MOVABLE) | __GFP_ZERO, | 100 | return alloc_pages((gfp_mask & ~GFP_MOVABLE_MASK) | __GFP_ZERO, |
102 | PAGE_CACHE_SHIFT-PAGE_SHIFT); | 101 | PAGE_CACHE_SHIFT-PAGE_SHIFT); |
103 | } | 102 | } |
104 | 103 | ||
@@ -972,7 +971,7 @@ static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_ | |||
972 | *nodelist++ = '\0'; | 971 | *nodelist++ = '\0'; |
973 | if (nodelist_parse(nodelist, *policy_nodes)) | 972 | if (nodelist_parse(nodelist, *policy_nodes)) |
974 | goto out; | 973 | goto out; |
975 | if (!nodes_subset(*policy_nodes, node_online_map)) | 974 | if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY])) |
976 | goto out; | 975 | goto out; |
977 | } | 976 | } |
978 | if (!strcmp(value, "default")) { | 977 | if (!strcmp(value, "default")) { |
@@ -997,9 +996,11 @@ static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_ | |||
997 | err = 0; | 996 | err = 0; |
998 | } else if (!strcmp(value, "interleave")) { | 997 | } else if (!strcmp(value, "interleave")) { |
999 | *policy = MPOL_INTERLEAVE; | 998 | *policy = MPOL_INTERLEAVE; |
1000 | /* Default to nodes online if no nodelist */ | 999 | /* |
1000 | * Default to online nodes with memory if no nodelist | ||
1001 | */ | ||
1001 | if (!nodelist) | 1002 | if (!nodelist) |
1002 | *policy_nodes = node_online_map; | 1003 | *policy_nodes = node_states[N_HIGH_MEMORY]; |
1003 | err = 0; | 1004 | err = 0; |
1004 | } | 1005 | } |
1005 | out: | 1006 | out: |
@@ -1025,8 +1026,8 @@ static struct page *shmem_swapin_async(struct shared_policy *p, | |||
1025 | return page; | 1026 | return page; |
1026 | } | 1027 | } |
1027 | 1028 | ||
1028 | struct page *shmem_swapin(struct shmem_inode_info *info, swp_entry_t entry, | 1029 | static struct page *shmem_swapin(struct shmem_inode_info *info, |
1029 | unsigned long idx) | 1030 | swp_entry_t entry, unsigned long idx) |
1030 | { | 1031 | { |
1031 | struct shared_policy *p = &info->policy; | 1032 | struct shared_policy *p = &info->policy; |
1032 | int i, num; | 1033 | int i, num; |
@@ -1061,7 +1062,8 @@ shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, | |||
1061 | return page; | 1062 | return page; |
1062 | } | 1063 | } |
1063 | #else | 1064 | #else |
1064 | static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes) | 1065 | static inline int shmem_parse_mpol(char *value, int *policy, |
1066 | nodemask_t *policy_nodes) | ||
1065 | { | 1067 | { |
1066 | return 1; | 1068 | return 1; |
1067 | } | 1069 | } |
@@ -1109,7 +1111,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, | |||
1109 | * Normally, filepage is NULL on entry, and either found | 1111 | * Normally, filepage is NULL on entry, and either found |
1110 | * uptodate immediately, or allocated and zeroed, or read | 1112 | * uptodate immediately, or allocated and zeroed, or read |
1111 | * in under swappage, which is then assigned to filepage. | 1113 | * in under swappage, which is then assigned to filepage. |
1112 | * But shmem_readpage and shmem_prepare_write pass in a locked | 1114 | * But shmem_readpage and shmem_write_begin pass in a locked |
1113 | * filepage, which may be found not uptodate by other callers | 1115 | * filepage, which may be found not uptodate by other callers |
1114 | * too, and may need to be copied from the swappage read in. | 1116 | * too, and may need to be copied from the swappage read in. |
1115 | */ | 1117 | */ |
@@ -1327,14 +1329,14 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1327 | } | 1329 | } |
1328 | 1330 | ||
1329 | #ifdef CONFIG_NUMA | 1331 | #ifdef CONFIG_NUMA |
1330 | int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new) | 1332 | static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new) |
1331 | { | 1333 | { |
1332 | struct inode *i = vma->vm_file->f_path.dentry->d_inode; | 1334 | struct inode *i = vma->vm_file->f_path.dentry->d_inode; |
1333 | return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new); | 1335 | return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new); |
1334 | } | 1336 | } |
1335 | 1337 | ||
1336 | struct mempolicy * | 1338 | static struct mempolicy *shmem_get_policy(struct vm_area_struct *vma, |
1337 | shmem_get_policy(struct vm_area_struct *vma, unsigned long addr) | 1339 | unsigned long addr) |
1338 | { | 1340 | { |
1339 | struct inode *i = vma->vm_file->f_path.dentry->d_inode; | 1341 | struct inode *i = vma->vm_file->f_path.dentry->d_inode; |
1340 | unsigned long idx; | 1342 | unsigned long idx; |
@@ -1446,7 +1448,7 @@ static const struct inode_operations shmem_symlink_inode_operations; | |||
1446 | static const struct inode_operations shmem_symlink_inline_operations; | 1448 | static const struct inode_operations shmem_symlink_inline_operations; |
1447 | 1449 | ||
1448 | /* | 1450 | /* |
1449 | * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write; | 1451 | * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin; |
1450 | * but providing them allows a tmpfs file to be used for splice, sendfile, and | 1452 | * but providing them allows a tmpfs file to be used for splice, sendfile, and |
1451 | * below the loop driver, in the generic fashion that many filesystems support. | 1453 | * below the loop driver, in the generic fashion that many filesystems support. |
1452 | */ | 1454 | */ |
@@ -1459,10 +1461,30 @@ static int shmem_readpage(struct file *file, struct page *page) | |||
1459 | } | 1461 | } |
1460 | 1462 | ||
1461 | static int | 1463 | static int |
1462 | shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) | 1464 | shmem_write_begin(struct file *file, struct address_space *mapping, |
1465 | loff_t pos, unsigned len, unsigned flags, | ||
1466 | struct page **pagep, void **fsdata) | ||
1463 | { | 1467 | { |
1464 | struct inode *inode = page->mapping->host; | 1468 | struct inode *inode = mapping->host; |
1465 | return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL); | 1469 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
1470 | *pagep = NULL; | ||
1471 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); | ||
1472 | } | ||
1473 | |||
1474 | static int | ||
1475 | shmem_write_end(struct file *file, struct address_space *mapping, | ||
1476 | loff_t pos, unsigned len, unsigned copied, | ||
1477 | struct page *page, void *fsdata) | ||
1478 | { | ||
1479 | struct inode *inode = mapping->host; | ||
1480 | |||
1481 | set_page_dirty(page); | ||
1482 | page_cache_release(page); | ||
1483 | |||
1484 | if (pos+copied > inode->i_size) | ||
1485 | i_size_write(inode, pos+copied); | ||
1486 | |||
1487 | return copied; | ||
1466 | } | 1488 | } |
1467 | 1489 | ||
1468 | static ssize_t | 1490 | static ssize_t |
@@ -2219,7 +2241,7 @@ static int shmem_fill_super(struct super_block *sb, | |||
2219 | unsigned long blocks = 0; | 2241 | unsigned long blocks = 0; |
2220 | unsigned long inodes = 0; | 2242 | unsigned long inodes = 0; |
2221 | int policy = MPOL_DEFAULT; | 2243 | int policy = MPOL_DEFAULT; |
2222 | nodemask_t policy_nodes = node_online_map; | 2244 | nodemask_t policy_nodes = node_states[N_HIGH_MEMORY]; |
2223 | 2245 | ||
2224 | #ifdef CONFIG_TMPFS | 2246 | #ifdef CONFIG_TMPFS |
2225 | /* | 2247 | /* |
@@ -2338,8 +2360,8 @@ static const struct address_space_operations shmem_aops = { | |||
2338 | .set_page_dirty = __set_page_dirty_no_writeback, | 2360 | .set_page_dirty = __set_page_dirty_no_writeback, |
2339 | #ifdef CONFIG_TMPFS | 2361 | #ifdef CONFIG_TMPFS |
2340 | .readpage = shmem_readpage, | 2362 | .readpage = shmem_readpage, |
2341 | .prepare_write = shmem_prepare_write, | 2363 | .write_begin = shmem_write_begin, |
2342 | .commit_write = simple_commit_write, | 2364 | .write_end = shmem_write_end, |
2343 | #endif | 2365 | #endif |
2344 | .migratepage = migrate_page, | 2366 | .migratepage = migrate_page, |
2345 | }; | 2367 | }; |