Changelog since V9
o Rebase to 3.4-rc5
o Clarify comment on why PF_MEMALLOC is cleared in softirq handling (akpm)
o Only set page->pfmemalloc if ALLOC_NO_WATERMARKS was required (rientjes)
Changelog since V8
o Rebase to 3.4-rc2
o Use page flag instead of slab fields to keep structures the same size
o Properly detect allocations from softirq context that use PF_MEMALLOC
o Ensure kswapd does not sleep while processes are throttled
o Do not accidentally throttle !_GFP_FS processes indefinitely
Changelog since V7
o Rebase to 3.3-rc2
o Take greater care propagating page->pfmemalloc to skb
o Propagate pfmemalloc from netdev_alloc_page to skb where possible
o Release RCU lock properly on preempt kernel
Changelog since V6
o Rebase to 3.1-rc8
o Use wake_up instead of wake_up_interruptible()
o Do not throttle kernel threads
o Avoid a potential race between kswapd going to sleep and processes being
throttled
Changelog since V5
o Rebase to 3.1-rc5
Changelog since V4
o Update comment clarifying what protocols can be used (Michal)
o Rebase to 3.0-rc3
Changelog since V3
o Propogate pfmemalloc from packet fragment pages to skb (Neil)
o Rebase to 3.0-rc2
Changelog since V2
o Document that __GFP_NOMEMALLOC overrides __GFP_MEMALLOC (Neil)
o Use wait_event_interruptible (Neil)
o Use !! when casting to bool to avoid any possibilitity of type
truncation (Neil)
o Nicer logic when using skb_pfmemalloc_protocol (Neil)
Changelog since V1
o Rebase on top of mmotm
o Use atomic_t for memalloc_socks (David Miller)
o Remove use of sk_memalloc_socks in vmscan (Neil Brown)
o Check throttle within prepare_to_wait (Neil Brown)
o Add statistics on throttling instead of printk
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the
Network Block Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD
at places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP
The nbd-client also documents the use of NBD as swap. Despite this, the
fact is that a machine using NBD for swap can deadlock within minutes if
swap is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Ziljstra developed a series of
patches that supported swap over an NFS that at least one distribution
is carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 serialises access to min_free_kbytes. It's not strictly needed
by this series but as the series cares about watermarks in
general, it's a harmless fix. It could be merged independently
and may be if CMA is merged in advance.
Patch 2 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patch 7 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patches 8-14 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __netdev_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 14 is a micro-optimisation to avoid a function call in the
common case.
Patch 15 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 16 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 17 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf
on loopback for UDP and TCP, hackbench (pipes and sockets), iozone
and sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant
performance variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes and
runs to completion with them applied. With SLAB, the story is different
as an unpatched kernel run to completion. However, the patched kernel
completed the test 40% faster.
3.4.0-rc2 3.4.0-rc2
vanilla-slab swapnbd
Sys Time Running Test (seconds) 87.90 73.45
User+Sys Time Running Test (seconds) 91.93 76.91
Total Elapsed Time (seconds) 4174.37 2953.96
drivers/block/nbd.c | 6 +-
drivers/net/ethernet/chelsio/cxgb4/sge.c | 2 +-
drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 2 +-
drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +-
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 3 +-
drivers/net/usb/cdc-phonet.c | 2 +-
drivers/usb/gadget/f_phonet.c | 2 +-
include/linux/gfp.h | 13 +-
include/linux/mm_types.h | 9 +
include/linux/mmzone.h | 1 +
include/linux/page-flags.h | 28 +++
include/linux/sched.h | 7 +
include/linux/skbuff.h | 83 +++++++-
include/linux/vm_event_item.h | 1 +
include/net/sock.h | 19 ++
include/trace/events/gfpflags.h | 1 +
kernel/softirq.c | 9 +
mm/page_alloc.c | 69 +++++--
mm/slab.c | 212 +++++++++++++++++++--
mm/slub.c | 28 ++-
mm/vmscan.c | 131 ++++++++++++-
mm/vmstat.c | 1 +
net/core/dev.c | 52 ++++-
net/core/filter.c | 8 +
net/core/skbuff.c | 94 +++++++--
net/core/sock.c | 42 ++++
net/ipv4/tcp.c | 3 +-
net/ipv4/tcp_output.c | 16 +-
net/ipv6/tcp_ipv6.c | 8 +-
30 files changed, 765 insertions(+), 91 deletions(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
There is a race between the min_free_kbytes sysctl, memory hotplug
and transparent hugepage support enablement. Memory hotplug uses a
zonelists_mutex to avoid a race when building zonelists. Reuse it to
serialise watermark updates.
[a.p.zijlstra@chello.nl: Older patch fixed the race with spinlock]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Reviewed-by: Rik van Riel <redacted>
Acked-by: David Rientjes <rientjes@google.com>
---
mm/page_alloc.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
__alloc_pages_slowpath() is called when the number of free pages is below
the low watermark. If the caller is entitled to use ALLOC_NO_WATERMARKS
then the page will be marked page->pfmemalloc. This protects more pages
than are strictly necessary as we only need to protect pages allocated
below the min watermark (the pfmemalloc reserves).
This patch only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was
required to allocate the page.
[rientjes@google.com: David noticed the problem during review]
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
mm/page_alloc.c | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
The reserve is proportionally distributed over all !highmem zones
in the system. So we need to allow an emergency allocation access to
all zones. In order to do that we need to break out of any mempolicy
boundaries we might have.
In my opinion that does not break mempolicies as those are user
oriented and not system oriented. That is, system allocations are
not guaranteed to be within mempolicy boundaries. For instance IRQs
do not even have a mempolicy.
So breaking out of mempolicy boundaries for 'rare' emergency
allocations, which are always system allocations (as opposed to user)
is ok.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
mm/page_alloc.c | 7 +++++++
1 file changed, 7 insertions(+)
@@ -2293,6 +2293,13 @@ rebalance:/* Allocate without watermarks if the context allows */if(alloc_flags&ALLOC_NO_WATERMARKS){+/*+*IgnoremempoliciesifALLOC_NO_WATERMARKSonthegrounds+*theallocationishighpriorityandthesetypeof+*allocationsaresystemratherthanuserorientated+*/+zonelist=node_zonelist(numa_node_id(),gfp_mask);+page=__alloc_pages_high_priority(gfp_mask,order,zonelist,high_zoneidx,nodemask,preferred_zone,migratetype);
Change the skb allocation API to indicate RX usage and use this to fall
back to the PFMEMALLOC reserve when needed. SKBs allocated from the
reserve are tagged in skb->pfmemalloc. If an SKB is allocated from
the reserve and the socket is later found to be unrelated to page
reclaim, the packet is dropped so that the memory remains available
for page reclaim. Network protocols are expected to recover from this
packet loss.
[a.p.zijlstra@chello.nl: Ideas taken from various patches]
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/gfp.h | 3 ++
include/linux/skbuff.h | 17 +++++++--
include/net/sock.h | 6 ++++
mm/internal.h | 3 --
net/core/filter.c | 8 +++++
net/core/skbuff.c | 94 ++++++++++++++++++++++++++++++++++++++++--------
net/core/sock.c | 4 +++
7 files changed, 114 insertions(+), 21 deletions(-)
@@ -385,6 +385,9 @@ void drain_local_pages(void *dummy);*/externgfp_tgfp_allowed_mask;+/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */+boolgfp_pfmemalloc_allowed(gfp_tgfp_mask);+externvoidpm_restrict_gfp_mask(void);externvoidpm_restore_gfp_mask(void);
@@ -146,6 +146,43 @@ static void skb_under_panic(struct sk_buff *skb, int sz, void *here)BUG();}++/*+*kmalloc_reserveisawrapperaroundkmalloc_node_track_callerthattells+*thecallerifemergencypfmemallocreservesarebeingused.Ifitisand+*thesocketislaterfoundtobeSOCK_MEMALLOCthenPFMEMALLOCreserves+*maybeused.Otherwise,thepacketdatamaybediscardeduntilenough+*memoryisfree+*/+#define kmalloc_reserve(size, gfp, node, pfmemalloc) \+__kmalloc_reserve(size,gfp,node,_RET_IP_,pfmemalloc)+void*__kmalloc_reserve(size_tsize,gfp_tflags,intnode,unsignedlongip,+bool*pfmemalloc)+{+void*obj;+boolret_pfmemalloc=false;++/*+*Tryaregularallocation,whenthatfailsandwe'renotentitled+*tothereserves,fail.+*/+obj=kmalloc_node_track_caller(size,+flags|__GFP_NOMEMALLOC|__GFP_NOWARN,+node);+if(obj||!(gfp_pfmemalloc_allowed(flags)))+gotoout;++/* Try again but now we are using pfmemalloc reserves */+ret_pfmemalloc=true;+obj=kmalloc_node_track_caller(size,flags,node);++out:+if(pfmemalloc)+*pfmemalloc=ret_pfmemalloc;++returnobj;+}+/* Allocate a new skbuff. We do this ourselves so we can fill in a few*'private'fieldsandalsodomemorystatisticstofindallthe*[BEEP]leaks.
@@ -168,14 +207,19 @@ static void skb_under_panic(struct sk_buff *skb, int sz, void *here)*%GFP_ATOMIC.*/structsk_buff*__alloc_skb(unsignedintsize,gfp_tgfp_mask,-intfclone,intnode)+intflags,intnode){structkmem_cache*cache;structskb_shared_info*shinfo;structsk_buff*skb;u8*data;+boolpfmemalloc;++cache=(flags&SKB_ALLOC_FCLONE)+?skbuff_fclone_cache:skbuff_head_cache;-cache=fclone?skbuff_fclone_cache:skbuff_head_cache;+if(sk_memalloc_socks()&&(flags&SKB_ALLOC_RX))+gfp_mask|=__GFP_MEMALLOC;/* Get the HEAD */skb=kmem_cache_alloc_node(cache,gfp_mask&~__GFP_DMA,node);
@@ -190,7 +234,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,*/size=SKB_DATA_ALIGN(size);size+=SKB_DATA_ALIGN(sizeof(structskb_shared_info));-data=kmalloc_node_track_caller(size,gfp_mask,node);+data=kmalloc_reserve(size,gfp_mask,node,&pfmemalloc);if(!data)gotonodata;/* kmalloc(size) might give us more room than requested.
@@ -208,6 +252,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,memset(skb,0,offsetof(structsk_buff,tail));/* Account for allocated memory : skb + skb->head */skb->truesize=SKB_TRUESIZE(size);+skb->pfmemalloc=pfmemalloc;atomic_set(&skb->users,1);skb->head=data;skb->data=data;
@@ -952,8 +1012,10 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,gotoadjust_others;}-data=kmalloc(size+SKB_DATA_ALIGN(sizeof(structskb_shared_info)),-gfp_mask);+if(skb_pfmemalloc(skb))+gfp_mask|=__GFP_MEMALLOC;+data=kmalloc_reserve(size+SKB_DATA_ALIGN(sizeof(structskb_shared_info)),+gfp_mask,NUMA_NO_NODE,NULL);if(!data)gotonodata;size=SKB_WITH_OVERHEAD(ksize(data));
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
The skb->pfmemalloc flag gets set to true iff during the slab
allocation of data in __alloc_skb that the the PFMEMALLOC reserves
were used. If the packet is fragmented, it is possible that pages
will be allocated from the PFMEMALLOC reserve without propagating
this information to the skb. This patch propagates page->pfmemalloc
from pages allocated for fragments to the skb.
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/skbuff.h | 11 +++++++++++
1 file changed, 11 insertions(+)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
The skb->pfmemalloc flag gets set to true iff during the slab
allocation of data in __alloc_skb that the the PFMEMALLOC reserves
were used. If page splitting is used, it is possible that pages will
be allocated from the PFMEMALLOC reserve without propagating this
information to the skb. This patch propagates page->pfmemalloc from
pages allocated for fragments to the skb.
It works by reintroducing and expanding the netdev_alloc_page() API
to take an skb. If the page was allocated from pfmemalloc reserves,
it is automatically copied. If the driver allocates the page before
the skb, it should call propagate_pfmemalloc_skb() after the skb is
allocated to ensure the flag is copied properly.
Failure to do so is not critical. The resulting driver may perform
slower if it is used for swap-over-NBD or swap-over-NFS but it should
not result in failure.
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
drivers/net/ethernet/chelsio/cxgb4/sge.c | 2 +-
drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 2 +-
drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +-
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 3 +-
drivers/net/usb/cdc-phonet.c | 2 +-
drivers/usb/gadget/f_phonet.c | 2 +-
include/linux/skbuff.h | 55 +++++++++++++++++++++
8 files changed, 63 insertions(+), 7 deletions(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
In order to make sure pfmemalloc packets receive all memory
needed to proceed, ensure processing of pfmemalloc SKBs happens
under PF_MEMALLOC. This is limited to a subset of protocols that
are expected to be used for writing to swap. Taps are not allowed to
use PF_MEMALLOC as these are expected to communicate with userspace
processes which could be paged out.
[a.p.zijlstra@chello.nl: Ideas taken from various patches]
[jslaby@suse.cz: Lock imbalance fix]
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/net/sock.h | 5 +++++
net/core/dev.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
net/core/sock.c | 16 ++++++++++++++++
3 files changed, 67 insertions(+), 6 deletions(-)
@@ -3182,14 +3199,27 @@ static int __netif_receive_skb(struct sk_buff *skb)booldeliver_exact=false;intret=NET_RX_DROP;__be16type;+unsignedlongpflags=current->flags;net_timestamp_check(!netdev_tstamp_prequeue,skb);trace_netif_receive_skb(skb);+/*+*PFMEMALLOCskbsarespecial,theyshould+*-bedeliveredtoSOCK_MEMALLOCsocketsonly+*-stayawayfromuserspace+*-haveboundedmemoryusage+*+*UsePF_MEMALLOCasthissavesusfrompropagatingtheallocation+*contextdowntoallallocationsites.+*/+if(skb_pfmemalloc(skb))+current->flags|=PF_MEMALLOC;+/* if we've gotten here through NAPI, check netpoll */if(netpoll_receive_skb(skb))-returnNET_RX_DROP;+gotoout;if(!skb->skb_iif)skb->skb_iif=skb->dev->ifindex;
@@ -3284,6 +3321,7 @@ ncls:if(pt_prev){ret=pt_prev->func(skb,skb->dev,pt_prev,orig_dev);}else{+drop:atomic_long_inc(&skb->dev->rx_dropped);kfree_skb(skb);/* Jamal, now you will not able to escape explaining
@@ -292,6 +292,22 @@ void sk_clear_memalloc(struct sock *sk)}EXPORT_SYMBOL_GPL(sk_clear_memalloc);+int__sk_backlog_rcv(structsock*sk,structsk_buff*skb)+{+intret;+unsignedlongpflags=current->flags;++/* these should have been dropped before queueing */+BUG_ON(!sock_flag(sk,SOCK_MEMALLOC));++current->flags|=PF_MEMALLOC;+ret=sk->sk_backlog_rcv(sk,skb);+tsk_restore_flags(current,pflags,PF_MEMALLOC);++returnret;+}+EXPORT_SYMBOL(__sk_backlog_rcv);+#if defined(CONFIG_CGROUPS)#if !defined(CONFIG_NET_CLS_CGROUP)intnet_cls_subsys_id=-1;
Under significant pressure when writing back to network-backed storage,
direct reclaimers may get throttled. This is expected to be a
short-lived event and the processes get woken up again but processes do
get stalled. This patch counts how many times such stalling occurs. It's
up to the administrator whether to reduce these stalls by increasing
min_free_kbytes.
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/vm_event_item.h | 1 +
mm/vmscan.c | 3 +++
mm/vmstat.c | 1 +
3 files changed, 5 insertions(+)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
If swap is backed by network storage such as NBD, there is a risk
that a large number of reclaimers can hang the system by consuming
all PF_MEMALLOC reserves. To avoid these hangs, the administrator
must tune min_free_kbytes in advance which is a bit fragile.
This patch throttles direct reclaimers if half the PF_MEMALLOC reserves
are in use. If the system is routinely getting throttled the system
administrator can increase min_free_kbytes so degradation is smoother
but the system will keep running.
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/mmzone.h | 1 +
mm/page_alloc.c | 1 +
mm/vmscan.c | 128 +++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 122 insertions(+), 8 deletions(-)
@@ -2431,6 +2431,80 @@ out:return0;}+staticboolpfmemalloc_watermark_ok(pg_data_t*pgdat)+{+structzone*zone;+unsignedlongpfmemalloc_reserve=0;+unsignedlongfree_pages=0;+inti;+boolwmark_ok;++for(i=0;i<=ZONE_NORMAL;i++){+zone=&pgdat->node_zones[i];+pfmemalloc_reserve+=min_wmark_pages(zone);+free_pages+=zone_page_state(zone,NR_FREE_PAGES);+}++wmark_ok=free_pages>pfmemalloc_reserve/2;++/* kswapd must be awake if processes are being throttled */+if(!wmark_ok&&waitqueue_active(&pgdat->kswapd_wait)){+pgdat->classzone_idx=min(pgdat->classzone_idx,+(enumzone_type)ZONE_NORMAL);+wake_up_interruptible(&pgdat->kswapd_wait);+}++returnwmark_ok;+}++/*+*Throttledirectreclaimersifbackingstorageisbackedbythenetwork+*andthePFMEMALLOCreserveforthepreferrednodeisgettingdangerously+*depleted.kswapdwillcontinuetomakeprogressandwaketheprocesses+*whenthelowwatermarkisreached+*/+staticvoidthrottle_direct_reclaim(gfp_tgfp_mask,structzonelist*zonelist,+nodemask_t*nodemask)+{+structzone*zone;+inthigh_zoneidx=gfp_zone(gfp_mask);+pg_data_t*pgdat;++/*+*Kernelthreadsshouldnotbethrottledastheymaybeindirectly+*responsibleforcleaningpagesnecessaryforreclaimtomakeforward+*progress.kjournaldforexamplemayenterdirectreclaimwhile+*committingatransactionwherethrottlingitcouldforcingother+*processestoblockonlog_wait_commit().+*/+if(current->flags&PF_KTHREAD)+return;++/* Check if the pfmemalloc reserves are ok */+first_zones_zonelist(zonelist,high_zoneidx,NULL,&zone);+pgdat=zone->zone_pgdat;+if(pfmemalloc_watermark_ok(pgdat))+return;++/*+*Ifthecallercannotenterthefilesystem,it'spossiblethatit+*isduetothecallerholdinganFSlockorperformingajournal+*transactioninthecaseofafilesystemlikeext[3|4].Inthiscase,+*itisnotsafetoblockonpfmemalloc_waitaskswapdcouldbe+*blockedwaitingonthesamelock.Instead,throttleforuptoa+*secondbeforecontinuing.+*/+if(!(gfp_mask&__GFP_FS)){+wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,+pfmemalloc_watermark_ok(pgdat),HZ);+return;+}++/* Throttle until kswapd wakes the process */+wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,+pfmemalloc_watermark_ok(pgdat));+}+unsignedlongtry_to_free_pages(structzonelist*zonelist,intorder,gfp_tgfp_mask,nodemask_t*nodemask){
@@ -2449,6 +2523,15 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,.gfp_mask=sc.gfp_mask,};+throttle_direct_reclaim(gfp_mask,zonelist,nodemask);++/*+*Donotenterreclaimiffatalsignalispending.1isreturnedso+*thatthepageallocatordoesnotconsidertriggeringOOM+*/+if(fatal_signal_pending(current))+return1;+trace_mm_vmscan_direct_reclaim_begin(order,sc.may_writepage,gfp_mask);
@@ -2598,8 +2681,13 @@ static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages,returnbalanced_pages>=(present_pages>>2);}-/* is kswapd sleeping prematurely? */-staticboolsleeping_prematurely(pg_data_t*pgdat,intorder,longremaining,+/*+*Preparekswapdforsleeping.Thisverifiesthattherearenoprocesses+*waitinginthrottle_direct_reclaim()andthatwatermarkshavebeenmet.+*+*Returnstrueifkswapdisreadytosleep+*/+staticboolprepare_kswapd_sleep(pg_data_t*pgdat,intorder,longremaining,intclasszone_idx){inti;
@@ -2608,7 +2696,21 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,/* If a direct reclaimer woke kswapd within HZ/10, it's premature */if(remaining)-returntrue;+returnfalse;++/*+*Thereisapotentialracebetweenwhenkswapdchecksitswatermarks+*andaprocessgetsthrottled.Thereisalsoapotentialraceif+*processesgetthrottled,kswapdwakes,alargeprocessexitstherby+*balancingthezonesthatcauseskswapdtomissawakeup.Ifkswapd+*isgoingtosleep,noprocessshouldbesleepingonpfmemalloc_wait+*sowakethemnowifnecessary.Ifnecessary,processeswillwake+*kswapdandgetthrottledagain+*/+if(waitqueue_active(&pgdat->pfmemalloc_wait)){+wake_up(&pgdat->pfmemalloc_wait);+returnfalse;+}/* Check the watermark levels */for(i=0;i<=classzone_idx;i++){
@@ -2641,9 +2743,9 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,*mustbebalanced*/if(order)-return!pgdat_balanced(pgdat,balanced,classzone_idx);+returnpgdat_balanced(pgdat,balanced,classzone_idx);else-return!all_zones_ok;+returnall_zones_ok;}/*
@@ -2871,6 +2973,16 @@ loop_again:}}++/*+*Ifthelowwatermarkismetthereisnoneedforprocesses+*tobethrottledonpfmemalloc_waitastheyshouldnotbe+*abletosafelymakeforwardprogress.Wakethem+*/+if(waitqueue_active(&pgdat->pfmemalloc_wait)&&+pfmemalloc_watermark_ok(pgdat))+wake_up(&pgdat->pfmemalloc_wait);+if(all_zones_ok||(order&&pgdat_balanced(pgdat,balanced,*classzone_idx)))break;/* kswapd: all done *//*
@@ -2991,7 +3103,7 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)prepare_to_wait(&pgdat->kswapd_wait,&wait,TASK_INTERRUPTIBLE);/* Try to sleep for a short interval */-if(!sleeping_prematurely(pgdat,order,remaining,classzone_idx)){+if(prepare_kswapd_sleep(pgdat,order,remaining,classzone_idx)){remaining=schedule_timeout(HZ/10);finish_wait(&pgdat->kswapd_wait,&wait);prepare_to_wait(&pgdat->kswapd_wait,&wait,TASK_INTERRUPTIBLE);
@@ -3001,7 +3113,7 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)*Afterashortsleep,checkifitwasaprematuresleep.Ifnot,then*gofullytosleepuntilexplicitlywokenup.*/-if(!sleeping_prematurely(pgdat,order,remaining,classzone_idx)){+if(prepare_kswapd_sleep(pgdat,order,remaining,classzone_idx)){trace_mm_vmscan_kswapd_sleep(pgdat->node_id);/*
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Set SOCK_MEMALLOC on the NBD socket to allow access to PFMEMALLOC
reserves so pages backed by NBD, particularly if swap related, can
be cleaned to prevent the machine being deadlocked. It is still
possible that the PFMEMALLOC reserves get depleted resulting in
deadlock but this can be resolved by the administrator by increasing
min_free_kbytes.
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
drivers/block/nbd.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
@@ -154,6 +154,7 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,structmsghdrmsg;structkveciov;sigset_tblocked,oldset;+unsignedlongpflags=current->flags;if(unlikely(!sock)){dev_err(disk_to_dev(nbd->disk),
@@ -167,8 +168,9 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,siginitsetinv(&blocked,sigmask(SIGKILL));sigprocmask(SIG_SETMASK,&blocked,&oldset);+current->flags|=PF_MEMALLOC;do{-sock->sk->sk_allocation=GFP_NOIO;+sock->sk->sk_allocation=GFP_NOIO|__GFP_MEMALLOC;iov.iov_base=buf;iov.iov_len=size;msg.msg_name=NULL;
@@ -214,6 +216,7 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,}while(size>0);sigprocmask(SIG_SETMASK,&oldset,NULL);+tsk_restore_flags(current,pflags,PF_MEMALLOC);returnresult;}
@@ -405,6 +408,7 @@ static int nbd_do_it(struct nbd_device *nbd)BUG_ON(nbd->magic!=NBD_MAGIC);+sk_set_memalloc(nbd->sock->sk);nbd->pid=task_pid_nr(current);ret=device_create_file(disk_to_dev(nbd->disk),&pid_attr);if(ret){
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Getting and putting objects in SLAB currently requires a function call
but the bulk of the work is related to PFMEMALLOC reserves which are
only consumed when network-backed storage is critical. Use an inline
function to determine if the function call is required.
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
mm/slab.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Allow specific sockets to be tagged SOCK_MEMALLOC and use
__GFP_MEMALLOC for their allocations. These sockets will be able to go
below watermarks and allocate from the emergency reserve. Such sockets
are to be used to service the VM (iow. to swap over). They must be
handled kernel side, exposing such a socket to user-space is a bug.
There is a risk that the reserves be depleted so for now, the
administrator is responsible for increasing min_free_kbytes as
necessary to prevent deadlock for their workloads.
[a.p.zijlstra@chello.nl: Original patches]
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/net/sock.h | 5 ++++-
net/core/sock.c | 22 ++++++++++++++++++++++
2 files changed, 26 insertions(+), 1 deletion(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Introduce sk_allocation(), this function allows to inject sock specific
flags to each sock related allocation. It is only used on allocation
paths that may be required for writing pages back to network storage.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/net/sock.h | 5 +++++
net/ipv4/tcp.c | 3 ++-
net/ipv4/tcp_output.c | 16 +++++++++-------
net/ipv6/tcp_ipv6.c | 8 +++++---
4 files changed, 21 insertions(+), 11 deletions(-)
@@ -698,7 +698,8 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)/* The TCP header must be at least 32-bit aligned. */size=ALIGN(size,4);-skb=alloc_skb_fclone(size+sk->sk_prot->max_header,gfp);+skb=alloc_skb_fclone(size+sk->sk_prot->max_header,+sk_allocation(sk,gfp));if(skb){if(sk_wmem_schedule(sk,skb->truesize)){skb_reserve(skb,sk->sk_prot->max_header);
@@ -2756,7 +2758,7 @@ void tcp_send_ack(struct sock *sk)/* Send it off, this clears delayed acks for us. */TCP_SKB_CB(buff)->when=tcp_time_stamp;-tcp_transmit_skb(sk,buff,0,GFP_ATOMIC);+tcp_transmit_skb(sk,buff,0,sk_allocation(sk,GFP_ATOMIC));}/* This routine sends a packet with an out of date sequence
@@ -2776,7 +2778,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent)structsk_buff*skb;/* We don't queue it, tcp_transmit_skb() sets ownership. */-skb=alloc_skb(MAX_TCP_HEADER,GFP_ATOMIC);+skb=alloc_skb(MAX_TCP_HEADER,sk_allocation(sk,GFP_ATOMIC));if(skb==NULL)return-1;
@@ -1500,7 +1502,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)--ANK(980728)*/if(np->rxopt.all)-opt_skb=skb_clone(skb,GFP_ATOMIC);+opt_skb=skb_clone(skb,sk_allocation(sk,GFP_ATOMIC));if(sk->sk_state==TCP_ESTABLISHED){/* Fast path */sock_rps_save_rxhash(sk,skb);
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
This is needed to allow network softirq packet processing to make
use of PF_MEMALLOC.
Currently softirq context cannot use PF_MEMALLOC due to it not being
associated with a task, and therefore not having task flags to fiddle
with - thus the gfp to alloc flag mapping ignores the task flags when
in interrupts (hard or soft) context.
Allowing softirqs to make use of PF_MEMALLOC therefore requires some
trickery. We basically borrow the task flags from whatever process
happens to be preempted by the softirq.
So we modify the gfp to alloc flags mapping to not exclude task flags
in softirq context, and modify the softirq code to save, clear and
restore the PF_MEMALLOC flag.
The save and clear, ensures the preempted task's PF_MEMALLOC flag
doesn't leak into the softirq. The restore ensures a softirq's
PF_MEMALLOC flag cannot leak back into the preempted process.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/sched.h | 7 +++++++
kernel/softirq.c | 9 +++++++++
mm/page_alloc.c | 6 +++++-
3 files changed, 21 insertions(+), 1 deletion(-)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
__GFP_MEMALLOC will allow the allocation to disregard the watermarks,
much like PF_MEMALLOC. It allows one to pass along the memalloc state
in object related allocation flags as opposed to task related flags,
such as sk->sk_allocation. This removes the need for ALLOC_PFMEMALLOC
as callers using __GFP_MEMALLOC can get the ALLOC_NO_WATERMARK flag
which is now enough to identify allocations related to page reclaim.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/gfp.h | 10 ++++++++--
include/linux/mm_types.h | 2 +-
include/trace/events/gfpflags.h | 1 +
mm/page_alloc.c | 22 ++++++++++------------
mm/slab.c | 2 +-
5 files changed, 21 insertions(+), 16 deletions(-)
@@ -54,7 +54,7 @@ struct page {pgoff_tindex;/* Our offset within mapping. */void*freelist;/* slub first free object */boolpfmemalloc;/* If set by the page allocator,-*ALLOC_PFMEMALLOCwasset+*ALLOC_NO_WATERMARKSwasset*andthelowwatermarkwasnot*metimplyingthatthesystem*isundersomepressure.The
@@ -1930,7 +1930,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)returnNULL;}-/* Record if ALLOC_PFMEMALLOC was set when allocating the slab */+/* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */if(unlikely(page->pfmemalloc))pfmemalloc_active=true;
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From: Christoph Lameter <redacted>
This patch removes the check for pfmemalloc from the alloc hotpath and
puts the logic after the election of a new per cpu slab. For a pfmemalloc
page we do not use the fast path but force the use of the slow path which
is also used for the debug case.
This has the side-effect of weakening pfmemalloc processing in the
following way;
1. A process that is allocating for network swap calls __slab_alloc.
pfmemalloc_match is true so the freelist is loaded and c->freelist is
now pointing to a pfmemalloc page.
2. A process that is attempting normal allocations calls slab_alloc,
finds the pfmemalloc page on the freelist and uses it because it did
not check pfmemalloc_match()
The patch allows non-pfmemalloc allocations to use pfmemalloc pages with
the kmalloc slabs being the most vunerable caches on the grounds they
are most likely to have a mix of pfmemalloc and !pfmemalloc requests. A
later patch will still protect the system as processes will get throttled
if the pfmemalloc reserves get depleted but performance will not degrade
as smoothly.
[mgorman@suse.de: Expanded changelog]
Signed-off-by: Christoph Lameter <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
mm/slub.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
@@ -2298,11 +2298,11 @@ new_slab:}}-if(likely(!kmem_cache_debug(s)))+if(likely(!kmem_cache_debug(s)&&pfmemalloc_match(c,gfpflags)))gotoload_freelist;/* Only entered in the debug case */-if(!alloc_debug_processing(s,c->page,object,addr))+if(kmem_cache_debug(s)&&!alloc_debug_processing(s,c->page,object,addr))gotonew_slab;/* Slab failed checks. Next slab needed */c->freelist=get_freepointer(s,object);
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Allocations of pages below the min watermark run a risk of the
machine hanging due to a lack of memory. To prevent this, only
callers who have PF_MEMALLOC or TIF_MEMDIE set and are not processing
an interrupt are allowed to allocate with ALLOC_NO_WATERMARKS. Once
they are allocated to a slab though, nothing prevents other callers
consuming free objects within those slabs. This patch limits access
to slab pages that were alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark are
returned with page->pfmemalloc set and it is up to the caller to determine
how the page should be protected. SLAB restricts access to any page with
page->pfmemalloc set to callers which are known to able to access the
PFMEMALLOC reserve. If one is not available, an attempt is made to allocate
a new page rather than use a reserve. SLUB is a bit more relaxed in that
it only records if the current per-CPU page was allocated from PFMEMALLOC
reserve and uses another partial slab if the caller does not have the
necessary GFP or process flags. This was found to be sufficient in tests
to avoid hangs due to SLUB generally maintaining smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators
can fail a slab allocation even though free objects are available
because they are being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
Signed-off-by: Mel Gorman <mgorman@suse.de>
---
include/linux/mm_types.h | 9 +++
include/linux/page-flags.h | 28 +++++++
mm/internal.h | 3 +
mm/page_alloc.c | 27 +++++--
mm/slab.c | 188 +++++++++++++++++++++++++++++++++++++++-----
mm/slub.c | 27 ++++++-
6 files changed, 257 insertions(+), 25 deletions(-)
@@ -53,6 +53,15 @@ struct page {union{pgoff_tindex;/* Our offset within mapping. */void*freelist;/* slub first free object */+boolpfmemalloc;/* If set by the page allocator,+*ALLOC_PFMEMALLOCwasset+*andthelowwatermarkwasnot+*metimplyingthatthesystem+*isundersomepressure.The+*callershouldtryensure+*thispageisonlyusedto+*freeotherpages.+*/};union{
@@ -951,6 +980,98 @@ static struct array_cache *alloc_arraycache(int node, int entries,returnnc;}+staticinlineboolis_slab_pfmemalloc(structslab*slabp)+{+structpage*page=virt_to_page(slabp->s_mem);++returnPageSlabPfmemalloc(page);+}++/* Clears ac->pfmemalloc if no slabs have pfmalloc set */+staticvoidcheck_ac_pfmemalloc(structkmem_cache*cachep,+structarray_cache*ac)+{+structkmem_list3*l3=cachep->nodelists[numa_mem_id()];+structslab*slabp;++if(!pfmemalloc_active)+return;++list_for_each_entry(slabp,&l3->slabs_full,list)+if(is_slab_pfmemalloc(slabp))+return;++list_for_each_entry(slabp,&l3->slabs_partial,list)+if(is_slab_pfmemalloc(slabp))+return;++list_for_each_entry(slabp,&l3->slabs_free,list)+if(is_slab_pfmemalloc(slabp))+return;++pfmemalloc_active=false;+}++staticvoid*ac_get_obj(structkmem_cache*cachep,structarray_cache*ac,+gfp_tflags,boolforce_refill)+{+inti;+void*objp=ac->entry[--ac->avail];++/* Ensure the caller is allowed to use objects from PFMEMALLOC slab */+if(unlikely(is_obj_pfmemalloc(objp))){+structkmem_list3*l3;++if(gfp_pfmemalloc_allowed(flags)){+clear_obj_pfmemalloc(&objp);+returnobjp;+}++/* The caller cannot use PFMEMALLOC objects, find another one */+for(i=1;i<ac->avail;i++){+/* If a !PFMEMALLOC object is found, swap them */+if(!is_obj_pfmemalloc(ac->entry[i])){+objp=ac->entry[i];+ac->entry[i]=ac->entry[ac->avail];+ac->entry[ac->avail]=objp;+returnobjp;+}+}++/*+*Ifthereareemptyslabsontheslabs_freelistandweare+*beingforcedtorefillthecache,markthisone!pfmemalloc.+*/+l3=cachep->nodelists[numa_mem_id()];+if(!list_empty(&l3->slabs_free)&&force_refill){+structslab*slabp=virt_to_slab(objp);+ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem));+clear_obj_pfmemalloc(&objp);+check_ac_pfmemalloc(cachep,ac);+returnobjp;+}++/* No !PFMEMALLOC objects available */+ac->avail++;+objp=NULL;+}++returnobjp;+}++staticvoidac_put_obj(structkmem_cache*cachep,structarray_cache*ac,+void*objp)+{+if(unlikely(pfmemalloc_active)){+/* Some pfmemalloc slabs exist, check if this is one */+structpage*page=virt_to_page(objp);+if(PageSlabPfmemalloc(page))+set_obj_pfmemalloc(&objp);+}++ac->entry[ac->avail++]=objp;+}+/**Transferobjectsinonearraycachetoanother.*Lockingmustbehandledbythecaller.
@@ -1809,6 +1930,10 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)returnNULL;}+/* Record if ALLOC_PFMEMALLOC was set when allocating the slab */+if(unlikely(page->pfmemalloc))+pfmemalloc_active=true;+nr_pages=(1<<cachep->gfporder);if(cachep->flags&SLAB_RECLAIM_ACCOUNT)add_zone_page_state(page_zone(page),
@@ -3199,18 +3332,22 @@ alloc_done:if(unlikely(!ac->avail)){intx;+force_grow:x=cache_grow(cachep,flags|GFP_THISNODE,node,NULL);/* cache_grow can reenable interrupts, then ac could change. */ac=cpu_cache_get(cachep);-if(!x&&ac->avail==0)/* no objects in sight? abort */++/* no objects in sight? abort */+if(!x&&(ac->avail==0||force_refill))returnNULL;if(!ac->avail)/* objects refilled by interrupt? */gotoretry;}ac->touched=1;-returnac->entry[--ac->avail];++returnac_get_obj(cachep,ac,flags,force_refill);}staticinlinevoidcache_alloc_debugcheck_before(structkmem_cache*cachep,
@@ -2225,6 +2238,16 @@ redo:gotonew_slab;}+/*+*Byrights,weshouldbesearchingforaslabpagethatwas+*PFMEMALLOCbutrightnow,wearelosingthepfmemalloc+*informationwhenthepageleavestheper-cpuallocator+*/+if(unlikely(!pfmemalloc_match(c,gfpflags))){+deactivate_slab(s,c);+gotonew_slab;+}+/* must check again c->freelist in case of cpu migration or IRQ */object=c->freelist;if(object)
--
1.7.9.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From: Mike Christie <hidden> Date: 2012-05-10 17:17:24
On 05/10/2012 08:44 AM, Mel Gorman wrote:
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
Thank you for working on this. I made the attached patch for software
iscsi which has the same issue as nbd.
I tested the patch here and did not notice any performance regressions
or any other bugs.
This is needed to allow network softirq packet processing to make
use of PF_MEMALLOC.
Currently softirq context cannot use PF_MEMALLOC due to it not being
associated with a task, and therefore not having task flags to fiddle
with - thus the gfp to alloc flag mapping ignores the task flags when
in interrupts (hard or soft) context.
Allowing softirqs to make use of PF_MEMALLOC therefore requires some
trickery. We basically borrow the task flags from whatever process
happens to be preempted by the softirq.
So we modify the gfp to alloc flags mapping to not exclude task flags
in softirq context, and modify the softirq code to save, clear and
restore the PF_MEMALLOC flag.
The save and clear, ensures the preempted task's PF_MEMALLOC flag
doesn't leak into the softirq. The restore ensures a softirq's
PF_MEMALLOC flag cannot leak back into the preempted process.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
We're now making changes to task->flags from both base and
softirq context, but with non-atomic operations and no other
kind of synchronization.
As far as I can tell, this has to be racy.
If this works via some magic combination of invariants, you
absolutely have to document this, verbosely.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Introduce sk_allocation(), this function allows to inject sock specific
flags to each sock related allocation. It is only used on allocation
paths that may be required for writing pages back to network storage.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
This is still a little bit more than it needs to be.
You are trying to propagate a single bit from sk->sk_allocation into
all of the annotated socket memory allocation sites.
But many of them use sk->sk_allocation already. In fact all of them
that use a variable rather than a constant GFP_* satisfy this
invariant.
All of those annotations are therefore spurious, and probably end up
generating unnecessary |'s in of that special bit in at least some
cases.
What you really, therefore, care about are the GFP_FOO cases. And in
fact those are all GFP_ATOMIC. So make something that says what it
is that you want, a GFP_ATOMIC with some socket specified bits |'d
in.
Something like this:
static inline gfp_t sk_gfp_atomic(struct sock *sk)
{
return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC);
}
You'll also have to make your networking patches conform to the
networking subsystem coding style.
For example:
The sk_allocation() argument has to line up with the first column
after the openning parenthesis of the function call. You can't just
use all TAB characters. And this all TABs thing looks extremely ugly
to boot.
Same here.
What's really funny to me is that in several cases elsewhere in this
pach you get it right.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Allow specific sockets to be tagged SOCK_MEMALLOC and use
__GFP_MEMALLOC for their allocations. These sockets will be able to go
below watermarks and allocate from the emergency reserve. Such sockets
are to be used to service the VM (iow. to swap over). They must be
handled kernel side, exposing such a socket to user-space is a bug.
There is a risk that the reserves be depleted so for now, the
administrator is responsible for increasing min_free_kbytes as
necessary to prevent deadlock for their workloads.
[a.p.zijlstra@chello.nl: Original patches]
Signed-off-by: Mel Gorman <mgorman@suse.de>
After sk_allocation() is adjusted to be sk_gfp_atomic() as I suggested
in my feedback for patch #8, this is fine.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Likewise.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
+/**
+ * propagate_pfmemalloc_skb - Propagate pfmemalloc if skb is allocated after RX page
+ * @page: The page that was allocated from netdev_alloc_page
+ * @skb: The skb that may need pfmemalloc set
+ */
+static inline void propagate_pfmemalloc_skb(struct page *page,
+ struct sk_buff *skb)
Please use consistent prefixes in the names for new interfaces.
This one should probably be named "skb_propagate_pfmemalloc()" and
go into skbuff.h since it needs no knowledge of netdevices.
In fact all of these routines are about propagation of attributes
into SKBs, irregardless of any netdevice details.
Therefore they should probably all be named skb_*() and go into
skbuff.h
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
In order to make sure pfmemalloc packets receive all memory
needed to proceed, ensure processing of pfmemalloc SKBs happens
under PF_MEMALLOC. This is limited to a subset of protocols that
are expected to be used for writing to swap. Taps are not allowed to
use PF_MEMALLOC as these are expected to communicate with userspace
processes which could be paged out.
[a.p.zijlstra@chello.nl: Ideas taken from various patches]
[jslaby@suse.cz: Lock imbalance fix]
Signed-off-by: Mel Gorman <mgorman@suse.de>
This adds more code where we're modifying task->flags from software
interrupt context. I'm not convinced that's safe.
Also, this starts to add new tests in the fast paths.
Most of the time they are not going to trigger at all.
Please use the static branch I asked you to add in a previous
patch to mitigate this.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From: David Miller <davem@davemloft.net> Date: 2012-05-11 05:04:58
Ok, I'm generally happy with the networking parts.
If you address my feedback I'll sign off on it.
The next question is whose tree this stuff goes through :-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Introduce sk_allocation(), this function allows to inject sock specific
flags to each sock related allocation. It is only used on allocation
paths that may be required for writing pages back to network storage.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
This is still a little bit more than it needs to be.
You are trying to propagate a single bit from sk->sk_allocation into
all of the annotated socket memory allocation sites.
But many of them use sk->sk_allocation already. In fact all of them
that use a variable rather than a constant GFP_* satisfy this
invariant.
All of those annotations are therefore spurious, and probably end up
generating unnecessary |'s in of that special bit in at least some
cases.
Yes, you're completely correct here.
What you really, therefore, care about are the GFP_FOO cases. And in
fact those are all GFP_ATOMIC. So make something that says what it
is that you want, a GFP_ATOMIC with some socket specified bits |'d
in.
Something like this:
static inline gfp_t sk_gfp_atomic(struct sock *sk)
{
return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC);
}
I went with this.
You'll also have to make your networking patches conform to the
networking subsystem coding style.
For example:
The sk_allocation() argument has to line up with the first column
after the openning parenthesis of the function call. You can't just
use all TAB characters. And this all TABs thing looks extremely ugly
to boot.
I was not aware of the networking subsystem coding style. I'll fix it
up.
Same here.
What's really funny to me is that in several cases elsewhere in this
pach you get it right.
Whether I got it right or not would be effectively random. I tried
myself to see what pattern I was using thinking it would be "always"
tab but nope, no pattern :)
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
+/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */
+bool gfp_pfmemalloc_allowed(gfp_t gfp_mask);
I know this gets added in an earlier patch, but it seems slightly
overkill to have a function call just for a simply bit test.
It's not that simple. gfp_pfmemalloc_allowed calls gfp_to_alloc_flags()
which is quite involved and probably should not be duplicated. In the slab
case, it's called from slow paths where we are already under memory pressure
and swapping to network so it's not a major problem. In the network case,
it is called when kmalloc() has already failed and also a slow path.
Will do. I renamed memalloc_socks to sk_memalloc_socks, made it a int as
atomics are unnecessary and I check it directly in a branch instead of a
static inline. It should be relatively easy for the branch predictor.
Done.
Thanks.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Will do. I renamed memalloc_socks to sk_memalloc_socks, made it a int as
atomics are unnecessary and I check it directly in a branch instead of a
static inline. It should be relatively easy for the branch predictor.
David means you to use include/linux/jump_label.h.
static struct static_key sk_memalloc_socks = STATIC_KEY_INIT_FALSE;
and have your function read:
static inline bool sk_memalloc_socks(void)
{
return static_key_false(&sk_memalloc_socks);
}
which can be modified using:
static_key_slow_inc(&sk_memalloc_socks);
or
static_key_slow_dec(&sk_memalloc_socks);
This magic goo turns the branch into self-modifying code such that the
branch is an unconditional jump at runtime.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
+/**
+ * propagate_pfmemalloc_skb - Propagate pfmemalloc if skb is allocated after RX page
+ * @page: The page that was allocated from netdev_alloc_page
+ * @skb: The skb that may need pfmemalloc set
+ */
+static inline void propagate_pfmemalloc_skb(struct page *page,
+ struct sk_buff *skb)
Please use consistent prefixes in the names for new interfaces.
Understood.
This one should probably be named "skb_propagate_pfmemalloc()" and
go into skbuff.h since it needs no knowledge of netdevices.
I used a netdev prefix and placed it in skbuff.h which was stupid. The
screw-up was because I was partially reverting a patch that deleted
netdev_alloc_page but I didn't need any device information so the naming
was poor. I renamed netdev_alloc_page to skb_alloc_page and will fix up
the documentation appropriately.
Thanks.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Will do. I renamed memalloc_socks to sk_memalloc_socks, made it a int as
atomics are unnecessary and I check it directly in a branch instead of a
static inline. It should be relatively easy for the branch predictor.
David means you to use include/linux/jump_label.h.
Ah, that makes a whole lot more sense. Thanks for the clarification.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Fri, May 11, 2012 at 01:04:45AM -0400, David Miller wrote:
Ok, I'm generally happy with the networking parts.
Great!
If you address my feedback I'll sign off on it.
I didn't get through all the feedback and respond today but I will
during next week, get it retested and reposted. Thanks a lot.
The next question is whose tree this stuff goes through :-)
Yep, that's going to be entertaining. I had structured this so it could
go through multiple trees but it's not perfect. If I switch patches 14
(slab-related) and 15 (network related), then it becomes
Patch 1 gets dropped after the next merge window as it'll be in mainline anyway
Patch 2-3 goes through Pekka's sl*b tree
Patch 4-7 goes through akpm
Patch 8-14 goes through linux-net
Patch 15-17 goes through akpm
That sort of multiple staging is messy though and correctness would depend
on what order linux-next pulls trees from. I think I should be able to
move 15-17 before linux-net which might simplify things a little although
that would be a bit odd from a bisection perspective.
From my point of view, the ideal would be that all the patches go through
akpm's tree or yours but that probably will cause merge difficulties.
Any recommendations?
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Fri, May 11, 2012 at 12:57:40AM -0400, David Miller wrote:
quoted
Please change this to be a static branch.
Will do. I renamed memalloc_socks to sk_memalloc_socks, made it a int as
atomics are unnecessary and I check it directly in a branch instead of a
static inline. It should be relatively easy for the branch predictor.
No branch predictor can beat an unconditional branch :-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From my point of view, the ideal would be that all the patches go
through akpm's tree or yours but that probably will cause merge
difficulties.
Any recommendations?
I know there will be networking side conflicts very soon, it's not a
matter of 'if' but 'when'.
But the trick is that I bet the 'mm' and 'slab' folks are in a similar
situation.
In any event I'm more than happy to take it all in my tree.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From my point of view, the ideal would be that all the patches go
through akpm's tree or yours but that probably will cause merge
difficulties.
Any recommendations?
I know there will be networking side conflicts very soon, it's not a
matter of 'if' but 'when'.
But the trick is that I bet the 'mm' and 'slab' folks are in a similar
situation.
In any event I'm more than happy to take it all in my tree.
I guess either is OK. The main thing is to get it all reviewed and
tested, after all.
I can take all the patches once it's all lined up and everyone is
happy. If the net bits later take significant damage then I can squirt them
at you once the core MM bits are merged. That would give you a few
days to check them over and get them into Linus. If that's a problem,
we can hold the net bits over for a cycle.
That's all assuming that the core MM parts are mergeable without the
net parts being merged. I trust that's the case!
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
This is needed to allow network softirq packet processing to make
use of PF_MEMALLOC.
Currently softirq context cannot use PF_MEMALLOC due to it not being
associated with a task, and therefore not having task flags to fiddle
with - thus the gfp to alloc flag mapping ignores the task flags when
in interrupts (hard or soft) context.
Allowing softirqs to make use of PF_MEMALLOC therefore requires some
trickery. We basically borrow the task flags from whatever process
happens to be preempted by the softirq.
So we modify the gfp to alloc flags mapping to not exclude task flags
in softirq context, and modify the softirq code to save, clear and
restore the PF_MEMALLOC flag.
The save and clear, ensures the preempted task's PF_MEMALLOC flag
doesn't leak into the softirq. The restore ensures a softirq's
PF_MEMALLOC flag cannot leak back into the preempted process.
Signed-off-by: Peter Zijlstra <redacted>
Signed-off-by: Mel Gorman <mgorman@suse.de>
We're now making changes to task->flags from both base and
softirq context, but with non-atomic operations and no other
kind of synchronization.
As far as I can tell, this has to be racy.
I'm not seeing the race you are thinking of.
Softirqs can run on multiple CPUs sure but the same task should not be
executing the same softirq code. Interrupts are disabled and the
executing process cannot sleep in softirq context so the task flags
cannot "leak" nor can they be concurrently modified.
Softirqs are not execued from hard interrupt context so there are no
races with hardirqs.
If the softirq is deferred to ksoftirq then its flags may be used
instead of a normal tasks but as the softirq cannot be preempted,
the PF_MEMALLOC flag does not leak to other code by accident.
When __do_softirq() is finished, care is taken to restore the
PF_MEMALLOC flag to the value when __do_softirq() started. They
should not be accidentally clearing the flag.
I'm not seeing how current->flags can be modified while the softirq handler
is running in such a way that information is lost or misused. There
would be a problem if softirqs used GFP_KERNEL because the presense of
the PF_MEMALLOC flag would prevent the use of direct reclaim but softirqs
cannot use direct reclaim anyway.
If this works via some magic combination of invariants, you
absolutely have to document this, verbosely.
Did I miss a race you are thinking of or should I just add the above
explanation to the changelog?
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From my point of view, the ideal would be that all the patches go
through akpm's tree or yours but that probably will cause merge
difficulties.
Any recommendations?
I know there will be networking side conflicts very soon, it's not a
matter of 'if' but 'when'.
But the trick is that I bet the 'mm' and 'slab' folks are in a similar
situation.
In any event I'm more than happy to take it all in my tree.
I guess either is OK. The main thing is to get it all reviewed and
tested, after all.
I can take all the patches once it's all lined up and everyone is
happy. If the net bits later take significant damage then I can squirt them
at you once the core MM bits are merged. That would give you a few
days to check them over and get them into Linus. If that's a problem,
we can hold the net bits over for a cycle.
That's all assuming that the core MM parts are mergeable without the
net parts being merged. I trust that's the case!
I expect it to be the case as the series is (or at least should be)
bisect safe. If there is a conflict of some sort, just cut off at that
point and it should be fine until it gets fixed up.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Mon, May 14, 2012 at 11:02:29AM +0100, Mel Gorman wrote:
Softirqs can run on multiple CPUs sure but the same task should not be
executing the same softirq code. Interrupts are disabled and the
executing process cannot sleep in softirq context so the task flags
cannot "leak" nor can they be concurrently modified.
This comment about hardirq is obviously wrong as __do_softirq() enables
interrupts and can be preempted by a hardirq. I've updated the changelog
now to include the following;
Softirqs can run on multiple CPUs sure but the same task should not be
executing the same softirq code. Neither should the softirq
handler be preempted by any other softirq handler so the flags
should not leak to an unrelated softirq.
Softirqs re-enable hardware interrupts in __do_softirq() so can be
preempted by hardware interrupts so PF_MEMALLOC is inherited
by the hard IRQ. However, this is similar to a process in
reclaim being preempted by a hardirq. While PF_MEMALLOC is
set, gfp_to_alloc_flags() distinguishes between hard and
soft irqs and avoids giving a hardirq the ALLOC_NO_WATERMARKS
flag.
If the softirq is deferred to ksoftirq then its flags may be used
instead of a normal tasks but as the softirq cannot be preempted,
the PF_MEMALLOC flag does not leak to other code by accident.
--
Mel Gorman
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>