Message ID | 80e7221d9679032c2d5affc317957114e5d77657.1725481503.git.josef@toxicpanda.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fanotify: add pre-content hooks | expand |
On Wed, Sep 4, 2024 at 10:29 PM Josef Bacik <josef@toxicpanda.com> wrote: > > There's nothing stopping us from supporting this, we could simply pass > the order into the helper and emit the proper length. However currently > there's no tests to validate this works properly, so disable it until > there's a desire to support this along with the appropriate tests. > > Reviewed-by: Christian Brauner <brauner@kernel.org> > Signed-off-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Thanks, Amir. > --- > mm/memory.c | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/mm/memory.c b/mm/memory.c > index d10e616d7389..3010bcc5e4f9 100644 > --- a/mm/memory.c > +++ b/mm/memory.c > @@ -78,6 +78,7 @@ > #include <linux/ptrace.h> > #include <linux/vmalloc.h> > #include <linux/sched/sysctl.h> > +#include <linux/fsnotify.h> > > #include <trace/events/kmem.h> > > @@ -5252,8 +5253,17 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) > static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) > { > struct vm_area_struct *vma = vmf->vma; > + struct file *file = vma->vm_file; > if (vma_is_anonymous(vma)) > return do_huge_pmd_anonymous_page(vmf); > + /* > + * Currently we just emit PAGE_SIZE for our fault events, so don't allow > + * a huge fault if we have a pre content watch on this file. This would > + * be trivial to support, but there would need to be tests to ensure > + * this works properly and those don't exist currently. > + */ > + if (file && fsnotify_file_has_pre_content_watches(file)) > + return VM_FAULT_FALLBACK; > if (vma->vm_ops->huge_fault) > return vma->vm_ops->huge_fault(vmf, PMD_ORDER); > return VM_FAULT_FALLBACK; > @@ -5263,6 +5273,7 @@ static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) > static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf) > { > struct vm_area_struct *vma = vmf->vma; > + struct file *file = vma->vm_file; > const bool unshare = vmf->flags & FAULT_FLAG_UNSHARE; > vm_fault_t ret; > > @@ -5277,6 +5288,9 @@ static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf) > } > > if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) { > + /* See comment in create_huge_pmd. */ > + if (file && fsnotify_file_has_pre_content_watches(file)) > + goto split; > if (vma->vm_ops->huge_fault) { > ret = vma->vm_ops->huge_fault(vmf, PMD_ORDER); > if (!(ret & VM_FAULT_FALLBACK)) > @@ -5296,9 +5310,13 @@ static vm_fault_t create_huge_pud(struct vm_fault *vmf) > #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ > defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) > struct vm_area_struct *vma = vmf->vma; > + struct file *file = vma->vm_file; > /* No support for anonymous transparent PUD pages yet */ > if (vma_is_anonymous(vma)) > return VM_FAULT_FALLBACK; > + /* See comment in create_huge_pmd. */ > + if (file && fsnotify_file_has_pre_content_watches(file)) > + return VM_FAULT_FALLBACK; > if (vma->vm_ops->huge_fault) > return vma->vm_ops->huge_fault(vmf, PUD_ORDER); > #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ > @@ -5310,12 +5328,16 @@ static vm_fault_t wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud) > #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ > defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) > struct vm_area_struct *vma = vmf->vma; > + struct file *file = vma->vm_file; > vm_fault_t ret; > > /* No support for anonymous transparent PUD pages yet */ > if (vma_is_anonymous(vma)) > goto split; > if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) { > + /* See comment in create_huge_pmd. */ > + if (file && fsnotify_file_has_pre_content_watches(file)) > + goto split; > if (vma->vm_ops->huge_fault) { > ret = vma->vm_ops->huge_fault(vmf, PUD_ORDER); > if (!(ret & VM_FAULT_FALLBACK)) > -- > 2.43.0 >
diff --git a/mm/memory.c b/mm/memory.c index d10e616d7389..3010bcc5e4f9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -78,6 +78,7 @@ #include <linux/ptrace.h> #include <linux/vmalloc.h> #include <linux/sched/sysctl.h> +#include <linux/fsnotify.h> #include <trace/events/kmem.h> @@ -5252,8 +5253,17 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; + struct file *file = vma->vm_file; if (vma_is_anonymous(vma)) return do_huge_pmd_anonymous_page(vmf); + /* + * Currently we just emit PAGE_SIZE for our fault events, so don't allow + * a huge fault if we have a pre content watch on this file. This would + * be trivial to support, but there would need to be tests to ensure + * this works properly and those don't exist currently. + */ + if (file && fsnotify_file_has_pre_content_watches(file)) + return VM_FAULT_FALLBACK; if (vma->vm_ops->huge_fault) return vma->vm_ops->huge_fault(vmf, PMD_ORDER); return VM_FAULT_FALLBACK; @@ -5263,6 +5273,7 @@ static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; + struct file *file = vma->vm_file; const bool unshare = vmf->flags & FAULT_FLAG_UNSHARE; vm_fault_t ret; @@ -5277,6 +5288,9 @@ static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf) } if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) { + /* See comment in create_huge_pmd. */ + if (file && fsnotify_file_has_pre_content_watches(file)) + goto split; if (vma->vm_ops->huge_fault) { ret = vma->vm_ops->huge_fault(vmf, PMD_ORDER); if (!(ret & VM_FAULT_FALLBACK)) @@ -5296,9 +5310,13 @@ static vm_fault_t create_huge_pud(struct vm_fault *vmf) #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) struct vm_area_struct *vma = vmf->vma; + struct file *file = vma->vm_file; /* No support for anonymous transparent PUD pages yet */ if (vma_is_anonymous(vma)) return VM_FAULT_FALLBACK; + /* See comment in create_huge_pmd. */ + if (file && fsnotify_file_has_pre_content_watches(file)) + return VM_FAULT_FALLBACK; if (vma->vm_ops->huge_fault) return vma->vm_ops->huge_fault(vmf, PUD_ORDER); #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ @@ -5310,12 +5328,16 @@ static vm_fault_t wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud) #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) struct vm_area_struct *vma = vmf->vma; + struct file *file = vma->vm_file; vm_fault_t ret; /* No support for anonymous transparent PUD pages yet */ if (vma_is_anonymous(vma)) goto split; if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) { + /* See comment in create_huge_pmd. */ + if (file && fsnotify_file_has_pre_content_watches(file)) + goto split; if (vma->vm_ops->huge_fault) { ret = vma->vm_ops->huge_fault(vmf, PUD_ORDER); if (!(ret & VM_FAULT_FALLBACK))