diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-01-10 21:43:52 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-01-10 21:43:52 -0500 |
commit | 99cd7074891f87c49660e3b2880564324a4733ac (patch) | |
tree | 903d2665bcb445f1f265d1adf7a99f265bcefc15 /mm/shmem.c | |
parent | e8a9cbf6ae620d9e5ba9cb42001c033287a284a3 (diff) | |
parent | c59765042f53a79a7a65585042ff463b69cb248c (diff) |
Merge commit 'v2.6.29-rc1' into tracing/urgent
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 102 |
1 files changed, 85 insertions, 17 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index f1b0d4871f3a..5d0de96c9789 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 | |||
32 | static 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> |
@@ -920,7 +928,11 @@ found: | |||
920 | error = 1; | 928 | error = 1; |
921 | if (!inode) | 929 | if (!inode) |
922 | goto out; | 930 | goto out; |
923 | /* Precharge page using GFP_KERNEL while we can wait */ | 931 | /* |
932 | * Charge page using GFP_KERNEL while we can wait. | ||
933 | * Charged back to the user(not to caller) when swap account is used. | ||
934 | * add_to_page_cache() will be called with GFP_NOWAIT. | ||
935 | */ | ||
924 | error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL); | 936 | error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL); |
925 | if (error) | 937 | if (error) |
926 | goto out; | 938 | goto out; |
@@ -1312,15 +1324,19 @@ repeat: | |||
1312 | } else { | 1324 | } else { |
1313 | shmem_swp_unmap(entry); | 1325 | shmem_swp_unmap(entry); |
1314 | spin_unlock(&info->lock); | 1326 | spin_unlock(&info->lock); |
1315 | unlock_page(swappage); | ||
1316 | page_cache_release(swappage); | ||
1317 | if (error == -ENOMEM) { | 1327 | if (error == -ENOMEM) { |
1318 | /* allow reclaim from this memory cgroup */ | 1328 | /* allow reclaim from this memory cgroup */ |
1319 | error = mem_cgroup_shrink_usage(current->mm, | 1329 | error = mem_cgroup_shrink_usage(swappage, |
1330 | current->mm, | ||
1320 | gfp); | 1331 | gfp); |
1321 | if (error) | 1332 | if (error) { |
1333 | unlock_page(swappage); | ||
1334 | page_cache_release(swappage); | ||
1322 | goto failed; | 1335 | goto failed; |
1336 | } | ||
1323 | } | 1337 | } |
1338 | unlock_page(swappage); | ||
1339 | page_cache_release(swappage); | ||
1324 | goto repeat; | 1340 | goto repeat; |
1325 | } | 1341 | } |
1326 | } else if (sgp == SGP_READ && !filepage) { | 1342 | } else if (sgp == SGP_READ && !filepage) { |
@@ -1371,7 +1387,7 @@ repeat: | |||
1371 | 1387 | ||
1372 | /* Precharge page while we can wait, compensate after */ | 1388 | /* Precharge page while we can wait, compensate after */ |
1373 | error = mem_cgroup_cache_charge(filepage, current->mm, | 1389 | error = mem_cgroup_cache_charge(filepage, current->mm, |
1374 | gfp & ~__GFP_HIGHMEM); | 1390 | GFP_KERNEL); |
1375 | if (error) { | 1391 | if (error) { |
1376 | page_cache_release(filepage); | 1392 | page_cache_release(filepage); |
1377 | shmem_unacct_blocks(info->flags, 1); | 1393 | shmem_unacct_blocks(info->flags, 1); |
@@ -1444,7 +1460,6 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1444 | if (error) | 1460 | if (error) |
1445 | return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); | 1461 | return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); |
1446 | 1462 | ||
1447 | mark_page_accessed(vmf->page); | ||
1448 | return ret | VM_FAULT_LOCKED; | 1463 | return ret | VM_FAULT_LOCKED; |
1449 | } | 1464 | } |
1450 | 1465 | ||
@@ -2486,7 +2501,6 @@ static struct file_system_type tmpfs_fs_type = { | |||
2486 | .get_sb = shmem_get_sb, | 2501 | .get_sb = shmem_get_sb, |
2487 | .kill_sb = kill_litter_super, | 2502 | .kill_sb = kill_litter_super, |
2488 | }; | 2503 | }; |
2489 | static struct vfsmount *shm_mnt; | ||
2490 | 2504 | ||
2491 | static int __init init_tmpfs(void) | 2505 | static int __init init_tmpfs(void) |
2492 | { | 2506 | { |
@@ -2525,7 +2539,51 @@ out4: | |||
2525 | shm_mnt = ERR_PTR(error); | 2539 | shm_mnt = ERR_PTR(error); |
2526 | return error; | 2540 | return error; |
2527 | } | 2541 | } |
2528 | module_init(init_tmpfs) | 2542 | |
2543 | #else /* !CONFIG_SHMEM */ | ||
2544 | |||
2545 | /* | ||
2546 | * tiny-shmem: simple shmemfs and tmpfs using ramfs code | ||
2547 | * | ||
2548 | * This is intended for small system where the benefits of the full | ||
2549 | * shmem code (swap-backed and resource-limited) are outweighed by | ||
2550 | * their complexity. On systems without swap this code should be | ||
2551 | * effectively equivalent, but much lighter weight. | ||
2552 | */ | ||
2553 | |||
2554 | #include <linux/ramfs.h> | ||
2555 | |||
2556 | static struct file_system_type tmpfs_fs_type = { | ||
2557 | .name = "tmpfs", | ||
2558 | .get_sb = ramfs_get_sb, | ||
2559 | .kill_sb = kill_litter_super, | ||
2560 | }; | ||
2561 | |||
2562 | static int __init init_tmpfs(void) | ||
2563 | { | ||
2564 | BUG_ON(register_filesystem(&tmpfs_fs_type) != 0); | ||
2565 | |||
2566 | shm_mnt = kern_mount(&tmpfs_fs_type); | ||
2567 | BUG_ON(IS_ERR(shm_mnt)); | ||
2568 | |||
2569 | return 0; | ||
2570 | } | ||
2571 | |||
2572 | int shmem_unuse(swp_entry_t entry, struct page *page) | ||
2573 | { | ||
2574 | return 0; | ||
2575 | } | ||
2576 | |||
2577 | #define shmem_file_operations ramfs_file_operations | ||
2578 | #define shmem_vm_ops generic_file_vm_ops | ||
2579 | #define shmem_get_inode ramfs_get_inode | ||
2580 | #define shmem_acct_size(a, b) 0 | ||
2581 | #define shmem_unacct_size(a, b) do {} while (0) | ||
2582 | #define SHMEM_MAX_BYTES LLONG_MAX | ||
2583 | |||
2584 | #endif /* CONFIG_SHMEM */ | ||
2585 | |||
2586 | /* common code */ | ||
2529 | 2587 | ||
2530 | /** | 2588 | /** |
2531 | * shmem_file_setup - get an unlinked file living in tmpfs | 2589 | * shmem_file_setup - get an unlinked file living in tmpfs |
@@ -2569,12 +2627,20 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) | |||
2569 | if (!inode) | 2627 | if (!inode) |
2570 | goto close_file; | 2628 | goto close_file; |
2571 | 2629 | ||
2630 | #ifdef CONFIG_SHMEM | ||
2572 | SHMEM_I(inode)->flags = flags & VM_ACCOUNT; | 2631 | SHMEM_I(inode)->flags = flags & VM_ACCOUNT; |
2632 | #endif | ||
2573 | d_instantiate(dentry, inode); | 2633 | d_instantiate(dentry, inode); |
2574 | inode->i_size = size; | 2634 | inode->i_size = size; |
2575 | inode->i_nlink = 0; /* It is unlinked */ | 2635 | inode->i_nlink = 0; /* It is unlinked */ |
2576 | init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, | 2636 | init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, |
2577 | &shmem_file_operations); | 2637 | &shmem_file_operations); |
2638 | |||
2639 | #ifndef CONFIG_MMU | ||
2640 | error = ramfs_nommu_expand_for_mapping(inode, size); | ||
2641 | if (error) | ||
2642 | goto close_file; | ||
2643 | #endif | ||
2578 | return file; | 2644 | return file; |
2579 | 2645 | ||
2580 | close_file: | 2646 | close_file: |
@@ -2606,3 +2672,5 @@ int shmem_zero_setup(struct vm_area_struct *vma) | |||
2606 | vma->vm_ops = &shmem_vm_ops; | 2672 | vma->vm_ops = &shmem_vm_ops; |
2607 | return 0; | 2673 | return 0; |
2608 | } | 2674 | } |
2675 | |||
2676 | module_init(init_tmpfs) | ||