]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/shmem.c
mm: fix list corruptions on shmem shrinklist
[karo-tx-linux.git] / mm / shmem.c
index 9418f5a9bc46891df40335a74b809c26e5e94928..6540e598244412023db650412062604b704b58b3 100644 (file)
@@ -1022,7 +1022,11 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
                         */
                        if (IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE)) {
                                spin_lock(&sbinfo->shrinklist_lock);
-                               if (list_empty(&info->shrinklist)) {
+                               /*
+                                * _careful to defend against unlocked access to
+                                * ->shrink_list in shmem_unused_huge_shrink()
+                                */
+                               if (list_empty_careful(&info->shrinklist)) {
                                        list_add_tail(&info->shrinklist,
                                                        &sbinfo->shrinklist);
                                        sbinfo->shrinklist_len++;
@@ -1817,7 +1821,11 @@ alloc_nohuge:            page = shmem_alloc_and_acct_page(gfp, info, sbinfo,
                         * to shrink under memory pressure.
                         */
                        spin_lock(&sbinfo->shrinklist_lock);
-                       if (list_empty(&info->shrinklist)) {
+                       /*
+                        * _careful to defend against unlocked access to
+                        * ->shrink_list in shmem_unused_huge_shrink()
+                        */
+                       if (list_empty_careful(&info->shrinklist)) {
                                list_add_tail(&info->shrinklist,
                                                &sbinfo->shrinklist);
                                sbinfo->shrinklist_len++;
@@ -1977,10 +1985,12 @@ static int shmem_fault(struct vm_fault *vmf)
        }
 
        sgp = SGP_CACHE;
-       if (vma->vm_flags & VM_HUGEPAGE)
-               sgp = SGP_HUGE;
-       else if (vma->vm_flags & VM_NOHUGEPAGE)
+
+       if ((vma->vm_flags & VM_NOHUGEPAGE) ||
+           test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
                sgp = SGP_NOHUGE;
+       else if (vma->vm_flags & VM_HUGEPAGE)
+               sgp = SGP_HUGE;
 
        error = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, sgp,
                                  gfp, vma, vmf, &ret);