Messages in this thread Patch in this message | | | From | Richard Weinberger <> | Subject | [PATCH] [RFC] kernfs: Allow vm_ops->close() if VMA is never split | Date | Sat, 4 Jul 2020 22:56:19 +0200 |
| |
10 years ago commit a6849fa1f7d7 ("sysfs: Fail bin file mmap if vma close is implemented.") removed support for vm_ops->close() for mmap on sysfs. As far I understand the reason is that due to the wrapping in kernfs every VMA split operation needs to be tracked to call vm_ops->close() for all fragments. This is not feasible with reasonable effort.
Since commit 31383c6865a5 ("mm, hugetlbfs: introduce ->split() to vm_operations_struct") we can get notified as soon a VMA is split, this can help to relax the restriction. So I propose to allow having a custom close under the condition that a VMA cannot get split.
Signed-off-by: Richard Weinberger <richard@nod.at> --- fs/kernfs/file.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-)
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index 06b342d8462b..82b09e72acff 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -347,6 +347,38 @@ static void kernfs_vma_open(struct vm_area_struct *vma) kernfs_put_active(of->kn); } +static void kernfs_vma_close(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct kernfs_open_file *of = kernfs_of(file); + + if (!of->vm_ops) + return; + + if (!kernfs_get_active(of->kn)) + return; + + if (of->vm_ops->close) + of->vm_ops->close(vma); + + kernfs_put_active(of->kn); +} + +static int kernfs_vma_split(struct vm_area_struct *vma, unsigned long addr) +{ + struct file *file = vma->vm_file; + struct kernfs_open_file *of = kernfs_of(file); + + /* + * We cannot keep track of split operations, + * so refuse splitting a VMA if someone uses close. + */ + if (of->vm_ops && of->vm_ops->close) + return -EINVAL; + + return 0; +} + static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf) { struct file *file = vmf->vma->vm_file; @@ -457,6 +489,8 @@ static struct mempolicy *kernfs_vma_get_policy(struct vm_area_struct *vma, static const struct vm_operations_struct kernfs_vm_ops = { .open = kernfs_vma_open, + .close = kernfs_vma_close, + .split = kernfs_vma_split, .fault = kernfs_vma_fault, .page_mkwrite = kernfs_vma_page_mkwrite, .access = kernfs_vma_access, @@ -505,14 +539,6 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma) if (of->mmapped && of->vm_ops != vma->vm_ops) goto out_put; - /* - * It is not possible to successfully wrap close. - * So error if someone is trying to use close. - */ - rc = -EINVAL; - if (vma->vm_ops && vma->vm_ops->close) - goto out_put; - rc = 0; of->mmapped = true; of->vm_ops = vma->vm_ops; -- 2.26.2
| |