summaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2018-07-03 17:14:56 +0200
committerJens Axboe <axboe@kernel.dk>2018-07-09 17:07:54 +0200
commit2cf855837b89d92996cf264713f3bed2bf9b0b4f (patch)
treed2e61e78a5dce7925bebb7c50d345838aa948b4a /mm/swapfile.c
parentblkcg: add generic throttling mechanism (diff)
downloadlinux-2cf855837b89d92996cf264713f3bed2bf9b0b4f.tar.xz
linux-2cf855837b89d92996cf264713f3bed2bf9b0b4f.zip
memcontrol: schedule throttling if we are congested
Memory allocations can induce swapping via kswapd or direct reclaim. If we are having IO done for us by kswapd and don't actually go into direct reclaim we may never get scheduled for throttling. So instead check to see if our cgroup is congested, and if so schedule the throttling. Before we return to user space the throttling stuff will only throttle if we actually required it. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Josef Bacik <jbacik@fb.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 2cc2972eedaf..db4ec8ae1c8c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -3731,6 +3731,37 @@ static void free_swap_count_continuations(struct swap_info_struct *si)
}
}
+#if defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP)
+void mem_cgroup_throttle_swaprate(struct mem_cgroup *memcg, int node,
+ gfp_t gfp_mask)
+{
+ struct swap_info_struct *si, *next;
+ if (!(gfp_mask & __GFP_IO) || !memcg)
+ return;
+
+ if (!blk_cgroup_congested())
+ return;
+
+ /*
+ * We've already scheduled a throttle, avoid taking the global swap
+ * lock.
+ */
+ if (current->throttle_queue)
+ return;
+
+ spin_lock(&swap_avail_lock);
+ plist_for_each_entry_safe(si, next, &swap_avail_heads[node],
+ avail_lists[node]) {
+ if (si->bdev) {
+ blkcg_schedule_throttle(bdev_get_queue(si->bdev),
+ true);
+ break;
+ }
+ }
+ spin_unlock(&swap_avail_lock);
+}
+#endif
+
static int __init swapfile_init(void)
{
int nid;