aboutsummaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/shmem.c')
-rw-r--r--mm/shmem.c104
1 files changed, 86 insertions, 18 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index dd5588f5d939..75199888a6bd 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -14,31 +14,39 @@
14 * Copyright (c) 2004, Luke Kenneth Casson Leighton <lkcl@lkcl.net> 14 * Copyright (c) 2004, Luke Kenneth Casson Leighton <lkcl@lkcl.net>
15 * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> 15 * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
16 * 16 *
17 * tiny-shmem:
18 * Copyright (c) 2004, 2008 Matt Mackall <mpm@selenic.com>
19 *
17 * This file is released under the GPL. 20 * This file is released under the GPL.
18 */ 21 */
19 22
23#include <linux/fs.h>
24#include <linux/init.h>
25#include <linux/vfs.h>
26#include <linux/mount.h>
27#include <linux/file.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/swap.h>
31
32static struct vfsmount *shm_mnt;
33
34#ifdef CONFIG_SHMEM
20/* 35/*
21 * This virtual memory filesystem is heavily based on the ramfs. It 36 * This virtual memory filesystem is heavily based on the ramfs. It
22 * extends ramfs by the ability to use swap and honor resource limits 37 * extends ramfs by the ability to use swap and honor resource limits
23 * which makes it a completely usable filesystem. 38 * which makes it a completely usable filesystem.
24 */ 39 */
25 40
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/fs.h>
29#include <linux/xattr.h> 41#include <linux/xattr.h>
30#include <linux/exportfs.h> 42#include <linux/exportfs.h>
31#include <linux/generic_acl.h> 43#include <linux/generic_acl.h>
32#include <linux/mm.h>
33#include <linux/mman.h> 44#include <linux/mman.h>
34#include <linux/file.h>
35#include <linux/swap.h>
36#include <linux/pagemap.h> 45#include <linux/pagemap.h>
37#include <linux/string.h> 46#include <linux/string.h>
38#include <linux/slab.h> 47#include <linux/slab.h>
39#include <linux/backing-dev.h> 48#include <linux/backing-dev.h>
40#include <linux/shmem_fs.h> 49#include <linux/shmem_fs.h>
41#include <linux/mount.h>
42#include <linux/writeback.h> 50#include <linux/writeback.h>
43#include <linux/vfs.h> 51#include <linux/vfs.h>
44#include <linux/blkdev.h> 52#include <linux/blkdev.h>
@@ -921,7 +929,11 @@ found:
921 error = 1; 929 error = 1;
922 if (!inode) 930 if (!inode)
923 goto out; 931 goto out;
924 /* Precharge page using GFP_KERNEL while we can wait */ 932 /*
933 * Charge page using GFP_KERNEL while we can wait.
934 * Charged back to the user(not to caller) when swap account is used.
935 * add_to_page_cache() will be called with GFP_NOWAIT.
936 */
925 error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL); 937 error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
926 if (error) 938 if (error)
927 goto out; 939 goto out;
@@ -1313,15 +1325,19 @@ repeat:
1313 } else { 1325 } else {
1314 shmem_swp_unmap(entry); 1326 shmem_swp_unmap(entry);
1315 spin_unlock(&info->lock); 1327 spin_unlock(&info->lock);
1316 unlock_page(swappage);
1317 page_cache_release(swappage);
1318 if (error == -ENOMEM) { 1328 if (error == -ENOMEM) {
1319 /* allow reclaim from this memory cgroup */ 1329 /* allow reclaim from this memory cgroup */
1320 error = mem_cgroup_shrink_usage(current->mm, 1330 error = mem_cgroup_shrink_usage(swappage,
1331 current->mm,
1321 gfp); 1332 gfp);
1322 if (error) 1333 if (error) {
1334 unlock_page(swappage);
1335 page_cache_release(swappage);
1323 goto failed; 1336 goto failed;
1337 }
1324 } 1338 }
1339 unlock_page(swappage);
1340 page_cache_release(swappage);
1325 goto repeat; 1341 goto repeat;
1326 } 1342 }
1327 } else if (sgp == SGP_READ && !filepage) { 1343 } else if (sgp == SGP_READ && !filepage) {
@@ -1372,7 +1388,7 @@ repeat:
1372 1388
1373 /* Precharge page while we can wait, compensate after */ 1389 /* Precharge page while we can wait, compensate after */
1374 error = mem_cgroup_cache_charge(filepage, current->mm, 1390 error = mem_cgroup_cache_charge(filepage, current->mm,
1375 gfp & ~__GFP_HIGHMEM); 1391 GFP_KERNEL);
1376 if (error) { 1392 if (error) {
1377 page_cache_release(filepage); 1393 page_cache_release(filepage);
1378 shmem_unacct_blocks(info->flags, 1); 1394 shmem_unacct_blocks(info->flags, 1);
@@ -1445,7 +1461,6 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1445 if (error) 1461 if (error)
1446 return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); 1462 return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
1447 1463
1448 mark_page_accessed(vmf->page);
1449 return ret | VM_FAULT_LOCKED; 1464 return ret | VM_FAULT_LOCKED;
1450} 1465}
1451 1466
@@ -2487,7 +2502,6 @@ static struct file_system_type tmpfs_fs_type = {
2487 .get_sb = shmem_get_sb, 2502 .get_sb = shmem_get_sb,
2488 .kill_sb = kill_litter_super, 2503 .kill_sb = kill_litter_super,
2489}; 2504};
2490static struct vfsmount *shm_mnt;
2491 2505
2492static int __init init_tmpfs(void) 2506static int __init init_tmpfs(void)
2493{ 2507{
@@ -2526,7 +2540,51 @@ out4:
2526 shm_mnt = ERR_PTR(error); 2540 shm_mnt = ERR_PTR(error);
2527 return error; 2541 return error;
2528} 2542}
2529module_init(init_tmpfs) 2543
2544#else /* !CONFIG_SHMEM */
2545
2546/*
2547 * tiny-shmem: simple shmemfs and tmpfs using ramfs code
2548 *
2549 * This is intended for small system where the benefits of the full
2550 * shmem code (swap-backed and resource-limited) are outweighed by
2551 * their complexity. On systems without swap this code should be
2552 * effectively equivalent, but much lighter weight.
2553 */
2554
2555#include <linux/ramfs.h>
2556
2557static struct file_system_type tmpfs_fs_type = {
2558 .name = "tmpfs",
2559 .get_sb = ramfs_get_sb,
2560 .kill_sb = kill_litter_super,
2561};
2562
2563static int __init init_tmpfs(void)
2564{
2565 BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
2566
2567 shm_mnt = kern_mount(&tmpfs_fs_type);
2568 BUG_ON(IS_ERR(shm_mnt));
2569
2570 return 0;
2571}
2572
2573int shmem_unuse(swp_entry_t entry, struct page *page)
2574{
2575 return 0;
2576}
2577
2578#define shmem_file_operations ramfs_file_operations
2579#define shmem_vm_ops generic_file_vm_ops
2580#define shmem_get_inode ramfs_get_inode
2581#define shmem_acct_size(a, b) 0
2582#define shmem_unacct_size(a, b) do {} while (0)
2583#define SHMEM_MAX_BYTES LLONG_MAX
2584
2585#endif /* CONFIG_SHMEM */
2586
2587/* common code */
2530 2588
2531/** 2589/**
2532 * shmem_file_setup - get an unlinked file living in tmpfs 2590 * shmem_file_setup - get an unlinked file living in tmpfs
@@ -2570,12 +2628,20 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
2570 if (!inode) 2628 if (!inode)
2571 goto close_file; 2629 goto close_file;
2572 2630
2573 SHMEM_I(inode)->flags = flags & VM_ACCOUNT; 2631#ifdef CONFIG_SHMEM
2632 SHMEM_I(inode)->flags = (flags & VM_NORESERVE) ? 0 : VM_ACCOUNT;
2633#endif
2574 d_instantiate(dentry, inode); 2634 d_instantiate(dentry, inode);
2575 inode->i_size = size; 2635 inode->i_size = size;
2576 inode->i_nlink = 0; /* It is unlinked */ 2636 inode->i_nlink = 0; /* It is unlinked */
2577 init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, 2637 init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
2578 &shmem_file_operations); 2638 &shmem_file_operations);
2639
2640#ifndef CONFIG_MMU
2641 error = ramfs_nommu_expand_for_mapping(inode, size);
2642 if (error)
2643 goto close_file;
2644#endif
2579 return file; 2645 return file;
2580 2646
2581close_file: 2647close_file:
@@ -2608,3 +2674,5 @@ int shmem_zero_setup(struct vm_area_struct *vma)
2608 vma->vm_ops = &shmem_vm_ops; 2674 vma->vm_ops = &shmem_vm_ops;
2609 return 0; 2675 return 0;
2610} 2676}
2677
2678module_init(init_tmpfs)