SHARE
TWEET

Untitled

a guest May 19th, 2019 75 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
  2. index 2b8ee90bb644..510766a3fa05 100644
  3. --- a/Documentation/admin-guide/kernel-parameters.txt
  4. +++ b/Documentation/admin-guide/kernel-parameters.txt
  5. @@ -2008,6 +2008,13 @@
  6.             0: force disabled
  7.             1: force enabled
  8.  
  9. +   ksm_mode=
  10. +           [KNL]
  11. +           Format: [madvise|always]
  12. +           Default: madvise
  13. +           Can be used to control the default behavior of the system
  14. +           with respect to merging anonymous memory.
  15. +
  16.     kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
  17.             Default is 0 (don't ignore, but inject #GP)
  18.  
  19. diff --git a/Documentation/admin-guide/mm/ksm.rst b/Documentation/admin-guide/mm/ksm.rst
  20. index 9303786632d1..9af730640da7 100644
  21. --- a/Documentation/admin-guide/mm/ksm.rst
  22. +++ b/Documentation/admin-guide/mm/ksm.rst
  23. @@ -78,6 +78,13 @@ KSM daemon sysfs interface
  24.  The KSM daemon is controlled by sysfs files in ``/sys/kernel/mm/ksm/``,
  25.  readable by all but writable only by root:
  26.  
  27. +mode
  28. +        * set madvise to deduplicate only madvised memory
  29. +        * set always to allow deduplicating all the anonymous memory
  30. +          (applies to newly allocated memory only)
  31. +
  32. +        Default: madvise (maintains old behaviour)
  33. +
  34.  pages_to_scan
  35.          how many pages to scan before ksmd goes to sleep
  36.          e.g. ``echo 100 > /sys/kernel/mm/ksm/pages_to_scan``.
  37. diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
  38. index 95ca1fe7283c..19cc246000e8 100644
  39. --- a/fs/proc/task_mmu.c
  40. +++ b/fs/proc/task_mmu.c
  41. @@ -648,6 +648,9 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
  42.         [ilog2(VM_MIXEDMAP)]    = "mm",
  43.         [ilog2(VM_HUGEPAGE)]    = "hg",
  44.         [ilog2(VM_NOHUGEPAGE)]  = "nh",
  45. +#ifdef VM_UNMERGEABLE
  46. +       [ilog2(VM_UNMERGEABLE)] = "ug",
  47. +#endif
  48.         [ilog2(VM_MERGEABLE)]   = "mg",
  49.         [ilog2(VM_UFFD_MISSING)]= "um",
  50.         [ilog2(VM_UFFD_WP)] = "uw",
  51. diff --git a/include/linux/ksm.h b/include/linux/ksm.h
  52. index e48b1e453ff5..3c076b35259c 100644
  53. --- a/include/linux/ksm.h
  54. +++ b/include/linux/ksm.h
  55. @@ -21,6 +21,11 @@ struct mem_cgroup;
  56.  #ifdef CONFIG_KSM
  57.  int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
  58.         unsigned long end, int advice, unsigned long *vm_flags);
  59. +#ifdef VM_UNMERGEABLE
  60. +bool ksm_mode_always(void);
  61. +#endif
  62. +int ksm_enter(struct mm_struct *mm, struct vm_area_struct *vma,
  63. +       unsigned long *vm_flags);
  64.  int __ksm_enter(struct mm_struct *mm);
  65.  void __ksm_exit(struct mm_struct *mm);
  66.  
  67. diff --git a/include/linux/mm.h b/include/linux/mm.h
  68. index 6b10c21630f5..114cdb882cdd 100644
  69. --- a/include/linux/mm.h
  70. +++ b/include/linux/mm.h
  71. @@ -252,11 +252,13 @@ extern unsigned int kobjsize(const void *objp);
  72.  #define VM_HIGH_ARCH_BIT_2 34  /* bit only usable on 64-bit architectures */
  73.  #define VM_HIGH_ARCH_BIT_3 35  /* bit only usable on 64-bit architectures */
  74.  #define VM_HIGH_ARCH_BIT_4 36  /* bit only usable on 64-bit architectures */
  75. +#define VM_HIGH_ARCH_BIT_5 37  /* bit only usable on 64-bit architectures */
  76.  #define VM_HIGH_ARCH_0 BIT(VM_HIGH_ARCH_BIT_0)
  77.  #define VM_HIGH_ARCH_1 BIT(VM_HIGH_ARCH_BIT_1)
  78.  #define VM_HIGH_ARCH_2 BIT(VM_HIGH_ARCH_BIT_2)
  79.  #define VM_HIGH_ARCH_3 BIT(VM_HIGH_ARCH_BIT_3)
  80.  #define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4)
  81. +#define VM_HIGH_ARCH_5 BIT(VM_HIGH_ARCH_BIT_5)
  82.  #endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */
  83.  
  84.  #ifdef CONFIG_ARCH_HAS_PKEYS
  85. @@ -272,6 +274,10 @@ extern unsigned int kobjsize(const void *objp);
  86.  #endif
  87.  #endif /* CONFIG_ARCH_HAS_PKEYS */
  88.  
  89. +#ifdef VM_HIGH_ARCH_5
  90. +#define VM_UNMERGEABLE VM_HIGH_ARCH_5  /* Opt-out for KSM "always" mode */
  91. +#endif /* VM_HIGH_ARCH_5 */
  92. +
  93.  #if defined(CONFIG_X86)
  94.  # define VM_PAT        VM_ARCH_1   /* PAT reserves whole VMA at once (x86) */
  95.  #elif defined(CONFIG_PPC)
  96. diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
  97. index a1675d43777e..717e0fd9d2ef 100644
  98. --- a/include/trace/events/mmflags.h
  99. +++ b/include/trace/events/mmflags.h
  100. @@ -130,6 +130,12 @@ IF_HAVE_PG_IDLE(PG_idle,       "idle"      )
  101.  #define IF_HAVE_VM_SOFTDIRTY(flag,name)
  102.  #endif
  103.  
  104. +#ifdef VM_UNMERGEABLE
  105. +#define IF_HAVE_VM_UNMERGEABLE(flag,name) {flag, name },
  106. +#else
  107. +#define IF_HAVE_VM_UNMERGEABLE(flag,name)
  108. +#endif
  109. +
  110.  #define __def_vmaflag_names                        \
  111.     {VM_READ,           "read"      },      \
  112.     {VM_WRITE,          "write"     },      \
  113. @@ -161,6 +167,7 @@ IF_HAVE_VM_SOFTDIRTY(VM_SOFTDIRTY,  "softdirty" )       \
  114.     {VM_MIXEDMAP,           "mixedmap"  },      \
  115.     {VM_HUGEPAGE,           "hugepage"  },      \
  116.     {VM_NOHUGEPAGE,         "nohugepage"    },      \
  117. +IF_HAVE_VM_UNMERGEABLE(VM_UNMERGEABLE, "unmergeable"   )       \
  118.     {VM_MERGEABLE,          "mergeable" }       \
  119.  
  120.  #define show_vma_flags(flags)                      \
  121. diff --git a/mm/ksm.c b/mm/ksm.c
  122. index fc64874dc6f4..6a2280b875cc 100644
  123. --- a/mm/ksm.c
  124. +++ b/mm/ksm.c
  125. @@ -295,6 +295,12 @@ static int ksm_nr_node_ids = 1;
  126.  static unsigned long ksm_run = KSM_RUN_STOP;
  127.  static void wait_while_offlining(void);
  128.  
  129. +#ifdef VM_UNMERGEABLE
  130. +#define KSM_MODE_MADVISE   0
  131. +#define KSM_MODE_ALWAYS        1
  132. +static unsigned long ksm_mode = KSM_MODE_MADVISE;
  133. +#endif
  134. +
  135.  static DECLARE_WAIT_QUEUE_HEAD(ksm_thread_wait);
  136.  static DECLARE_WAIT_QUEUE_HEAD(ksm_iter_wait);
  137.  static DEFINE_MUTEX(ksm_thread_mutex);
  138. @@ -2450,36 +2456,18 @@ int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
  139.  
  140.     switch (advice) {
  141.     case MADV_MERGEABLE:
  142. -       /*
  143. -        * Be somewhat over-protective for now!
  144. -        */
  145. -       if (*vm_flags & (VM_MERGEABLE | VM_SHARED  | VM_MAYSHARE   |
  146. -                VM_PFNMAP    | VM_IO      | VM_DONTEXPAND |
  147. -                VM_HUGETLB | VM_MIXEDMAP))
  148. -           return 0;       /* just ignore the advice */
  149. -
  150. -       if (vma_is_dax(vma))
  151. -           return 0;
  152. -
  153. -#ifdef VM_SAO
  154. -       if (*vm_flags & VM_SAO)
  155. -           return 0;
  156. -#endif
  157. -#ifdef VM_SPARC_ADI
  158. -       if (*vm_flags & VM_SPARC_ADI)
  159. -           return 0;
  160. +#ifdef VM_UNMERGEABLE
  161. +       *vm_flags &= ~VM_UNMERGEABLE;
  162.  #endif
  163. -
  164. -       if (!test_bit(MMF_VM_MERGEABLE, &mm->flags)) {
  165. -           err = __ksm_enter(mm);
  166. -           if (err)
  167. -               return err;
  168. -       }
  169. -
  170. -       *vm_flags |= VM_MERGEABLE;
  171. +       err = ksm_enter(mm, vma, vm_flags);
  172. +       if (err)
  173. +           return err;
  174.         break;
  175.  
  176.     case MADV_UNMERGEABLE:
  177. +#ifdef VM_UNMERGEABLE
  178. +       *vm_flags |= VM_UNMERGEABLE;
  179. +#endif
  180.         if (!(*vm_flags & VM_MERGEABLE))
  181.             return 0;       /* just ignore the advice */
  182.  
  183. @@ -2496,6 +2484,76 @@ int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
  184.     return 0;
  185.  }
  186.  
  187. +#ifdef VM_UNMERGEABLE
  188. +bool ksm_mode_always(void)
  189. +{
  190. +   return ksm_mode == KSM_MODE_ALWAYS;
  191. +}
  192. +
  193. +static int __init setup_ksm_mode(char *str)
  194. +{
  195. +   int ret = 0;
  196. +
  197. +   if (!str)
  198. +       goto out;
  199. +
  200. +   if (!strcmp(str, "madvise")) {
  201. +       ksm_mode = KSM_MODE_MADVISE;
  202. +       ret = 1;
  203. +   } else if (!strcmp(str, "always")) {
  204. +       ksm_mode = KSM_MODE_ALWAYS;
  205. +       ret = 1;
  206. +   }
  207. +
  208. +out:
  209. +   if (!ret)
  210. +       pr_warn("ksm_mode= cannot parse, ignored\n");
  211. +
  212. +   return ret;
  213. +}
  214. +__setup("ksm_mode=", setup_ksm_mode);
  215. +#endif
  216. +
  217. +int ksm_enter(struct mm_struct *mm, struct vm_area_struct *vma,
  218. +       unsigned long *vm_flags)
  219. +{
  220. +   int err;
  221. +
  222. +   /*
  223. +    * Be somewhat over-protective for now!
  224. +    */
  225. +   if (*vm_flags & (VM_MERGEABLE | VM_SHARED  | VM_MAYSHARE   |
  226. +            VM_PFNMAP    | VM_IO      | VM_DONTEXPAND |
  227. +            VM_HUGETLB | VM_MIXEDMAP))
  228. +       return 0;       /* just ignore the advice */
  229. +
  230. +   if (vma_is_dax(vma))
  231. +       return 0;
  232. +
  233. +#ifdef VM_SAO
  234. +   if (*vm_flags & VM_SAO)
  235. +       return 0;
  236. +#endif
  237. +#ifdef VM_SPARC_ADI
  238. +   if (*vm_flags & VM_SPARC_ADI)
  239. +       return 0;
  240. +#endif
  241. +#ifdef VM_UNMERGEABLE
  242. +   if (*vm_flags & VM_UNMERGEABLE)
  243. +       return 0;
  244. +#endif
  245. +
  246. +   if (!test_bit(MMF_VM_MERGEABLE, &mm->flags)) {
  247. +       err = __ksm_enter(mm);
  248. +       if (err)
  249. +           return err;
  250. +   }
  251. +
  252. +   *vm_flags |= VM_MERGEABLE;
  253. +
  254. +   return 0;
  255. +}
  256. +
  257.  int __ksm_enter(struct mm_struct *mm)
  258.  {
  259.     struct mm_slot *mm_slot;
  260. @@ -2859,6 +2917,35 @@ static void wait_while_offlining(void)
  261.     static struct kobj_attribute _name##_attr = \
  262.         __ATTR(_name, 0644, _name##_show, _name##_store)
  263.  
  264. +#ifdef VM_UNMERGEABLE
  265. +static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr,
  266. +   char *buf)
  267. +{
  268. +   switch (ksm_mode) {
  269. +   case KSM_MODE_MADVISE:
  270. +       return sprintf(buf, "always [madvise]\n");
  271. +   case KSM_MODE_ALWAYS:
  272. +       return sprintf(buf, "[always] madvise\n");
  273. +   }
  274. +
  275. +   return sprintf(buf, "always [madvise]\n");
  276. +}
  277. +
  278. +static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
  279. +   const char *buf, size_t count)
  280. +{
  281. +   if (!memcmp("madvise", buf, min(sizeof("madvise")-1, count)))
  282. +       ksm_mode = KSM_MODE_MADVISE;
  283. +   else if (!memcmp("always", buf, min(sizeof("always")-1, count)))
  284. +       ksm_mode = KSM_MODE_ALWAYS;
  285. +   else
  286. +       return -EINVAL;
  287. +
  288. +   return count;
  289. +}
  290. +KSM_ATTR(mode);
  291. +#endif
  292. +
  293.  static ssize_t sleep_millisecs_show(struct kobject *kobj,
  294.                     struct kobj_attribute *attr, char *buf)
  295.  {
  296. @@ -3161,6 +3248,9 @@ static ssize_t full_scans_show(struct kobject *kobj,
  297.  KSM_ATTR_RO(full_scans);
  298.  
  299.  static struct attribute *ksm_attrs[] = {
  300. +#ifdef VM_UNMERGEABLE
  301. +   &mode_attr.attr,
  302. +#endif
  303.     &sleep_millisecs_attr.attr,
  304.     &pages_to_scan_attr.attr,
  305.     &run_attr.attr,
  306. diff --git a/mm/memory.c b/mm/memory.c
  307. index ab650c21bccd..08f3f92de310 100644
  308. --- a/mm/memory.c
  309. +++ b/mm/memory.c
  310. @@ -2994,6 +2994,12 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
  311.     update_mmu_cache(vma, vmf->address, vmf->pte);
  312.  unlock:
  313.     pte_unmap_unlock(vmf->pte, vmf->ptl);
  314. +
  315. +#if defined(CONFIG_KSM) && defined(VM_UNMERGEABLE)
  316. +   if (ksm_mode_always())
  317. +       ksm_enter(vma->vm_mm, vma, &vma->vm_flags);
  318. +#endif
  319. +
  320.     return ret;
  321.  release:
  322.     mem_cgroup_cancel_charge(page, memcg, false);
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top