shm cleanup
Subsystems (12)
PATCH 1/1 shm cleanup
Hi Linus,
Here is my shm cleanup patch. It survived several days of stress testing on my 8way.
It is somewhat conservative wrt to locking and the truncate logic could be optimised for speed. But it is robust and passes all the SYSV compatibilty tests I remembered.
I had to implement some semantic change to writepage in vmscan.c to be able to implement SHM_LOCK handling. I actually do not understand how we can ignore the return code from writepage... If writepage fails we probably should not simply drop the page?
You do not see the SYSV shared memory segments any more in the mounted instance and loose the ability to 'rm' them instead of using ipcrm. Also /proc/sys/kernel/shm{all,mni} are back. Therefore you can now mount several shm filesystem instances for POSIX shm and when we implement read and write for the fs we will have a fullblown swapfs like Solaris' tmpfs.
Greetings
Christoph
Documentation/Changes +8 -8
@@ -115,18 +115,18 @@ the kernel source tree for all the gory details. System V shared memory is now implemented via a virtual filesystem. -You do not have to mount it to use it as long as you can live with the -default maxima for shared memory and segments. If you wish to change -these variables, you have to mount it with the options nr_blocks -and / or nr_inodes. POSIX shared memory is also now implemented via a -virtual filesystem. If you want to use it, you'll need to mount the -filesystem. The recommended mount location is /dev/shm, and adding the -following line to /etc/fstab should take care of things: +You do not have to mount it to use it. SYSV shared memory limits are +set via /proc/sys/kernel/shm{max,all,mni}. You should mount the +filesystem under /dev/shm to be able to use POSIX shared +memory. Adding the following line to /etc/fstab should take care of +things: none /dev/shm shm defaults 0 0 Remember to create the directory that you intend to mount shm on if -necessary. +necessary (The entry is automagically created if you use devfs). You +can set limits for the number of blocks and inodes used by the +filesystem with the mount options nr_blocks and nr_inodes. The Logical Volume Manager (LVM) is now in the kernel. If you want to use this, you'll need to install the necessary LVM toolset.
drivers/char/mem.c +1 -1
@@ -438,7 +438,7 @@static int mmap_zero (struct file * file,struct vm_area_struct * vma) {if (vma->vm_flags &VM_SHARED ) -return map_zero_setup (vma); +return shmem_zero_setup (vma);if (zeromap_page_range (vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))return -EAGAIN ;return 0 ;
include/linux/fs.h +3 -0
@@ -283,6 +283,7 @@#include <linux/efs_fs_i.h> #include <linux/coda_fs_i.h> #include <linux/romfs_fs_i.h> +#include <linux/shmem_fs.h> #include <linux/smb_fs_i.h> #include <linux/hfs_fs_i.h> #include <linux/adfs_fs_i.h>
@@ -441,6 +442,7 @@struct ufs_inode_info ufs_i;struct efs_inode_info efs_i;struct romfs_inode_info romfs_i; +struct shmem_inode_info shmem_i;struct coda_inode_info coda_i;struct smb_inode_info smbfs_i;struct hfs_inode_info hfs_i;
@@ -685,6 +687,7 @@struct affs_sb_info affs_sb;struct ufs_sb_info ufs_sb;struct efs_sb_info efs_sb; +struct shmem_sb_info shmem_sb;struct romfs_sb_info romfs_sb;struct smb_sb_info smbfs_sb;struct hfs_sb_info hfs_sb;
include/linux/mm.h +4 -10
@@ -129,15 +129,6 @@ };/* -* A swap entry has to fit into a "unsigned long", as -* the entry is hidden in the "index" field of the -* swapper address space. -*/ -typedef struct { -unsigned long val; -}swp_entry_t ; - -/* * Try to keep the most commonly accessed fields in single cache lines * here (16 bytes or greater). This ordering should be particularly * beneficial on 32-bit processors.
@@ -390,7 +381,10 @@extern void clear_page_tables (struct mm_struct *,unsigned long ,int ); -extern int map_zero_setup (struct vm_area_struct *); +int shmem_swapout (struct page * page,struct file *file); +struct page *shmem_nopage (struct vm_area_struct * vma,unsigned long address,int no_share); +struct file *shmem_file_setup (char * name,loff_t size); +extern int shmem_zero_setup (struct vm_area_struct *);extern void zap_page_range (struct mm_struct *mm,unsigned long address,unsigned long size);extern int copy_page_range (struct mm_struct *dst,struct mm_struct *src,struct vm_area_struct *vma);
include/linux/pagemap.h +2 -0
@@ -67,6 +67,8 @@#define page_hash (mapping,index) (page_hash_table+_page_hashfn(mapping,index)) +extern struct page *__find_get_page (struct address_space *mapping, +unsigned long offset,struct page **hash);extern struct page *__find_lock_page (struct address_space * mapping,unsigned long index,struct page **hash);extern void lock_page (struct page *page);
include/linux/shmem_fs.h +37 -0
@@ -0,0 +1,37 @@ +#ifndef __SHMEM_FS_H +#define __SHMEM_FS_H + +/* inode in-kernel data */ + +#define SHMEM_NR_DIRECT 16 + +/* +* A swap entry has to fit into a "unsigned long", as +* the entry is hidden in the "index" field of the +* swapper address space. +* +* We have to move it here, since not every user of fs.h is including +* mm.h, but m.h is including fs.h via sched .h :-/ +*/ +typedef struct { +unsigned long val; +}swp_entry_t ; + +struct shmem_inode_info { +spinlock_t lock; +swp_entry_t i_direct[SHMEM_NR_DIRECT ];/* for the first blocks */ +swp_entry_t **i_indirect;/* doubly indirect blocks */ +unsigned long swapped; +int locked;/* into memory */ +struct list_head list; +}; + +struct shmem_sb_info { +unsigned long max_blocks;/* How many blocks are allowed */ +unsigned long free_blocks;/* How many are left for allocation */ +unsigned long max_inodes;/* How many inodes are allowed */ +unsigned long free_inodes;/* How many are left for allocation */ +spinlock_t stat_lock; +}; + +#endif
include/linux/swap.h +2 -0
@@ -291,6 +291,8 @@#define swap_device_lock (p) spin_lock(&p->sdev_lock)#define swap_device_unlock (p) spin_unlock(&p->sdev_lock) +extern void shmem_unuse (swp_entry_t entry,struct page *page); +#endif /* __KERNEL__*/ #endif /* _LINUX_SWAP_H */
ipc/shm.c +168 -1222
1,644 lines not on this page · raw message
ipc/util.c +0 -14
@@ -345,11 +345,6 @@return ; } -int shm_swap (int prio,int gfp_mask) -{ -return 0 ; -} -asmlinkage long sys_semget (key_t key,int nsems,int semflg) {return -ENOSYS ;
@@ -404,15 +399,6 @@asmlinkage long sys_shmctl (int shmid,int cmd,struct shmid_ds *buf) {return -ENOSYS ; -} - -void shm_unuse (swp_entry_t entry,struct page *page) -{ -} - -int map_zero_setup (struct vm_area_struct *vma) -{ -return -EINVAL ; }#endif /* CONFIG_SYSVIPC */
kernel/sysctl.c +6 -0
@@ -63,6 +63,8 @@#endif #ifdef CONFIG_SYSVIPC extern size_t shm_ctlmax; +extern size_t shm_ctlall; +extern int shm_ctlmni;extern int msg_ctlmax;extern int msg_ctlmnb;extern int msg_ctlmni;
@@ -208,6 +210,10 @@#ifdef CONFIG_SYSVIPC {KERN_SHMMAX ,"shmmax" , &shm_ctlmax,sizeof (size_t ), 0644, NULL, &proc_doulongvec_minmax}, + {KERN_SHMALL, "shmall", &shm_ctlall, sizeof (size_t), + 0644, NULL, &proc_doulongvec_minmax}, + {KERN_SHMMNI, "shmmni", &shm_ctlmni, sizeof (int), + 0644, NULL, &proc_dointvec}, {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int), 0644, NULL, &proc_dointvec}, {KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
mm/Makefile +2 -1
@@ -11,7 +11,8 @@ obj-y := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \ vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \ - page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o + page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o \ + shmem.o obj-$(CONFIG_HIGHMEM) += highmem.o
mm/filemap.c +2 -2
@@ -542,8 +542,8 @@* a rather lightweight function, finding and getting a reference to a * hashed page atomically, waiting for it if it's locked. */ -static struct page *__find_get_page (struct address_space *mapping, -unsigned long offset,struct page **hash) +struct page *__find_get_page (struct address_space *mapping, +unsigned long offset,struct page **hash) {struct page *page;
mm/mmap.c +1 -1
@@ -333,7 +333,7 @@if (error) goto unmap_and_free_vma; }else if (flags &MAP_SHARED ) { - error =map_zero_setup (vma); + error =shmem_zero_setup (vma);if (error) goto free_vma; }
mm/shmem.c +882 -0
882 lines not on this page · raw message
mm/swapfile.c +1 -1
@@ -375,7 +375,7 @@for_each_task (p)unuse_process (p->mm, entry, page);read_unlock (&tasklist_lock); -shm_unuse (entry, page); +shmem_unuse (entry, page);/* Now get rid of the extra reference to the temporary page we've been using. */ page_cache_release (page);
mm/vmscan.c +8 -2
@@ -603,6 +603,8 @@*/ if (PageDirty (page)) {int (*writepage)(struct page *) = page->mapping->a_ops->writepage; +int result; +if (!writepage) goto page_active;
@@ -619,12 +621,16 @@page_cache_get (page);spin_unlock (&pagemap_lru_lock); -writepage (page); + result =writepage (page);page_cache_release (page);/* And re-start the thing.. */ spin_lock (&pagemap_lru_lock); -continue ; +if (result !=1 ) +continue ; +/* writepage refused to do anything */ +SetPageDirty (page); + goto page_active; }/*
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
Please read the FAQ at http://www.tux.org/lkml/