]> www.infradead.org Git - users/willy/linux.git/commitdiff
mm: Add become_kswapd and restore_kswapd
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 27 Mar 2020 16:57:58 +0000 (12:57 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 24 Jun 2020 16:57:30 +0000 (12:57 -0400)
Since XFS needs to pretend to be kswapd in some of its worker threads,
create methods to save & restore kswapd state.  Don't bother restoring
kswapd state in kswapd -- the only time we reach this code is when we're
exiting and the task_struct is about to be destroyed anyway.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
fs/xfs/libxfs/xfs_btree.c
include/linux/sched/mm.h
mm/vmscan.c

index 2d25bab687647794ae804f1347467ab248c3a886..a04a44238aab7f7bfd258b27def152fa4e32d4c9 100644 (file)
@@ -2813,8 +2813,9 @@ xfs_btree_split_worker(
 {
        struct xfs_btree_split_args     *args = container_of(work,
                                                struct xfs_btree_split_args, work);
+       bool                    is_kswapd = args->kswapd;
        unsigned long           pflags;
-       unsigned long           new_pflags = PF_MEMALLOC_NOFS;
+       int                     memalloc_nofs;
 
        /*
         * we are in a transaction context here, but may also be doing work
@@ -2822,16 +2823,17 @@ xfs_btree_split_worker(
         * temporarily to ensure that we don't block waiting for memory reclaim
         * in any way.
         */
-       if (args->kswapd)
-               new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
-
-       current_set_flags_nested(&pflags, new_pflags);
+       if (is_kswapd)
+               pflags = become_kswapd();
+       memalloc_nofs = memalloc_nofs_save();
 
        args->result = __xfs_btree_split(args->cur, args->level, args->ptrp,
                                         args->key, args->curp, args->stat);
        complete(args->done);
 
-       current_restore_flags_nested(&pflags, new_pflags);
+       memalloc_nofs_restore(memalloc_nofs);
+       if (is_kswapd)
+               restore_kswapd(pflags);
 }
 
 /*
index 1a7e1ab1be8569cb399ab9e97a2d3e7229a8114d..b0089eadc3670be6037fde0ef49512b467f827bd 100644 (file)
@@ -308,6 +308,32 @@ static inline void memalloc_nocma_restore(unsigned int flags)
 }
 #endif
 
+/*
+ * Tell the memory management that we're a "memory allocator",
+ * and that if we need more memory we should get access to it
+ * regardless (see "__alloc_pages()"). "kswapd" should
+ * never get caught in the normal page freeing logic.
+ *
+ * (Kswapd normally doesn't need memory anyway, but sometimes
+ * you need a small amount of memory in order to be able to
+ * page out something else, and this flag essentially protects
+ * us from recursively trying to free more memory as we're
+ * trying to free the first piece of memory in the first place).
+ */
+#define KSWAPD_PF_FLAGS                (PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD)
+
+static inline unsigned long become_kswapd(void)
+{
+       unsigned long flags = current->flags & KSWAPD_PF_FLAGS;
+       current->flags |= KSWAPD_PF_FLAGS;
+       return flags;
+}
+
+static inline void restore_kswapd(unsigned long flags)
+{
+       current->flags &= ~(flags ^ KSWAPD_PF_FLAGS);
+}
+
 static inline void set_current_io_flusher(void)
 {
        current->flags |= PF_LOCAL_THROTTLE;
index b6d84326bdf2dfd5c56b7b6265685630c40d57b7..27ae76699899c2a9b13c8894b1017f1b47361b45 100644 (file)
@@ -3870,19 +3870,7 @@ static int kswapd(void *p)
        if (!cpumask_empty(cpumask))
                set_cpus_allowed_ptr(tsk, cpumask);
 
-       /*
-        * Tell the memory management that we're a "memory allocator",
-        * and that if we need more memory we should get access to it
-        * regardless (see "__alloc_pages()"). "kswapd" should
-        * never get caught in the normal page freeing logic.
-        *
-        * (Kswapd normally doesn't need memory anyway, but sometimes
-        * you need a small amount of memory in order to be able to
-        * page out something else, and this flag essentially protects
-        * us from recursively trying to free more memory as we're
-        * trying to free the first piece of memory in the first place).
-        */
-       tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+       become_kswapd();
        set_freezable();
 
        WRITE_ONCE(pgdat->kswapd_order, 0);
@@ -3932,8 +3920,6 @@ kswapd_try_sleep:
                        goto kswapd_try_sleep;
        }
 
-       tsk->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD);
-
        return 0;
 }