From patchwork Thu Feb 16 14:31:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Rados=C5=82aw_Smogura?= X-Patchwork-Id: 141697 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 8F964B6EE6 for ; Fri, 17 Feb 2012 08:18:41 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755888Ab2BPVSj (ORCPT ); Thu, 16 Feb 2012 16:18:39 -0500 Received: from flawless.hostnac.com ([67.23.244.186]:41001 "EHLO flawless.hostnac.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755885Ab2BPVSj (ORCPT ); Thu, 16 Feb 2012 16:18:39 -0500 Received: from [80.48.234.131] (port=51897 helo=radek_samsung.prointegra.corp) by flawless.hostnac.com with esmtpa (Exim 4.69) (envelope-from ) id 1Ry2OE-0003k0-ER; Thu, 16 Feb 2012 09:32:54 -0500 From: =?UTF-8?q?Rados=C5=82aw=20Smogura?= To: linux-mm@kvack.org Cc: Yongqiang Yang , mail@smogura.eu, linux-ext4@vger.kernel.org Subject: [PATCH 09/18] Allowing usage of MAP_HUGETLB in mmap Date: Thu, 16 Feb 2012 15:31:36 +0100 Message-Id: <1329402705-25454-9-git-send-email-mail@smogura.eu> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1329402705-25454-1-git-send-email-mail@smogura.eu> References: <1329402705-25454-1-git-send-email-mail@smogura.eu> MIME-Version: 1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - flawless.hostnac.com X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - smogura.eu Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Patch adds support for mapping file with MAP_HUGETLB and does checks if filesystem supports huge page cache. Signed-off-by: Radosław Smogura --- mm/mmap.c | 24 +++++++++++++++- mm/shmem.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 3f758c7..19f3016 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -992,6 +992,12 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + if (flags & MAP_HUGETLB) { + vm_flags &= ~VM_NOHUGEPAGE; + vm_flags |= VM_HUGEPAGE; + printk(KERN_INFO "Setted huge page mapping in do_mmap_pgoff."); + } + if (flags & MAP_LOCKED) if (!can_do_mlock()) return -EPERM; @@ -1086,11 +1092,25 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, if (!(flags & MAP_ANONYMOUS)) { audit_mmap_fd(fd, flags); - if (unlikely(flags & MAP_HUGETLB)) - return -EINVAL; file = fget(fd); if (!file) goto out; + + if (unlikely(flags & MAP_HUGETLB)) { +#ifdef CONFIG_HUGEPAGECACHE + if (!(file->f_mapping->a_ops->defragpage)) { + fput(file); + retval = -EINVAL; + goto out; + } else { + printk(KERN_INFO "Called to mmap huge with" + " good fs type.\n"); + } +#else + fput(file); + return -EINVAL; +#endif + } } else if (flags & MAP_HUGETLB) { struct user_struct *user = NULL; /* diff --git a/mm/shmem.c b/mm/shmem.c index 269d049..a834488 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1065,6 +1065,90 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return ret; } +static int shmem_fault_huge(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; + int error; + int ret = VM_FAULT_LOCKED; + + error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret); + if (error) + return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); + + /* Just portion of developer code, to force defragmentation, as we have + * no external interface to make defragmentation (or daemon to do it). + */ + if ((vma->vm_flags & VM_HUGEPAGE) && !PageCompound(vmf->page)) { + /* Force defrag - mainly devo code */ + int defragResult; + const loff_t hugeChunkSize = 1 << (PMD_SHIFT - PAGE_SHIFT); + + const loff_t vmaSizeToMap = (vma->vm_start + + ((vmf->pgoff + vma->vm_pgoff + hugeChunkSize) + << PAGE_SHIFT) <= vma->vm_end) ? + hugeChunkSize : 0; + + const loff_t inodeSizeToMap = + (vmf->pgoff + vma->vm_pgoff + hugeChunkSize < + inode->i_size) ? hugeChunkSize : 0; + + const struct defrag_pagecache_ctl defragControl = { + .fillPages = 1, + .requireFillPages = 1, + .force = 1 + }; + + if (ret & VM_FAULT_LOCKED) { + unlock_page(vmf->page); + } + put_page(vmf->page); + + defragResult = defragPageCache(vma->vm_file, + vmf->pgoff, + min(vmaSizeToMap, min(inodeSizeToMap, hugeChunkSize)), + &defragControl); + printk(KERN_INFO "Page defragmented with result %d\n", + defragResult); + + /* Retake page. */ + error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, + &ret); + if (error) { + return ((error == -ENOMEM) ? + VM_FAULT_OOM : VM_FAULT_SIGBUS); + } + } + + /* XXX Page & compound lock ordering please... */ + + /* After standard fault page is getted. */ + if (PageCompound(vmf->page)) { + compound_lock(vmf->page); + if (!PageHead(vmf->page)) { + compound_unlock(vmf->page); + goto no_hugepage; + } + }else { + goto no_hugepage; + } + + if (!(ret & VM_FAULT_LOCKED)) + lock_page(vmf->page); + + ret |= VM_FAULT_LOCKED; + + if (ret & VM_FAULT_MAJOR) { + count_vm_event(PGMAJFAULT); + mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); + } + return ret; +no_hugepage: + if (ret & VM_FAULT_LOCKED) + unlock_page(vmf->page); + page_cache_release(vmf->page); + vmf->page = NULL; + return VM_FAULT_NOHUGE; +} #ifdef CONFIG_NUMA static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *mpol) {