mm, thp: relax the VM_DENYWRITE constraint on file-backed THPs
[linux-block.git] / mm / khugepaged.c
index d97b20fad6e8e61c6fd36f101e9e326632c3c388..b0412be08fa2c5cbb0a21057b30b1351bbf7b820 100644 (file)
@@ -457,7 +457,8 @@ static bool hugepage_vma_check(struct vm_area_struct *vma,
 
        /* Read-only file mappings need to be aligned for THP to work. */
        if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && vma->vm_file &&
-           (vm_flags & VM_DENYWRITE)) {
+           !inode_is_open_for_write(vma->vm_file->f_inode) &&
+           (vm_flags & VM_EXEC)) {
                return IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff,
                                HPAGE_PMD_NR);
        }
@@ -1862,6 +1863,19 @@ out_unlock:
        else {
                __mod_lruvec_page_state(new_page, NR_FILE_THPS, nr);
                filemap_nr_thps_inc(mapping);
+               /*
+                * Paired with smp_mb() in do_dentry_open() to ensure
+                * i_writecount is up to date and the update to nr_thps is
+                * visible. Ensures the page cache will be truncated if the
+                * file is opened writable.
+                */
+               smp_mb();
+               if (inode_is_open_for_write(mapping->host)) {
+                       result = SCAN_FAIL;
+                       __mod_lruvec_page_state(new_page, NR_FILE_THPS, -nr);
+                       filemap_nr_thps_dec(mapping);
+                       goto xa_locked;
+               }
        }
 
        if (nr_none) {