Skip to contentSkip to conversation

shm cleanups

PATCH In review Christoph Rohland 4 participants 13 messages Nov 3, 1999 – Nov 5, 1999

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 shm cleanups

The following message was crippled somewhere on the way to linux-mm so I resend it:

Hi Linus,

Here is a patch against 2.3.25 which

1) avoids vmalloc in the shm coding.
2) cleans a lot of cruft out of the shm headers
3) makes shm sysctl'able

I did test it a lot on SMP/HIGHMEM. Since 2.3.25 with and without this breaks on swapping shm and other high memory load conditions I could not verify everything. But I would like to see this in the mainstream kernel. I will then proceed debugging the swapping issues.

Greetings
Christoph

arch/i386/kernel/sys_i386.c +64 -79
diff -uNr 2.3.25/arch/i386/kernel/sys_i386.c 2.3.25-shm3/arch/i386/kernel/sys_i386.c
@@ -116,86 +116,71 @@
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
-	if (call <= SEMCTL)
-		switch (call) {
-		case SEMOP:
-			return sys_semop (first, (struct sembuf *)ptr, second);
-		case SEMGET:
-			return sys_semget (first, second, third);
-		case SEMCTL: {
-			union semun fourth;
-			if (!ptr)
-				return -EINVAL;
-			if (get_user(fourth.__pad, (void **) ptr))
-				return -EFAULT;
-			return sys_semctl (first, second, third, fourth);
-			}
-		default:
-			return -EINVAL;
-		}
+        switch (call) {
+        case SEMOP:
+                return sys_semop (first, (struct sembuf *)ptr, second);
+        case SEMGET:
+                return sys_semget (first, second, third);
+        case SEMCTL: {
+                union semun fourth;
+                if (!ptr)
+                        return -EINVAL;
+                if (get_user(fourth.__pad, (void **) ptr))
+                        return -EFAULT;
+                return sys_semctl (first, second, third, fourth);
+        }
 
-	if (call <= MSGCTL) 
-		switch (call) {
-		case MSGSND:
-			return sys_msgsnd (first, (struct msgbuf *) ptr, 
-					  second, third);
-		case MSGRCV:
-			switch (version) {
-			case 0: {
-				struct ipc_kludge tmp;
-				if (!ptr)
-					return -EINVAL;
-				
-				if (copy_from_user(&tmp,
-						   (struct ipc_kludge *) ptr, 
-						   sizeof (tmp)))
-					return -EFAULT;
-				return sys_msgrcv (first, tmp.msgp, second,
-						   tmp.msgtyp, third);
-				}
-			default:
-				return sys_msgrcv (first,
-						   (struct msgbuf *) ptr,
-						   second, fifth, third);
-			}
-		case MSGGET:
-			return sys_msgget ((key_t) first, second);
-		case MSGCTL:
-			return sys_msgctl (first, second,
-					   (struct msqid_ds *) ptr);
-		default:
-			return -EINVAL;
-		}
-	if (call <= SHMCTL) 
-		switch (call) {
-		case SHMAT:
-			switch (version) {
-			default: {
-				ulong raddr;
-				ret = sys_shmat (first, (char *) ptr,
-						 second, &raddr);
-				if (ret)
-					return ret;
-				return put_user (raddr, (ulong *) third);
-			}
-			case 1:	/* iBCS2 emulator entry point */
-				if (!segment_eq(get_fs(), get_ds()))
-					return -EINVAL;
-				return sys_shmat (first, (char *) ptr,
-						  second, (ulong *) third);
-			}
-		case SHMDT: 
-			return sys_shmdt ((char *)ptr);
-		case SHMGET:
-			return sys_shmget (first, second, third);
-		case SHMCTL:
-			return sys_shmctl (first, second,
-					   (struct shmid_ds *) ptr);
-		default:
-			return -EINVAL;
-		}
-	
-	return -EINVAL;
+        case MSGSND:
+                return sys_msgsnd (first, (struct msgbuf *) ptr, 
+                                   second, third);
+        case MSGRCV:
+                switch (version) {
+                case 0: {
+                        struct ipc_kludge tmp;
+                        if (!ptr)
+                                return -EINVAL;
+                        
+                        if (copy_from_user(&tmp,
+                                           (struct ipc_kludge *) ptr, 
+                                           sizeof (tmp)))
+                                return -EFAULT;
+                        return sys_msgrcv (first, tmp.msgp, second,
+                                           tmp.msgtyp, third);
+                }
+                default:
+                        return sys_msgrcv (first,
+                                           (struct msgbuf *) ptr,
+                                           second, fifth, third);
+                }
+        case MSGGET:
+                return sys_msgget ((key_t) first, second);
+        case MSGCTL:
+                return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+
+        case SHMAT:
+                switch (version) {
+                default: {
+                        ulong raddr;
+                        ret = sys_shmat (first, (char *) ptr, second, &raddr);
+                        if (ret)
+                                return ret;
+                        return put_user (raddr, (ulong *) third);
+                }
+                case 1:	/* iBCS2 emulator entry point */
+                        if (!segment_eq(get_fs(), get_ds()))
+                                return -EINVAL;
+                        return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+                }
+        case SHMDT: 
+                return sys_shmdt ((char *)ptr);
+        case SHMGET:
+                return sys_shmget (first, second, third);
+        case SHMCTL:
+                return sys_shmctl (first, second,
+                                   (struct shmid_ds *) ptr);
+        default:
+                return -EINVAL;
+        }
 }
 
 /*
include/asm-alpha/shmparam.h +1 -42

48 lines not on this page · raw message

include/asm-arm/proc-armo/shmparam.h +1 -3
diff -uNr 2.3.25/include/asm-arm/proc-armo/shmparam.h 2.3.25-shm3/include/asm-arm/proc-armo/shmparam.h
@@ -9,9 +9,7 @@
 #ifndef __ASM_PROC_SHMPARAM_H
 #define __ASM_PROC_SHMPARAM_H
 
-#ifndef SHM_RANGE_START
-#define SHM_RANGE_START	0x00a00000
-#define SHM_RANGE_END	0x00c00000
+#ifndef SHMMAX
 #define SHMMAX		0x003fa000
 #endif
 
include/asm-arm/proc-armv/shmparam.h +1 -3
diff -uNr 2.3.25/include/asm-arm/proc-armv/shmparam.h 2.3.25-shm3/include/asm-arm/proc-armv/shmparam.h
@@ -10,9 +10,7 @@
 #ifndef __ASM_PROC_SHMPARAM_H
 #define __ASM_PROC_SHMPARAM_H
 
-#ifndef SHM_RANGE_START
-#define SHM_RANGE_START	0x50000000
-#define SHM_RANGE_END	0x60000000
+#ifndef SHMMAX
 #define SHMMAX		0x01000000
 #endif
 
include/asm-arm/shmparam.h +1 -34
diff -uNr 2.3.25/include/asm-arm/shmparam.h 2.3.25-shm3/include/asm-arm/shmparam.h
@@ -3,39 +3,6 @@
 
 #include <asm/proc/shmparam.h>
 
-/*
- * Format of a swap-entry for shared memory pages currently out in
- * swap space (see also mm/swap.c).
- *
- * SWP_TYPE = SHM_SWP_TYPE
- * SWP_OFFSET is used as follows:
- *
- *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
- *  bits 7..21: index of page within shared memory segment (SHM_IDX)
- *		(actually fewer bits get used since SHMMAX is so low)
- */
-
-/*
- * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
- * there is a static array of size SHMMNI.
- */
-#define _SHM_ID_BITS	7
-#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
-#define _SHM_IDX_BITS	15
-#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
-
-/*
- * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
- * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
- */
-
-#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
-#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
-#define SHMALL				/* max shm system wide (pages) */ \
-	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
-#define	SHMLBA PAGE_SIZE		/* attach addr a multiple of this */
-#define SHMSEG SHMMNI			/* max shared segs per process */
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
 
 #endif /* _ASMARM_SHMPARAM_H */
include/asm-i386/shmparam.h +1 -41

47 lines not on this page · raw message

include/asm-m68k/shmparam.h +1 -44

50 lines not on this page · raw message

include/asm-mips/shmparam.h +0 -40
diff -uNr 2.3.25/include/asm-mips/shmparam.h 2.3.25-shm3/include/asm-mips/shmparam.h
@@ -1,49 +1,9 @@
 #ifndef __ASM_MIPS_SHMPARAM_H
 #define __ASM_MIPS_SHMPARAM_H
 
-/* address range for shared memory attaches if no address passed to shmat() */
-#define SHM_RANGE_START	0x50000000
-#define SHM_RANGE_END	0x60000000
-
-/*
- * Format of a swap-entry for shared memory pages currently out in
- * swap space (see also mm/swap.c).
- *
- * SWP_TYPE = SHM_SWP_TYPE
- * SWP_OFFSET is used as follows:
- *
- *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
- *  bits 7..21: index of page within shared memory segment (SHM_IDX)
- *		(actually fewer bits get used since SHMMAX is so low)
- */
-
-/*
- * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
- * there is a static array of size SHMMNI.
- */
-#define _SHM_ID_BITS	7
-#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
-#define _SHM_IDX_BITS	15
-#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
-
-/*
- * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
- * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
- */
-
-#define SHMMAX 0x2000000		/* max shared seg size (bytes) */
-/* Try not to change the default shipped SHMMAX - people rely on it */
-
-#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
-#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
-#define SHMALL				/* max shm system wide (pages) */ \
-	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
 /*
  * This constant is very large but the ABI in it's wisdom says ...
  */
 #define	SHMLBA 0x40000			/* attach addr a multiple of this */
-#define SHMSEG SHMMNI			/* max shared segs per process */
 
 #endif /* __ASM_MIPS_SHMPARAM_H */
include/asm-ppc/shmparam.h +1 -39
diff -uNr 2.3.25/include/asm-ppc/shmparam.h 2.3.25-shm3/include/asm-ppc/shmparam.h
@@ -1,44 +1,6 @@
 #ifndef _PPC_SHMPARAM_H
 #define _PPC_SHMPARAM_H
 
-/* address range for shared memory attaches if no address passed to shmat() */
-#define SHM_RANGE_START	0x50000000
-#define SHM_RANGE_END	0x60000000
-
-/*
- * Format of a swap-entry for shared memory pages currently out in
- * swap space (see also mm/swap.c).
- *
- * SWP_TYPE = SHM_SWP_TYPE
- * SWP_OFFSET is used as follows:
- *
- *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
- *  bits 7..21: index of page within shared memory segment (SHM_IDX)
- *		(actually fewer bits get used since SHMMAX is so low)
- */
-
-/*
- * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
- * there is a static array of size SHMMNI.
- */
-#define _SHM_ID_BITS	7
-#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
-#define _SHM_IDX_BITS	15
-#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
-
-/*
- * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
- * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
- */
-
-#define SHMMAX 0x2000000		/* max shared seg size (bytes) */
-#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
-#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
-#define SHMALL				/* max shm system wide (pages) */ \
-	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
-#define	SHMLBA PAGE_SIZE		/* attach addr a multiple of this */
-#define SHMSEG SHMMNI			/* max shared segs per process */
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
 
 #endif /* _PPC_SHMPARAM_H */
include/asm-sh/shmparam.h +1 -41

47 lines not on this page · raw message

include/asm-sparc/shmparam.h +1 -39
diff -uNr 2.3.25/include/asm-sparc/shmparam.h 2.3.25-shm3/include/asm-sparc/shmparam.h
@@ -2,44 +2,6 @@
 #ifndef _ASMSPARC_SHMPARAM_H
 #define _ASMSPARC_SHMPARAM_H
 
-/* address range for shared memory attaches if no address passed to shmat() */
-#define SHM_RANGE_START	0x10000000
-#define SHM_RANGE_END	0x20000000
-
-/*
- * Format of a swap-entry for shared memory pages currently out in
- * swap space (see also mm/swap.c).
- *
- * SWP_TYPE = SHM_SWP_TYPE
- * SWP_OFFSET is used as follows:
- *
- *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
- *  bits 7..21: index of page within shared memory segment (SHM_IDX)
- *		(actually fewer bits get used since SHMMAX is so low)
- */
-
-/*
- * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
- * there is a static array of size SHMMNI.
- */
-#define _SHM_ID_BITS	7
-#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
-#define _SHM_IDX_BITS	15
-#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
-
-/*
- * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
- * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
- */
-
-#define SHMMAX 0x1000000		/* max shared seg size (bytes) */
-#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
-#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
-#define SHMALL				/* max shm system wide (pages) */ \
-	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
-#define	SHMLBA PAGE_SIZE		/* attach addr a multiple of this */
-#define SHMSEG SHMMNI			/* max shared segs per process */
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
 
 #endif /* _ASMSPARC_SHMPARAM_H */
include/asm-sparc64/shmparam.h +0 -40
diff -uNr 2.3.25/include/asm-sparc64/shmparam.h 2.3.25-shm3/include/asm-sparc64/shmparam.h
@@ -2,46 +2,6 @@
 #ifndef _ASMSPARC64_SHMPARAM_H
 #define _ASMSPARC64_SHMPARAM_H
 
-/* XXX Redo most of this... */
-
-/* address range for shared memory attaches if no address passed to shmat() */
-#define SHM_RANGE_START	0x10000000
-#define SHM_RANGE_END	0x20000000
-
-/*
- * Format of a swap-entry for shared memory pages currently out in
- * swap space (see also mm/swap.c).
- *
- * SWP_TYPE = SHM_SWP_TYPE
- * SWP_OFFSET is used as follows:
- *
- *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
- *  bits 7..21: index of page within shared memory segment (SHM_IDX)
- *		(actually fewer bits get used since SHMMAX is so low)
- */
-
-/*
- * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
- * there is a static array of size SHMMNI.
- */
-#define _SHM_ID_BITS	7
-#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
-#define _SHM_IDX_BITS	15
-#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
-
-/*
- * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
- * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
- */
-
-#define SHMMAX 0x1000000		/* max shared seg size (bytes) */
-#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
-#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
-#define SHMALL				/* max shm system wide (pages) */ \
-	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
 #define	SHMLBA (PAGE_SIZE<<1)		/* attach addr a multiple of this */
-#define SHMSEG SHMMNI			/* max shared segs per process */
 
 #endif /* _ASMSPARC64_SHMPARAM_H */
include/linux/shm.h +11 -9
diff -uNr 2.3.25/include/linux/shm.h 2.3.25-shm3/include/linux/shm.h
@@ -3,6 +3,17 @@
 
 #include <linux/ipc.h>
 
+/*
+ * SHMMAX, SHMMNI and SHMALL are upper limits are defaults which can
+ * be increased by sysctl
+ */
+
+#define SHMMAX 0x2000000		 /* max shared seg size (bytes) */
+#define SHMMIN 1 /* really PAGE_SIZE */	 /* min shared seg size (bytes) */
+#define SHMMNI 128			 /* max num of segs system wide */
+#define SHMALL (SHMMAX/PAGE_SIZE*SHMMNI) /* max shm system wide (pages) */
+#define SHMSEG SHMMNI			 /* max shared segs per process */
+
 #include <asm/shmparam.h>
 
 struct shmid_ds {
@@ -17,15 +28,6 @@
 	unsigned short 		shm_unused;	/* compatibility */
 	void 			*shm_unused2;	/* ditto - used by DIPC */
 	void			*shm_unused3;	/* unused */
-};
-
-struct shmid_kernel
-{	
-	struct shmid_ds		u;
-	/* the following are private */
-	unsigned long		shm_npages;	/* size of segment (pages) */
-	pte_t			*shm_pages;	/* array of ptrs to frames -> SHMMAX */ 
-	struct vm_area_struct	*attaches;	/* descriptors for attaches */
 };
 
 /* permission flag for shmget */
include/linux/swap.h +0 -11
diff -uNr 2.3.25/include/linux/swap.h 2.3.25-shm3/include/linux/swap.h
@@ -122,17 +122,6 @@
 asmlinkage long sys_swapoff(const char *);
 asmlinkage long sys_swapon(const char *, int);
 
-/*
- * vm_ops not present page codes for shared memory.
- *
- * Will go away eventually..
- */
-#define SHM_SWP_TYPE 0x20
-
-/*
- * swap cache stuff (in linux/mm/swap_state.c)
- */
-
 #define SWAP_CACHE_INFO
 
 #ifdef SWAP_CACHE_INFO
include/linux/sysctl.h +1 -2
diff -uNr 2.3.25/include/linux/sysctl.h 2.3.25-shm3/include/linux/sysctl.h
@@ -103,8 +103,7 @@
 	KERN_MSGPOOL=37,        /* int: Maximum system message pool size */
 	KERN_SYSRQ=38,		/* int: Sysreq enable */
 	KERN_MAX_THREADS=39,    /* int: Maximum nr of threads in the system */
- 	KERN_RANDOM=40,		/* Random driver */
- 	KERN_SHMALL=41		/* int: Maximum size of shared memory */
+ 	KERN_RANDOM=40		/* Random driver */
 };
 
ipc/shm.c +189 -75

537 lines not on this page · raw message

ipc/util.c +2 -0
diff -uNr 2.3.25/ipc/util.c 2.3.25-shm3/ipc/util.c
@@ -14,6 +14,8 @@
 #include <linux/init.h>
 #include <linux/msg.h>
 
+#include "util.h"
+
 #if defined(CONFIG_SYSVIPC)
 
 extern void sem_init (void), msg_init (void), shm_init (void);
ipc/util.h +12 -0
diff -uNr 2.3.25/ipc/util.h 2.3.25-shm3/ipc/util.h
@@ -0,0 +1,12 @@
+/*
+ * linux/ipc/util.h
+ * Copyright (C) 1999 Christoph Rohland
+ */
+
+/*
+ * IPCMNI is the absolute maximum for ipc identifier. This is used to
+ * detect stale identifiers
+ */
+#define IPCMNI (1<<15)          
+
+extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
kernel/sysctl.c +2 -2
diff -uNr 2.3.25/kernel/sysctl.c 2.3.25-shm3/kernel/sysctl.c
@@ -49,7 +49,7 @@
 extern int sg_big_buff;
 #endif
 #ifdef CONFIG_SYSVIPC
-extern size_t shmmax;
+extern size_t shm_prm[];
 #endif
 
 #ifdef __sparc__
@@ -213,7 +213,7 @@
 	{KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
 	 0644, NULL, &proc_dointvec},
 #ifdef CONFIG_SYSVIPC
-	{KERN_SHMMAX, "shmmax", &shmmax, sizeof (size_t),
+	{KERN_SHMMAX, "shmmax", &shm_prm, 3*sizeof (size_t),
 	 0644, NULL, &proc_doulongvec_minmax},
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
mm/swap_state.c +0 -4
diff -uNr 2.3.25/mm/swap_state.c 2.3.25-shm3/mm/swap_state.c
@@ -68,8 +68,6 @@
 	if (!entry.val)
 		goto out;
 	type = SWP_TYPE(entry);
-	if (type & SHM_SWP_TYPE)
-		goto out;
 	if (type >= nr_swapfiles)
 		goto bad_file;
 	p = type + swap_info;
@@ -115,8 +113,6 @@
 	if (!entry.val)
 		goto bad_entry;
 	type = SWP_TYPE(entry);
-	if (type & SHM_SWP_TYPE)
-		goto out;
 	if (type >= nr_swapfiles)
 		goto bad_file;
 	p = type + swap_info;
mm/swapfile.c +0 -4
diff -uNr 2.3.25/mm/swapfile.c 2.3.25-shm3/mm/swapfile.c
@@ -135,8 +135,6 @@
 		goto out;
 
 	type = SWP_TYPE(entry);
-	if (type & SHM_SWP_TYPE)
-		goto out;
 	if (type >= nr_swapfiles)
 		goto bad_nofile;
 	p = & swap_info[type];
@@ -190,8 +188,6 @@
 		goto new_swap_entry;
 	entry.val = page->index;
 	type = SWP_TYPE(entry);
-	if (type & SHM_SWP_TYPE)
-		goto new_swap_entry;
 	if (type >= nr_swapfiles)
 		goto new_swap_entry;
 	p = type + swap_info;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#1 lore raw
Quoted 4 lines · Christoph Rohland

I did test it a lot on SMP/HIGHMEM. Since 2.3.25 with and without this breaks on swapping shm and other high memory load conditions I could not verify everything. But I would like to see this in the mainstream kernel. I will then proceed debugging the swapping issues.

(i can see the problems too, but i've got no explanation either, working on it as well.)

-- mingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#2 lore raw

Hi Ingo,

Quoted 11 lines · Ingo Molnar
Quoted 4 lines · Christoph Rohland

I did test it a lot on SMP/HIGHMEM. Since 2.3.25 with and without this breaks on swapping shm and other high memory load conditions I could not verify everything. But I would like to see this in the mainstream kernel. I will then proceed debugging the swapping issues.

(i can see the problems too, but i've got no explanation either, working on it as well.)

-- mingo

After applying the following patch against ipc/shm.c (thanks to Larry Woodman <[email protected]> for the first one):

ipc/shm.c Thu Nov 4 12:47:14 1999 renamed from ipc/shm.c Tue Nov 2 12:46:29 1999 +2 -2
@@ -788,10 +789,10 @@
                unlock_kernel();
                return 0;
        }
-       if (page_count(page_map))
+       if (page_count(page_map) != 1)
                goto check_table;
        if (!(page_map = prepare_highmem_swapout(page_map)))
-               goto check_table;
+               goto failed;
        shp->shm_pages[idx] = swp_entry_to_pte(swap_entry);
        swap_successes++;
        shm_swp++;

791c791
< if (page_count(page_map))
---

Quoted 1 line
	if (page_count(page_map) != 1)

I get the same behaviour for shm swapping as on 2.3.22 as long as I only use 1G memory (HIGHMEM setting is always 64GB).

I do get swapping also with 8GB of RAM, but it runs out of memory before running out of swap space since prepare_highmem_swapout is failing way to often.

(It then locks up since it cannot free the shm segments and so is unable to free the memory. This should be perhaps addressed later in the oom handler. It cannot handle the case where nearly all memory is allocted in shm segments)

Greetings
Christoph
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#3 lore raw
Quoted 8 lines · Christoph Rohland

I do get swapping also with 8GB of RAM, but it runs out of memory before running out of swap space since prepare_highmem_swapout is failing way to often.

(It then locks up since it cannot free the shm segments and so is unable to free the memory. This should be perhaps addressed later in the oom handler. It cannot handle the case where nearly all memory is allocted in shm segments)

ho humm. I think prepare_highmem_swapout() has a design bug. It's way too naive in low memory situations, it should keep a short list of pages for emergency swapout. It's the GFP_ATOMIC that is failing too often, right?

i believe we should have some explicit mechanizm that tells vmscan that there is 'IO in progress which will result in more memory', to distinct between true out-of-memory and 'wait a little bit to get more RAM' cases? I think we'd have a lot less to worry about and there would be a much clearer distinction between true out-of-mem and 'just cannot allocate it right now but help is on the way' cases.

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#4 lore raw
Quoted 6 lines · Ingo Molnar
Quoted 3 lines · Christoph Rohland

I do get swapping also with 8GB of RAM, but it runs out of memory before running out of swap space since prepare_highmem_swapout is failing way to often.

Quoted 7 lines

ho humm. I think prepare_highmem_swapout() has a design bug. It's way too naive in low memory situations, it should keep a short list of pages for emergency swapout. It's the GFP_ATOMIC that is failing too often, right?

i believe we should have some explicit mechanizm that tells vmscan that there is 'IO in progress which will result in more memory', to distinct between true out-of-memory and 'wait a little bit to get more RAM' cases?

I think I see what is going on here. Kswapd sees that memory is low an "frees" a bunch of high memory pages, causing those pages to be shifted to low memory so the total number of free pages stays just as low as when kswapd started.

This can result in in-memory swap storms, we should probably limit the number of in-transit async himem pages to 256 or some other even smaller number.

regards,

Rik
--
The Internet is not a network of computers. It is a network of people. That is its real strength.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#5 lore raw
Quoted 4 lines · Rik van Riel

I think I see what is going on here. Kswapd sees that memory is low an "frees" a bunch of high memory pages, causing those pages to be shifted to low memory so the total number of free pages stays just as low as when kswapd started.

hm, kswapd should really be immune against this.

Quoted 3 lines

This can result in in-memory swap storms, we should probably limit the number of in-transit async himem pages to 256 or some other even smaller number.

i introduced some stupid balancing bugs, and i wrongly thought that the fixes are already in 2.3.25, but no, it's the pre1-2.3.26 kernel that is supposed to have balancing right. basically the fix is to restore the original behavior of not counting high memory in memory pressure. This might sound an unfair policy, but the real critical resource is low memory. If this ever proves to be a problematic approach then we still can make it more sophisticated.

[Christoph, are you still seeing the same kind of bad swapping behavior with pre1-2.3.26?]

-- mingo

ps. some people might ask why we want to swap on an 8GB box, but i think it's really an issue in production systems to provide some kind of 'rubber wall' instead of 'hard concrete' if the system is reaching its limits. adding (99% unused) swap space does exactly this.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#6 lore raw
Quoted 2 lines · Ingo Molnar

[Christoph, are you still seeing the same kind of bad swapping behavior with pre1-2.3.26?]

If you still get process killed during heavy swapout (cause OOM of an ATOMIC allocation) please try to increase the ATOMIC pool before designing a separate pool. We just have a pool for atomic allocation it may not be large enough for the increased pressure on the regular pages.

        echo 1000 2000 4000 >/proc/sys/vm/freepages

This way you'll basically waste 16mbyte of ram. It's just to check if the ATOMIC allocation shortage is the source of the segfault or not.

Signature · 5 lines
Andrea
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/
#7 lore raw
Quoted 10 lines · Andrea Arcangeli
Quoted 2 lines · Ingo Molnar

[Christoph, are you still seeing the same kind of bad swapping behavior with pre1-2.3.26?]

If you still get process killed during heavy swapout (cause OOM of an ATOMIC allocation) please try to increase the ATOMIC pool before designing a separate pool. We just have a pool for atomic allocation it may not be large enough for the increased pressure on the regular pages.

Quoted 4 lines
        echo 1000 2000 4000 >/proc/sys/vm/freepages

This way you'll basically waste 16mbyte of ram. It's just to check if the ATOMIC allocation shortage is the source of the segfault or not.

O.k. with and without these settings 2.3.26-pre2 looks pretty good about allocating bounce buffers and swapping highmem pages.

To swap shm the first part of the following patch is definitely needed. The second part makes the machine probably much more useable if we have problems allocating bounce buffers. Which now hardly ever happens when stresstesting my 8GB machine.

Linus, could you please apply this?

Christoph

ipc/shm.c Thu Nov 4 12:47:14 1999 renamed from ipc/shm.c Tue Nov 2 12:46:29 1999 +2 -2
@@ -788,10 +789,10 @@
                unlock_kernel();
                return 0;
        }
-       if (page_count(page_map))
+       if (page_count(page_map) != 1)
                goto check_table;
        if (!(page_map = prepare_highmem_swapout(page_map)))
-               goto check_table;
+               goto failed;
        shp->shm_pages[idx] = swp_entry_to_pte(swap_entry);
        swap_successes++;
        shm_swp++;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#8 lore raw

ipc/shm.c Thu Nov 4 12:47:14 1999 line 795

Quoted 3 lines · Christoph Rohland

if (!(page_map = prepare_highmem_swapout(page_map)))

ipc/shm.c Thu Nov 4 12:47:14 1999 renamed from ipc/shm.c Tue Nov 2 12:46:29 1999 +1 -1
-               goto check_table;
+               goto failed;

This fragment isn't correct. You may fail too early and so you may get a task killed due OOM even if you still have lots of regular pages queued in a shm segment.

Signature · 5 lines
Andrea
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/
#9 lore raw
Quoted 9 lines · Andrea Arcangeli

ipc/shm.c Thu Nov 4 12:47:14 1999 line 795

Quoted 3 lines · Christoph Rohland

if (!(page_map = prepare_highmem_swapout(page_map)))

ipc/shm.c Thu Nov 4 12:47:14 1999 renamed from ipc/shm.c Tue Nov 2 12:46:29 1999 +1 -1
-               goto check_table;
+               goto failed;

This fragment isn't correct. You may fail too early and so you may get a task killed due OOM even if you still have lots of regular pages queued in a shm segment.

Yes I know it is questionable, but if prepare_highmem_swapout fails we are in the highmem area and probably most of the rest of shm is also there. So we only consume a lot of CPU if going on and calling prepare_highmem_swapout again and again..

prepare_highmem_swapout should not fail (and does not fail very often in 2.3.26-pre2) In 2.3.25 the machine effectivly locked up when it failed (and it failed very often).

On 2.3.26-pre2 I do not see a difference between the two versions. So I do not know which way will be better.

Christoph
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#10 lore raw
Quoted 3 lines · Christoph Rohland

Yes I know it is questionable, but if prepare_highmem_swapout fails we are in the highmem area and probably most of the rest of shm is also there. So we only consume a lot of CPU if going on and calling

If prepare_highmem_swapout fails maybe all the regular pages are allocated in the rest of the shm segment and to free them and do progresses you should continue to properly shrink the VM.

Quoted 1 line

prepare_highmem_swapout again and again..

That will happen in the patological unlikely to happen case so the performance of such path is not an issue.

Andrea

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#11 lore raw
Quoted 6 lines · Andrea Arcangeli
Quoted 3 lines · Christoph Rohland

Yes I know it is questionable, but if prepare_highmem_swapout fails we are in the highmem area and probably most of the rest of shm is also there. So we only consume a lot of CPU if going on and calling

Quoted 8 lines

If prepare_highmem_swapout fails maybe all the regular pages are allocated in the rest of the shm segment and to free them and do progresses you should continue to properly shrink the VM.

Quoted 1 line

prepare_highmem_swapout again and again..

That will happen in the patological unlikely to happen case so the performance of such path is not an issue.

So we only need the first part of the patch.

Christoph

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#12 lore raw
In reply to Ingo Molnar
Quoted 21 lines · Ingo Molnar
Quoted 4 lines · Rik van Riel

I think I see what is going on here. Kswapd sees that memory is low an "frees" a bunch of high memory pages, causing those pages to be shifted to low memory so the total number of free pages stays just as low as when kswapd started.

hm, kswapd should really be immune against this.

Quoted 3 lines

This can result in in-memory swap storms, we should probably limit the number of in-transit async himem pages to 256 or some other even smaller number.

i introduced some stupid balancing bugs, and i wrongly thought that the fixes are already in 2.3.25, but no, it's the pre1-2.3.26 kernel that is supposed to have balancing right. basically the fix is to restore the original behavior of not counting high memory in memory pressure. This might sound an unfair policy, but the real critical resource is low memory. If this ever proves to be a problematic approach then we still can make it more sophisticated.

Quoted 2 lines

[Christoph, are you still seeing the same kind of bad swapping behavior with pre1-2.3.26?]

No, after applying the following patch, it is much better now:

ipc/shm.c Fri Nov 5 10:54:09 1999 renamed from ipc/shm.c Fri Nov 5 10:25:40 1999 +2 -2
@@ -897,10 +897,10 @@
                unlock_kernel();
                return 0;
        }
-       if (page_count(page_map))
+       if (page_count(page_map) != 1)
                goto check_table;
        if (!(page_map = prepare_highmem_swapout(page_map)))
-               goto check_table;
+               goto failed;
        SHM_ENTRY (shp, idx) = swp_entry_to_pte(swap_entry);
        swap_successes++;
        shm_swp++;

[root@ls3016 src]# ipcs -um

------ Shared Memory Status --------
segments allocated 274
pages allocated 2244608
pages resident 2043405
pages swapped 177175
Swap performance: 251917 attempts 241439 successes

[root@ls3016 src]# cat /proc/meminfo
total: used: free: shared: buffers: cached:

Mem:  4152516608 4133502976 19013632        0   512000 21954560
Swap: 4133269504 725725184 3407544320
MemTotal:   8249496 kB
MemFree:      18568 kB
MemShared:        0 kB
Buffers:        500 kB
Cached:       21440 kB
HighTotal:  7471104 kB
HighFree:         0 kB
SwapTotal:  4036396 kB
SwapFree:   3327680 kB

and output of vmstat 5:

   procs                      memory    swap          io     system         cpu
 r  b  w   swpd   free   buff  cache  si  so    bi    bo   in    cs  us  sy  id
17  3  1 424020   2688    244  25932 407 10280   104  2570  970  1490   0  92   7
20  0  1 461380   1688    240  24464 467 8048   120  2012  758  1188   0  87  13
18  1  1 484676  27728    240  20692 994 5644   250  1411  549   910   0  90  10
19  0  1 497068   2732    260  25700 2690 5055   675  1264  532  1038   0  81  18
11  8  1 529820   4692    272  25192 4232 10643  1063  2661 1191  2126   0  85  15
17  2  1 559572   1472    264  19860 2538 8473   641  2118  919  1653   0  81  19
12  7  1 609780   1944    268  24280 3620 13611   912  3404 1485  2799   0  79  21
15  3  1 648148   1836    272  16648 8061 15666  2025  3916 2227  3731   0  78  22
12  6  1 692208   3044    280  23192 5394 14147  1359  3538 1768  3163   0  75  25
12  5  0 742160   2256    276  38144 6208 16190  1559  4047 1936  3419   0  78  22

So we have very few failes. Probably we never get caught by the second part of the above patch any more.

Quoted 6 lines

-- mingo

ps. some people might ask why we want to swap on an 8GB box, but i think it's really an issue in production systems to provide some kind of 'rubber wall' instead of 'hard concrete' if the system is reaching its limits. adding (99% unused) swap space does exactly this.

Yes we need it for ERP applications. You do not beleive how many data is processed sometimes in business applications.

And to have a hard limit for production servers is always a reason to use something else.

Christoph
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/