Skip to contentSkip to conversation

VM deadlock prevention -v4

RFC PATCH In review Peter Zijlstra 10 participants 30 messages Aug 12, 2006 – Aug 24, 2006

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

cover VM deadlock prevention -v4

Hi,

here the latest effort, it includes a whole new trivial allocator with a horrid name and an almost full rewrite of the deadlock prevention core. This version does not do anything per device and hence does not depend on the new netdev_alloc_skb() API.

The reason to add a second allocator to the receive side is twofold:
1) it allows easy detection of the memory pressure / OOM situation;
2) it allows the receive path to be unbounded and go at full speed when resources permit.

The choice of using the global memalloc reserve as a mempool makes that the new allocator has to release pages as soon as possible; if we were to hoard pages in the allocator the memalloc reserve would not get replenished readily.

Peter

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw

RFC PATCH 1/4 pfn_to_kaddr() for UML

Update UML with a proper 'pfn_to_kaddr()' definition, the SROG allocator uses it.

---
 include/asm-um/page.h |    2 ++
 1 file changed, 2 insertions(+)
include/asm-um/page.h +2 -0
Index: linux-2.6/include/asm-um/page.h
===================================================================
@@ -111,6 +111,8 @@ extern unsigned long uml_physmem;
 #define pfn_valid(pfn) ((pfn) < max_mapnr)
 #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
 
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
 extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
 #define HAVE_ARCH_VALIDATE
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw

RFC PATCH 2/4 SROG allocator

In reply to Peter Zijlstra

A simple memory allocator with a horrid name.
(if someone knows the proper name of this thing, please speak up. It's too trivial to not be described somewhere)

Its use is for cases where you have multiple objects of various sizes that have similar livetimes and should release pages as soon as possible.

In a few words, it allocates pages and packs the objects in them, the pages are kept on a list and the free space blocks are kept in address order. On free insertion sort is used and front and back merges are tried.

---
 include/linux/srog.h |   14 ++
 mm/Makefile          |    3 
 mm/srog.c            |  290 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 306 insertions(+), 1 deletion(-)
include/linux/srog.h new file +14 -0
Index: linux-2.6/include/linux/srog.h
===================================================================
@@ -0,0 +1,14 @@
+#ifndef _LINUX_SROG_H_
+#define _LINUX_SROG_H_
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+extern void *srog_alloc(void *srogp, unsigned long size, gfp_t gfp_mask);
+extern void srog_free(void *srogp, void *obj);
+extern void srog_link(void *srogp1, void *srogp2);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SSROG_H_ */
mm/Makefile +2 -1
Index: linux-2.6/mm/Makefile
===================================================================
@@ -10,7 +10,8 @@ mmu-$(CONFIG_MMU)	:= fremap.o highmem.o 
 obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
 			   page_alloc.o page-writeback.o pdflush.o \
 			   readahead.o swap.o truncate.o vmscan.o \
-			   prio_tree.o util.o mmzone.o vmstat.o $(mmu-y)
+			   prio_tree.o util.o mmzone.o vmstat.o srog.o \
+			   $(mmu-y)
 
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
mm/srog.c new file +289 -0

289 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw

RFC PATCH 3/4 deadlock prevention core

In reply to Peter Zijlstra

The core of the VM deadlock avoidance framework.

Quoted 1 line

From the 'user' side of things it provides a function to mark a 'struct sock'

as SOCK_MEMALLOC, meaning this socket may dip into the memalloc reserves on the receive side.

When *dev_alloc_skb() finds it cannot allocate a struct sk_buff the regular way it will grab some memory from the memalloc reserve.

Network paths will drop !SOCK_MEMALLOC packets ASAP when reserve is being used.

Memalloc sk_buff allocations are not done from the SLAB but are done using the new SROG allocator. sk_buff::memalloc records this exception so that kfree_skbmem()/skb_clone() and others can do the right thing.

---
 include/linux/gfp.h    |    3 -
 include/linux/mmzone.h |    1 
 include/linux/skbuff.h |    6 +-
 include/net/sock.h     |   40 +++++++++++++++
 mm/page_alloc.c        |   41 ++++++++++++++-
 net/core/skbuff.c      |  127 ++++++++++++++++++++++++++++++++++++++++++++-----
 net/core/sock.c        |   74 ++++++++++++++++++++++++++++
 net/ipv4/af_inet.c     |    3 +
 net/ipv4/icmp.c        |    3 +
 net/ipv4/tcp_ipv4.c    |    3 +
 net/ipv4/udp.c         |    8 ++-
 11 files changed, 290 insertions(+), 19 deletions(-)
include/linux/gfp.h +2 -1
Index: linux-2.6/include/linux/gfp.h
===================================================================
@@ -46,6 +46,7 @@ struct vm_area_struct;
 #define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
+#define __GFP_MEMALLOC  ((__force gfp_t)0x40000u) /* Use emergency reserves */
 
 #define __GFP_BITS_SHIFT 20	/* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
@@ -54,7 +55,7 @@ struct vm_area_struct;
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
 			__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
 			__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
-			__GFP_NOMEMALLOC|__GFP_HARDWALL)
+			__GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_MEMALLOC)
 
 /* This equals 0, but use constants in case they ever change */
 #define GFP_NOWAIT	(GFP_ATOMIC & ~__GFP_HIGH)
include/linux/mmzone.h +1 -0
Index: linux-2.6/include/linux/mmzone.h
===================================================================
@@ -420,6 +420,7 @@ int percpu_pagelist_fraction_sysctl_hand
 					void __user *, size_t *, loff_t *);
 int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *, int,
 			struct file *, void __user *, size_t *, loff_t *);
+int adjust_memalloc_reserve(int bytes);
 
 #include <linux/topology.h>
 /* Returns the number of the current Node. */
include/linux/skbuff.h +4 -2
Index: linux-2.6/include/linux/skbuff.h
===================================================================
@@ -282,7 +282,8 @@ struct sk_buff {
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				memalloc:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
@@ -1086,7 +1087,8 @@ static inline void __skb_queue_purge(str
 static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
 					      gfp_t gfp_mask)
 {
-	struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
+	struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD,
+			gfp_mask | __GFP_MEMALLOC);
 	if (likely(skb))
 		skb_reserve(skb, NET_SKB_PAD);
 	return skb;
include/net/sock.h +40 -0
Index: linux-2.6/include/net/sock.h
===================================================================
@@ -391,6 +391,7 @@ enum sock_flags {
 	SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
 	SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
 	SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
+	SOCK_MEMALLOC, /* protocol can use memalloc reserve */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -413,6 +414,45 @@ static inline int sock_flag(struct sock 
 	return test_bit(flag, &sk->sk_flags);
 }
 
+static inline int sk_is_memalloc(struct sock *sk)
+{
+	return sock_flag(sk, SOCK_MEMALLOC);
+}
+
+/*
+ * Is this high enough, or do we want it to depend on the number of
+ * online devices and online CPUs?
+ *
+ *  #define MAX_CONCURRENT_SKBS (64*nr_devices*num_online_cpus())
+ */
+#define MAX_CONCURRENT_SKBS	128
+
+/*
+ * Used to count skb payloads.
+ *
+ * The assumption is that the sk_buffs themselves are small enough to fit
+ * in the remaining page space.
+ */
+extern atomic_t memalloc_skbs_used;
+
+static inline int memalloc_skbs_try_inc(void)
+{
+	return atomic_add_unless(&memalloc_skbs_used, 1, MAX_CONCURRENT_SKBS);
+}
+
+static inline void memalloc_skbs_dec(void)
+{
+	atomic_dec(&memalloc_skbs_used);
+}
+
+static inline int memalloc_skbs_available(void)
+{
+	return atomic_read(&memalloc_skbs_used) < MAX_CONCURRENT_SKBS;
+}
+
+extern int sk_adjust_memalloc(int);
+extern int sk_set_memalloc(struct sock *sk);
+
 static inline void sk_acceptq_removed(struct sock *sk)
 {
 	sk->sk_ack_backlog--;
mm/page_alloc.c +38 -3

65 lines not on this page · raw message

net/core/skbuff.c +115 -12

231 lines not on this page · raw message

net/ipv4/icmp.c +3 -0
Index: linux-2.6/net/ipv4/icmp.c
===================================================================
@@ -938,6 +938,9 @@ int icmp_rcv(struct sk_buff *skb)
 			goto error;
 	}
 
+	if (unlikely(skb->memalloc))
+		goto drop;
+
 	if (!pskb_pull(skb, sizeof(struct icmphdr)))
 		goto error;
 
net/ipv4/tcp_ipv4.c +3 -0
Index: linux-2.6/net/ipv4/tcp_ipv4.c
===================================================================
@@ -1093,6 +1093,9 @@ int tcp_v4_rcv(struct sk_buff *skb)
 	if (!sk)
 		goto no_tcp_socket;
 
+	if (unlikely(skb->memalloc && !sk_is_memalloc(sk)))
+		goto discard_and_relse;
+
 process:
 	if (sk->sk_state == TCP_TIME_WAIT)
 		goto do_time_wait;
net/ipv4/udp.c +7 -1
Index: linux-2.6/net/ipv4/udp.c
===================================================================
@@ -1136,7 +1136,12 @@ int udp_rcv(struct sk_buff *skb)
 	sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);
 
 	if (sk != NULL) {
-		int ret = udp_queue_rcv_skb(sk, skb);
+		int ret;
+
+		if (unlikely(skb->memalloc && !sk_is_memalloc(sk)))
+			goto drop_noncritical;
+
+		ret = udp_queue_rcv_skb(sk, skb);
 		sock_put(sk);
 
 		/* a return value > 0 means to resubmit the input, but
@@ -1147,6 +1152,7 @@ int udp_rcv(struct sk_buff *skb)
 		return 0;
 	}
 
+drop_noncritical:
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto drop;
 	nf_reset(skb);
net/ipv4/af_inet.c +3 -0
Index: linux-2.6/net/ipv4/af_inet.c
===================================================================
@@ -132,6 +132,9 @@ void inet_sock_destruct(struct sock *sk)
 {
 	struct inet_sock *inet = inet_sk(sk);
 
+	if (sk_is_memalloc(sk))
+		sk_adjust_memalloc(-1);
+
 	__skb_queue_purge(&sk->sk_receive_queue);
 	__skb_queue_purge(&sk->sk_error_queue);
 
net/core/sock.c +74 -0

86 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

include/linux/gfp.h struct vm_area_struct; · line 49

Quoted 9 lines · Peter Zijlstra

Index: linux-2.6/include/linux/gfp.h
===================================================================

include/linux/gfp.h +1 -0
@@ -46,6 +46,7 @@ struct vm_area_struct;
 #define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
+#define __GFP_MEMALLOC  ((__force gfp_t)0x40000u) /* Use emergency reserves */

This symbol name has nothing to do with its purpose. The entire area of code you are modifying could be described as having something to do with 'memalloc'.

GFP_EMERGENCY or GFP_USE_RESERVES or somesuch would be a far better symbol name.

I recognize that is matches with GFP_NOMEMALLOC, but that doesn't change the situation anyway. In fact, a cleanup patch to rename GFP_NOMEMALLOC would be nice.

Jeff

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw

rename *MEMALLOC flags (was: Re: [RFC][PATCH 3/4] deadlock prevention core)

Quoted 15 lines · Jeff Garzik

include/linux/gfp.h struct vm_area_struct; · line 49

Quoted 9 lines · Peter Zijlstra

Index: linux-2.6/include/linux/gfp.h
===================================================================

include/linux/gfp.h +1 -0
@@ -46,6 +46,7 @@ struct vm_area_struct;
 #define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
+#define __GFP_MEMALLOC  ((__force gfp_t)0x40000u) /* Use emergency reserves */

This symbol name has nothing to do with its purpose. The entire area of code you are modifying could be described as having something to do with 'memalloc'.

Quoted 6 lines

GFP_EMERGENCY or GFP_USE_RESERVES or somesuch would be a far better symbol name.

I recognize that is matches with GFP_NOMEMALLOC, but that doesn't change the situation anyway. In fact, a cleanup patch to rename GFP_NOMEMALLOC would be nice.

I'm rather bad at picking names, but here goes:

PF_MEMALLOC -> PF_EMERGALLOC
__GFP_NOMEMALLOC -> __GFP_NOEMERGALLOC
__GFP_MEMALLOC -> __GFP_EMERGALLOC

Is that suitable and shall I prepare patches? Or do we want more ppl to chime in and have a few more rounds?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw

Re: rename *MEMALLOC flags (was: Re: [RFC][PATCH 3/4] deadlock prevention core)

Quoted 24 lines · Peter Zijlstra
Quoted 16 lines · Jeff Garzik

include/linux/gfp.h struct vm_area_struct; · line 48

Quoted 8 lines · Peter Zijlstra

Index: linux-2.6/include/linux/gfp.h
===================================================================

include/linux/gfp.h +0 -0
@@ -46,6 +46,7 @@ struct vm_area_struct;
 #define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs

*/

include/linux/gfp.h struct vm_area_struct; · line 49

Quoted 1 line
include/linux/gfp.h +1 -0
+#define __GFP_MEMALLOC  ((__force gfp_t)0x40000u) /* Use emergency reserves */

This symbol name has nothing to do with its purpose. The entire area of code you are modifying could be described as having something to do with 'memalloc'.

Quoted 6 lines

GFP_EMERGENCY or GFP_USE_RESERVES or somesuch would be a far better symbol name.

I recognize that is matches with GFP_NOMEMALLOC, but that doesn't change the situation anyway. In fact, a cleanup patch to rename GFP_NOMEMALLOC would be nice.

Quoted 8 lines

I'm rather bad at picking names, but here goes:

PF_MEMALLOC -> PF_EMERGALLOC
__GFP_NOMEMALLOC -> __GFP_NOEMERGALLOC
__GFP_MEMALLOC -> __GFP_EMERGALLOC

Is that suitable and shall I prepare patches? Or do we want more ppl to chime in and have a few more rounds?

Pardon my ignorance, but if we're doing cleanup anyway, why not use only one flag instead of two? Why is __GFP_NOMEMALLOC needed when not setting __GFP_MEMALLOC could mean the same? Or else what is the expected behaviour if both flags are set?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw

Re: rename *MEMALLOC flags (was: Re: [RFC][PATCH 3/4] deadlock prevention core)

Quoted 25 lines · Indan Zupancic
Quoted 24 lines · Peter Zijlstra
Quoted 22 lines · Jeff Garzik

include/linux/gfp.h struct vm_area_struct; · line 48

Quoted 8 lines · Peter Zijlstra

Index: linux-2.6/include/linux/gfp.h
===================================================================

include/linux/gfp.h +0 -0
@@ -46,6 +46,7 @@ struct vm_area_struct;
 #define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs

*/

include/linux/gfp.h struct vm_area_struct; · line 49

Quoted 1 line
include/linux/gfp.h +1 -0
+#define __GFP_MEMALLOC  ((__force gfp_t)0x40000u) /* Use emergency reserves */

This symbol name has nothing to do with its purpose. The entire area of code you are modifying could be described as having something to do with 'memalloc'.

GFP_EMERGENCY or GFP_USE_RESERVES or somesuch would be a far better symbol name.

I recognize that is matches with GFP_NOMEMALLOC, but that doesn't change the situation anyway. In fact, a cleanup patch to rename GFP_NOMEMALLOC would be nice.

Quoted 5 lines
Quoted 5 lines

I'm rather bad at picking names, but here goes:

PF_MEMALLOC -> PF_EMERGALLOC
__GFP_NOMEMALLOC -> __GFP_NOEMERGALLOC
__GFP_MEMALLOC -> __GFP_EMERGALLOC

    SOCK_MEMALLOC    -> SOCK_EMERGALLOC
Quoted 7 lines
Quoted 3 lines

Is that suitable and shall I prepare patches? Or do we want more ppl to chime in and have a few more rounds?

Pardon my ignorance, but if we're doing cleanup anyway, why not use only one flag instead of two? Why is __GFP_NOMEMALLOC needed when not setting __GFP_MEMALLOC could mean the same? Or else what is the expected behaviour if both flags are set?

__GFP_NOMEMALLOC is most authorative; its use is (afaik) to negate PF_MEMALLOC.

I agree that having both seems odd, but I haven't spend any significant time on trying to find a 'nicer' solution.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw

Re: rename *MEMALLOC flags

In reply to Peter Zijlstra
Quoted 19 lines · Peter Zijlstra

Jeff Garzik in his infinite wisdom spake thusly:

Quoted 14 lines

include/linux/gfp.h struct vm_area_struct; · line 49

Quoted 9 lines · Peter Zijlstra

Index: linux-2.6/include/linux/gfp.h
===================================================================

include/linux/gfp.h +1 -0
@@ -46,6 +46,7 @@ struct vm_area_struct;
 #define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
 #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
+#define __GFP_MEMALLOC  ((__force gfp_t)0x40000u) /* Use emergency reserves */

This symbol name has nothing to do with its purpose. The entire area of code you are modifying could be described as having something to do with 'memalloc'.

Quoted 3 lines

GFP_EMERGENCY or GFP_USE_RESERVES or somesuch would be a far better symbol name.

I recognize that is matches with GFP_NOMEMALLOC, but that doesn't change the situation anyway. In fact, a cleanup patch to rename GFP_NOMEMALLOC would be nice.

Quoted 8 lines

I'm rather bad at picking names, but here goes:

PF_MEMALLOC -> PF_EMERGALLOC
__GFP_NOMEMALLOC -> __GFP_NOEMERGALLOC
__GFP_MEMALLOC -> __GFP_EMERGALLOC

Is that suitable and shall I prepare patches? Or do we want more ppl to chime in and have a few more rounds?

MEMALLOC is the name Linus chose to name exactly the reserve from which we are allocating. Perhaps that was just Linus being denser than jgarzik and not realizing that he should have called it EMERGALLOC right from the start.

BUT since Linus did call it MEMALLOC, we should too. Or just email Linus and tell him how much better EMERGALLOC rolls off the tongue, and could we please change all occurances of MEMALLOC to EMERGALLOC. Then don't read your email for a week ;-)

Inventing a new name for an existing thing is very poor taste on grounds of grepability alone.

Regards,

Daniel

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw

Re: rename *MEMALLOC flags

Quoted 2 lines · Daniel

Inventing a new name for an existing thing is very poor taste on grounds of grepability alone.

I wouldn't say 'very poor taste' -- just something that should be done infrequently, with good reason, and with reasonable concensus, especially from the key maintainers in the affected area.

Good names are good taste, in my book. But stable naming is good too.

I wonder what Nick thinks of this? Looks like he added __GFP_NOMEMALLOC a year ago, following the naming style of PF_MEMALLOC.

I added him to the cc list.

Signature · 9 lines
                  I won't rest till it's the best ...
                  Programmer, Linux Scalability
                  Paul Jackson <[email protected]> 1.925.600.0401

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#10 lore raw

Re: rename *MEMALLOC flags

Quoted 10 lines · Paul Jackson
Quoted 2 lines · Daniel

Inventing a new name for an existing thing is very poor taste on grounds of grepability alone.

I wouldn't say 'very poor taste' -- just something that should be done infrequently, with good reason, and with reasonable concensus, especially from the key maintainers in the affected area.

Quoted 7 lines

Good names are good taste, in my book. But stable naming is good too.

I wonder what Nick thinks of this? Looks like he added __GFP_NOMEMALLOC a year ago, following the naming style of PF_MEMALLOC.

I added him to the cc list.

__GFP_NOMEMALLOC was added to prevent mempool backed allocations from accessing the emergency reserve. Because that would just shift deadlocks from mempool "safe" sites to those which have not been converted.

PF_MEMALLOC is a good name: PF_MEMALLOC says that the task is currently allocating memory. It does not say anything about the actual allocator implementation details to handle this (1. don't recurse into reclaim; 2. allow access to reserves), but that is a good thing.

__GFP_NOMEMALLOC and __GFP_MEMALLOC are poorly named (I take the blame). It isn't that the task is suddenly no longer allocating in the context of an allocation, it is just that you want to allow or deny access to the reserve.

__GFP_NOMEMALLOC should be something like __GFP_EMERG_NEVER and __GFP_MEMALLOC should be _ALWAYS. Or something like that.

NOMEMALLOC is specific enough that I don't mind a rename at this stage. Renaming PF_MEMALLOC would be wrong, however.

Signature · 8 lines
SUSE Labs, Novell Inc.
Send instant messages to your online friends http://au.messenger.yahoo.com 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#11 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

In reply to Peter Zijlstra

net/core/skbuff.c nodata: · line 242

Quoted 12 lines · Peter Zijlstra
net/core/skbuff.c +12 -0
+struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone)
+{
+	struct sk_buff *skb;
+
+	skb = ___alloc_skb(size, gfp_mask & ~__GFP_MEMALLOC, fclone);
+
+	if (!skb && (gfp_mask & __GFP_MEMALLOC) && memalloc_skbs_available())
+		skb = ___alloc_skb(size, gfp_mask, fclone);
+
+	return skb;
+}
+

I'd drop the memalloc_skbs_available() check, as that's already done by ___alloc_skb.

net/core/sock.c __u32 sysctl_rmem_default = SK_RMEM_MAX; · line 202

Quoted 3 lines
net/core/sock.c +3 -0
+static DEFINE_SPINLOCK(memalloc_lock);
+static int memalloc_socks;
+static unsigned long memalloc_reserve;

Why is this a long? adjust_memalloc_reserve() takes an int. Is it needed at all, considering var_free_kbytes already exists?

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#12 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

Quoted 16 lines · Indan Zupancic

net/core/skbuff.c nodata: · line 242

Quoted 12 lines · Peter Zijlstra
net/core/skbuff.c +12 -0
+struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone)
+{
+	struct sk_buff *skb;
+
+	skb = ___alloc_skb(size, gfp_mask & ~__GFP_MEMALLOC, fclone);
+
+	if (!skb && (gfp_mask & __GFP_MEMALLOC) && memalloc_skbs_available())
+		skb = ___alloc_skb(size, gfp_mask, fclone);
+
+	return skb;
+}
+

I'd drop the memalloc_skbs_available() check, as that's already done by ___alloc_skb.

Right, thanks. Hmm, its the last occurence of that function, even better.

Quoted 5 lines

net/core/sock.c __u32 sysctl_rmem_default = SK_RMEM_MAX; · line 202

Quoted 3 lines
net/core/sock.c +3 -0
+static DEFINE_SPINLOCK(memalloc_lock);
+static int memalloc_socks;
+static unsigned long memalloc_reserve;

Why is this a long? adjust_memalloc_reserve() takes an int.

Euhm, right :-) long comes naturaly when I think about quantities op pages. The adjust_memalloc_reserve() argument is an increment, a delta; perhaps I should change that to long.

Quoted 1 line

Is it needed at all, considering var_free_kbytes already exists?

Having them separate would allow ajust_memalloc_reserve() to be used by other callers too (would need some extra locking).

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

Quoted 3 lines · Peter Zijlstra

Euhm, right :-) long comes naturaly when I think about quantities op pages. The adjust_memalloc_reserve() argument is an increment, a delta; perhaps I should change that to long.

Maybe, but having 16 TB of reserved memory seems plenty for a while.

Quoted 2 lines

Having them separate would allow ajust_memalloc_reserve() to be used by other callers too (would need some extra locking).

True, but currently memalloc_reserve isn't used in a sensible way, or I'm missing something.

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#14 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

Quoted 6 lines · Indan Zupancic
Quoted 3 lines · Peter Zijlstra

Euhm, right :-) long comes naturaly when I think about quantities op pages. The adjust_memalloc_reserve() argument is an increment, a delta; perhaps I should change that to long.

Maybe, but having 16 TB of reserved memory seems plenty for a while.

Oh, for sure, but since it doesn't really matter all that much, I'd rather go for proper.

Quoted 5 lines
Quoted 2 lines

Having them separate would allow ajust_memalloc_reserve() to be used by other callers too (would need some extra locking).

True, but currently memalloc_reserve isn't used in a sensible way, or I'm missing something.

Well, I'm somewhat reluctant to stick network related code into mm/, it seems well separated now.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#15 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Indan Zupancic

True, but currently memalloc_reserve isn't used in a sensible way, or I'm missing something.

Well, I'm somewhat reluctant to stick network related code into mm/, it seems well separated now.

What I had in mind was something like:

+static DEFINE_SPINLOCK(memalloc_lock);
+static int memalloc_socks;
+
+atomic_t memalloc_skbs_used;
+EXPORT_SYMBOL_GPL(memalloc_skbs_used);
+
+int sk_adjust_memalloc(int nr_socks)
+{
+ unsigned long flags;
+ unsigned int reserve;
+ int err;
+
+ spin_lock_irqsave(&memalloc_lock, flags);
+
+ memalloc_socks += nr_socks;
+ BUG_ON(memalloc_socks < 0);
+
+ reserve = nr_socks * (2 * MAX_PHYS_SEGMENTS + /* outbound */
+ 5 * MAX_CONCURRENT_SKBS); /* inbound */
+
+ err = adjust_memalloc_reserve(reserve);
+ spin_unlock_irqrestore(&memalloc_lock, flags);
+ if (err) {
+ printk(KERN_WARNING
+ "Unable to change RX reserve to: %lu, error: %d\n",
+ reserve, err);
+ }
+ return err;
+}

The original code missed the brackets, so 5 * MAX_CONCURRENT_SKBS wasn't done per socket. But the comment said it was per socket, so I added in this version.

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#16 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

Quoted 40 lines · Indan Zupancic
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Indan Zupancic

True, but currently memalloc_reserve isn't used in a sensible way, or I'm missing something.

Well, I'm somewhat reluctant to stick network related code into mm/, it seems well separated now.

What I had in mind was something like:

net/core/sock.c +29 -0
+static DEFINE_SPINLOCK(memalloc_lock);
+static int memalloc_socks;
+
+atomic_t memalloc_skbs_used;
+EXPORT_SYMBOL_GPL(memalloc_skbs_used);
+
+int sk_adjust_memalloc(int nr_socks)
+{
+	unsigned long flags;
+	unsigned int reserve;
+	int err;
+
+	spin_lock_irqsave(&memalloc_lock, flags);
+
+	memalloc_socks += nr_socks;
+	BUG_ON(memalloc_socks < 0);
+
+	reserve = nr_socks * (2 * MAX_PHYS_SEGMENTS + 	/* outbound */
+			      5 * MAX_CONCURRENT_SKBS);	/* inbound */
+
+	err = adjust_memalloc_reserve(reserve);
+	spin_unlock_irqrestore(&memalloc_lock, flags);
+	if (err) {
+		printk(KERN_WARNING
+			"Unable to change RX reserve to: %lu, error: %d\n",
+			reserve, err);
+	}
+	return err;
+}
Quoted 2 lines

The original code missed the brackets, so 5 * MAX_CONCURRENT_SKBS wasn't done per socket. But the comment said it was per socket, so I added in this version.

Ah right, I did that in v3, with a similar comment, but I realised that the inbound reserve need not be per socket, and that the comment was ambiguous enough to allow this reading.

Why not per socket, its used to place an upper bound, its not calculating one, its setting one.

Like you can see in memalloc_skbs_inc(), it limits to MAX_CONCURRENT_SKBS.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#17 lore raw

Re: [RFC][PATCH 3/4] deadlock prevention core

Quoted 3 lines · Peter Zijlstra

Ah right, I did that in v3, with a similar comment, but I realised that the inbound reserve need not be per socket, and that the comment was ambiguous enough to allow this reading.

True, but better to change the comment than to confuse people. Lots of it is outdated because reservations aren't per device anymore.

Changes to your version:
- Got rid of memalloc_socks.
- Don't include inetdevice.h (it isn't needed anymore, right?)
- Updated comment.

(I'm editing the diff, so this won't apply)

net/core/sock.c +52 -0
Index: linux-2.6/net/core/sock.c
===================================================================
@@ -111,6 +111,8 @@
 #include <linux/poll.h>
 #include <linux/tcp.h>
 #include <linux/init.h>
+#include <linux/blkdev.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -195,6 +197,78 @@ __u32 sysctl_rmem_default = SK_RMEM_MAX;
 /* Maximal space eaten by iovec or ancilliary data plus some space */
 int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512);
 
+static DEFINE_SPINLOCK(memalloc_lock);
+static int memalloc_socks;
+static unsigned long memalloc_reserve;
+
+atomic_t memalloc_skbs_used;
+EXPORT_SYMBOL_GPL(memalloc_skbs_used);
+
+/**
+ *        sk_adjust_memalloc - adjust the global memalloc reserve
+ *        @nr_socks: number of new %SOCK_MEMALLOC sockets
+ *
+ *        This function adjusts the memalloc reserve based on system demand.
+ *        For each %SOCK_MEMALLOC socket 2 * %MAX_PHYS_SEGMENTS pages are
+ *        reserved for outbound traffic (assumption: each %SOCK_MEMALLOC
+ *        socket will have a %request_queue associated).
+ *
+ *        Pages for inbound traffic are already reserved.
+ *
+ *        2 * %MAX_PHYS_SEGMENTS - the request queue can hold up to 150%,
+ *                the remaining 50% goes to being sure we can write packets
+ *                for the outgoing pages.
+ */
+static DEFINE_SPINLOCK(memalloc_lock);
+static int memalloc_socks;
+
+atomic_t memalloc_skbs_used;
+EXPORT_SYMBOL_GPL(memalloc_skbs_used);
+
+int sk_adjust_memalloc(int nr_socks)
+{
+	unsigned long flags;
+	unsigned int reserve;
+	int err;
+
+	spin_lock_irqsave(&memalloc_lock, flags);
+
+	memalloc_socks += nr_socks;
+	BUG_ON(memalloc_socks < 0);
+
+	reserve = nr_socks * 2 * MAX_PHYS_SEGMENTS;	/* outbound */
+
+	err = adjust_memalloc_reserve(reserve);
+	spin_unlock_irqrestore(&memalloc_lock, flags);
+	if (err) {
+		printk(KERN_WARNING
+			"Unable to adjust RX reserve by %lu, error: %d\n",
+			reserve, err);
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(sk_adjust_memalloc);
 

What's missing now is an adjust_memalloc_reserve(5 * MAX_CONCURRENT_SKBS) call in some init code.

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#18 lore raw

RFC PATCH 4/4 deadlock prevention for NBD

In reply to Peter Zijlstra

Use sk_set_memalloc() on the nbd socket.

Limit each request to 1 page, so that the request throttling also limits the number of in-flight pages and force the IO scheduler to NOOP as anything else doesn't make sense anyway.

---
 block/elevator.c       |    5 +++++
 block/ll_rw_blk.c      |   12 ++++++++++--
 drivers/block/nbd.c    |   12 +++++++++++-
 include/linux/blkdev.h |    9 +++++++++
 4 files changed, 35 insertions(+), 3 deletions(-)
block/ll_rw_blk.c +10 -2
Index: linux-2.6/block/ll_rw_blk.c
===================================================================
@@ -1899,6 +1899,14 @@ EXPORT_SYMBOL(blk_init_queue);
 request_queue_t *
 blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
 {
+	return blk_init_queue_node_elv(rfn, lock, node_id, NULL);
+}
+EXPORT_SYMBOL(blk_init_queue_node);
+
+request_queue_t *
+blk_init_queue_node_elv(request_fn_proc *rfn, spinlock_t *lock, int node_id,
+		char *elv_name)
+{
 	request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
 
 	if (!q)
@@ -1939,7 +1947,7 @@ blk_init_queue_node(request_fn_proc *rfn
 	/*
 	 * all done
 	 */
-	if (!elevator_init(q, NULL)) {
+	if (!elevator_init(q, elv_name)) {
 		blk_queue_congestion_threshold(q);
 		return q;
 	}
@@ -1947,7 +1955,7 @@ blk_init_queue_node(request_fn_proc *rfn
 	blk_put_queue(q);
 	return NULL;
 }
-EXPORT_SYMBOL(blk_init_queue_node);
+EXPORT_SYMBOL(blk_init_queue_node_elv);
 
 int blk_get_queue(request_queue_t *q)
 {
drivers/block/nbd.c +11 -1
Index: linux-2.6/drivers/block/nbd.c
===================================================================
@@ -361,8 +361,13 @@ static void nbd_do_it(struct nbd_device 
 
 	BUG_ON(lo->magic != LO_MAGIC);
 
+	if (sk_set_memalloc(lo->sock->sk))
+		printk(KERN_WARNING
+				"failed to set SO_MEMALLOC on NBD socket\n");
+
 	while ((req = nbd_read_stat(lo)) != NULL)
 		nbd_end_request(req);
+
 	return;
 }
 
@@ -628,11 +633,16 @@ static int __init nbd_init(void)
 		 * every gendisk to have its very own request_queue struct.
 		 * These structs are big so we dynamically allocate them.
 		 */
-		disk->queue = blk_init_queue(do_nbd_request, &nbd_lock);
+		disk->queue = blk_init_queue_node_elv(do_nbd_request,
+				&nbd_lock, -1, "noop");
 		if (!disk->queue) {
 			put_disk(disk);
 			goto out;
 		}
+		blk_queue_pin_elevator(disk->queue);
+		blk_queue_max_segment_size(disk->queue, PAGE_SIZE);
+		blk_queue_max_hw_segments(disk->queue, 1);
+		blk_queue_max_phys_segments(disk->queue, 1);
 	}
 
 	if (register_blkdev(NBD_MAJOR, "nbd")) {
include/linux/blkdev.h +9 -0
Index: linux-2.6/include/linux/blkdev.h
===================================================================
@@ -444,6 +444,12 @@ struct request_queue
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
 #define QUEUE_FLAG_ELVSWITCH	8	/* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_ELVPINNED	9	/* pin the current elevator */
+
+static inline void blk_queue_pin_elevator(struct request_queue *q)
+{
+	set_bit(QUEUE_FLAG_ELVPINNED, &q->queue_flags);
+}
 
 enum {
 	/*
@@ -696,6 +702,9 @@ static inline void elv_dispatch_add_tail
 /*
  * Access functions for manipulating queue properties
  */
+extern request_queue_t *blk_init_queue_node_elv(request_fn_proc *rfn,
+					spinlock_t *lock, int node_id,
+					char *elv_name);
 extern request_queue_t *blk_init_queue_node(request_fn_proc *rfn,
 					spinlock_t *lock, int node_id);
 extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *);
block/elevator.c +5 -0
Index: linux-2.6/block/elevator.c
===================================================================
@@ -861,6 +861,11 @@ ssize_t elv_iosched_store(request_queue_
 	size_t len;
 	struct elevator_type *e;
 
+	if (test_bit(QUEUE_FLAG_ELVPINNED, &q->queue_flags)) {
+		printk(KERN_ERR "elevator: cannot switch elevator, pinned\n");
+		return count;
+	}
+
 	elevator_name[sizeof(elevator_name) - 1] = '\0';
 	strncpy(elevator_name, name, sizeof(elevator_name) - 1);
 	len = strlen(elevator_name);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#19 lore raw

Re: [RFC][PATCH 4/4] deadlock prevention for NBD

Hi!

Quoted 3 lines

Limit each request to 1 page, so that the request throttling also limits the number of in-flight pages and force the IO scheduler to NOOP as anything else doesn't make sense anyway.

I'd like to understand why it breaks with other schedulers before merging this. Maybe the failure in NOOP is just harder to trigger?

Pavel

Signature · 7 lines
Thanks for all the (sleeping) penguins.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#20 lore raw
In reply to Peter Zijlstra
Quoted 12 lines · Peter Zijlstra

Hi,

here the latest effort, it includes a whole new trivial allocator with a horrid name and an almost full rewrite of the deadlock prevention core. This version does not do anything per device and hence does not depend on the new netdev_alloc_skb() API.

The reason to add a second allocator to the receive side is twofold:
1) it allows easy detection of the memory pressure / OOM situation;
2) it allows the receive path to be unbounded and go at full speed when resources permit.

Quoted 4 lines

The choice of using the global memalloc reserve as a mempool makes that the new allocator has to release pages as soon as possible; if we were to hoard pages in the allocator the memalloc reserve would not get replenished readily.

Version 2 had about 250 new lines of code, while v3 has close to 600, when including the SROG code. And that while things should have become simpler. So why use SROG instead of the old alloc_pages() based code? And why couldn't you use a slightly modified SLOB instead of writing a new allocator? It looks like overkill to me.

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#21 lore raw
Quoted 18 lines · Indan Zupancic
Quoted 12 lines · Peter Zijlstra

Hi,

here the latest effort, it includes a whole new trivial allocator with a horrid name and an almost full rewrite of the deadlock prevention core. This version does not do anything per device and hence does not depend on the new netdev_alloc_skb() API.

The reason to add a second allocator to the receive side is twofold:
1) it allows easy detection of the memory pressure / OOM situation;
2) it allows the receive path to be unbounded and go at full speed when resources permit.

Quoted 4 lines

The choice of using the global memalloc reserve as a mempool makes that the new allocator has to release pages as soon as possible; if we were to hoard pages in the allocator the memalloc reserve would not get replenished readily.

Quoted 5 lines

Version 2 had about 250 new lines of code, while v3 has close to 600, when including the SROG code. And that while things should have become simpler. So why use SROG instead of the old alloc_pages() based code? And why couldn't you use a slightly modified SLOB instead of writing a new allocator? It looks like overkill to me.

Of the 611 new lines about 150 are new comments.

Simpler yes, but also more complete; the old patches had serious issues with the alternative allocation scheme.

As for why SROG, because trying to stick all the semantics needed for all skb operations into the old approach was nasty, I had it almost complete but it was horror (and more code than the SROG approach).

Why not SLOB, well, I mistakenly assumed that it was a simpler SLAB allocator, my bad. However after having had a quick peek at it; whereas it seems similar in intent it does not provide the things I look for. Making it so and keep the old semantics and make it compile along side of SLAB will take quite some effort.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#22 lore raw
Quoted 2 lines · Peter Zijlstra

Simpler yes, but also more complete; the old patches had serious issues with the alternative allocation scheme.

It sure is more complete, and looks nicer, but the price is IMHO too high. I'm curious what those serious issues are, and if they can't be fixed.

Quoted 3 lines

As for why SROG, because trying to stick all the semantics needed for all skb operations into the old approach was nasty, I had it almost complete but it was horror (and more code than the SROG approach).

What was missing or wrong in the old approach? Can't you use the new approach, but use alloc_pages() instead of SROG?

Sorry if I bug you so, but I'm also trying to increase my knowledge here. ;-)

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#23 lore raw
Quoted 7 lines · Indan Zupancic
Quoted 2 lines · Peter Zijlstra

Simpler yes, but also more complete; the old patches had serious issues with the alternative allocation scheme.

It sure is more complete, and looks nicer, but the price is IMHO too high. I'm curious what those serious issues are, and if they can't be fixed.

Quoted 8 lines
Quoted 3 lines

As for why SROG, because trying to stick all the semantics needed for all skb operations into the old approach was nasty, I had it almost complete but it was horror (and more code than the SROG approach).

What was missing or wrong in the old approach? Can't you use the new approach, but use alloc_pages() instead of SROG?

Sorry if I bug you so, but I'm also trying to increase my knowledge here. ;-)

I'm almost sorry I threw that code out, you'd understand instantly..

Lemme see what I can do to explain; what I need/want is:
- single allocation group per packet - that is, when I free a packet
and all its associated object I get my memory back.
- not waste too much space managing the various objects

skb operations want to allocate various sk_buffs for the same data clones. Also, it wants to be able to break the COW or realloc the data.

The trivial approach would be one page (or higher alloc page) per object, and that will work quite well, except that it'll waste a _lot_ of memory.

So I tried manual packing (parts of that you have seen in previous attempts). This gets hard when you want to do unlimited clones and COW breaks. To do either you need to go link several pages.

So needing a list of pages and wanting packing gave me SROG. The biggest wart is having to deal with higher order pages. Explicitly coding in knowledge of the object you're packing just makes the code bigger - such is the power of abstraction.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#24 lore raw
Quoted 2 lines · Peter Zijlstra

- single allocation group per packet - that is, when I free a packet
and all its associated object I get my memory back.

This is easy.

Quoted 1 line

- not waste too much space managing the various objects

This too, when ignoring clones and COW.

Quoted 2 lines

skb operations want to allocate various sk_buffs for the same data clones. Also, it wants to be able to break the COW or realloc the data.

So this seems to be what adds all the complexity.

Quoted 3 lines

So I tried manual packing (parts of that you have seen in previous attempts). This gets hard when you want to do unlimited clones and COW breaks. To do either you need to go link several pages.

It gets messy quite quickly, yes.

Quoted 4 lines

So needing a list of pages and wanting packing gave me SROG. The biggest wart is having to deal with higher order pages. Explicitly coding in knowledge of the object you're packing just makes the code bigger - such is the power of abstraction.

I assume you meant "Not explicitly coding in", or else I'm tempted to disagree. Abstraction that has only one user which uses it in one way only adds bloat. But looking at the code a bit more I'm afraid you're right.

Greetings,

Indan

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#25 lore raw
In reply to Peter Zijlstra
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Indan Zupancic

What was missing or wrong in the old approach? Can't you use the new approach, but use alloc_pages() instead of SROG?

Sorry if I bug you so, but I'm also trying to increase my knowledge here. ;-)

I'm almost sorry I threw that code out...

Good instinct :-)

Quoted 3 lines

Lemme see what I can do to explain; what I need/want is:
- single allocation group per packet - that is, when I free a packet
and all its associated object I get my memory back.

First, try to recast all your objects as pages, as Evgeniy Polyakov suggested. Then if there is some place where that just doesn't work (please point it out) put a mempool there and tweak the high level reservation setup accordingly.

Quoted 1 line

- not waste too much space managing the various objects

If we waste a little space only where the network would have otherwise dropped a packet, that is still a big win. We just need to be sure the normal path does not become more wasteful.

Quoted 6 lines

skb operations want to allocate various sk_buffs for the same data clones. Also, it wants to be able to break the COW or realloc the data.

The trivial approach would be one page (or higher alloc page) per object, and that will work quite well, except that it'll waste a _lot_ of memory.

High order allocations are just way too undependable without active defragmentation, which isn't even on the horizon at the moment. We just need to treat any network hardware that can't scatter/gather into single pages as too broken to use for network block io.

As for sk_buff cow break, we need to look at which network paths do it (netfilter obviously, probably others) and decide whether we just want to declare that the feature breaks network block IO, or fix the feature so it plays well with reserve accounting.

Quoted 3 lines

So I tried manual packing (parts of that you have seen in previous attempts). This gets hard when you want to do unlimited clones and COW breaks. To do either you need to go link several pages.

You need to avoid the temptation to fix the entire world on the first attempt. Sure, there will be people who call for gobs of overengineering right from the start, but simple has always worked better for Linux than lathering on layers of complexity just to support some feature that may arguably be broken by design. For example, swapping through a firewall.

Changing from per-interface to a global block IO reserve was a great simplification, we need more of those.

Looking forward to -v5 ;-)

Regards,

Daniel

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#26 lore raw
Quoted 4 lines · Daniel Phillips

High order allocations are just way too undependable without active defragmentation, which isn't even on the horizon at the moment. We just need to treat any network hardware that can't scatter/gather into single pages as too broken to use for network block io.

A bit of network tree allocator free advertisement - per-CPU self defragmentation works reliably in that allocator, one could even find a graphs of memory usage for NTA and SLAB-like allocator.

Quoted 4 lines

As for sk_buff cow break, we need to look at which network paths do it (netfilter obviously, probably others) and decide whether we just want to declare that the feature breaks network block IO, or fix the feature so it plays well with reserve accounting.

I would suggest to consider skb cow (cloning) as a must.

Quoted 3 lines

Regards,

Daniel

Signature · 7 lines
	Evgeniy Polyakov

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#27 lore raw
Quoted 8 lines · Evgeniy Polyakov
Quoted 4 lines · Daniel Phillips

As for sk_buff cow break, we need to look at which network paths do it (netfilter obviously, probably others) and decide whether we just want to declare that the feature breaks network block IO, or fix the feature so it plays well with reserve accounting.

I would suggest to consider skb cow (cloning) as a must.

That should not be any problem, since skb's (including cowed ones) are short lived anyway. Allocating a little bit more memory is fine when we have a guarantee that the memory will be freed again shortly.

Signature · 7 lines
What is important?  What you want to be true, or what is true?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#28 lore raw
Quoted 5 lines · Rik van Riel

That should not be any problem, since skb's (including cowed ones) are short lived anyway. Allocating a little bit more memory is fine when we have a guarantee that the memory will be freed again shortly.

I'm not sure about the context the comment applies to, but skb's are not necessarily short-lived. For example, they could be queued for a few seconds for ARP/NDISC and even longer for IPsec SA resolution.

Cheers,

Signature · 10 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#29 lore raw
Quoted 9 lines · Herbert Xu
Quoted 4 lines · Rik van Riel

That should not be any problem, since skb's (including cowed ones) are short lived anyway. Allocating a little bit more memory is fine when we have a guarantee that the memory will be freed again shortly.

I'm not sure about the context the comment applies to, but skb's are not necessarily short-lived. For example, they could be queued for a few seconds for ARP/NDISC and even longer for IPsec SA resolution.

That's still below the threshold where it should cause problems with the VM going OOM. Especially if there aren't too many of these packets.

Signature · 7 lines
All Rights Reversed

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>