Commit eec3636a authored by Jane Chu's avatar Jane Chu Committed by Linus Torvalds

ipc/shm.c add ->pagesize function to shm_vm_ops

Commit 05ea8860 ("mm, hugetlbfs: introduce ->pagesize() to
vm_operations_struct") adds a new ->pagesize() function to
hugetlb_vm_ops, intended to cover all hugetlbfs backed files.

With System V shared memory model, if "huge page" is specified, the
"shared memory" is backed by hugetlbfs files, but the mappings initiated
via shmget/shmat have their original vm_ops overwritten with shm_vm_ops,
so we need to add a ->pagesize function to shm_vm_ops.  Otherwise,
vma_kernel_pagesize() returns PAGE_SIZE given a hugetlbfs backed vma,
result in below BUG:

  fs/hugetlbfs/inode.c
        443             if (unlikely(page_mapped(page))) {
        444                     BUG_ON(truncate_op);

resulting in

  hugetlbfs: oracle (4592): Using mlock ulimits for SHM_HUGETLB is deprecated
  ------------[ cut here ]------------
  kernel BUG at fs/hugetlbfs/inode.c:444!
  Modules linked in: nfsv3 rpcsec_gss_krb5 nfsv4 ...
  CPU: 35 PID: 5583 Comm: oracle_5583_sbt Not tainted 4.14.35-1829.el7uek.x86_64 #2
  RIP: 0010:remove_inode_hugepages+0x3db/0x3e2
  ....
  Call Trace:
    hugetlbfs_evict_inode+0x1e/0x3e
    evict+0xdb/0x1af
    iput+0x1a2/0x1f7
    dentry_unlink_inode+0xc6/0xf0
    __dentry_kill+0xd8/0x18d
    dput+0x1b5/0x1ed
    __fput+0x18b/0x216
    ____fput+0xe/0x10
    task_work_run+0x90/0xa7
    exit_to_usermode_loop+0xdd/0x116
    do_syscall_64+0x187/0x1ae
    entry_SYSCALL_64_after_hwframe+0x150/0x0

[jane.chu@oracle.com: relocate comment]
  Link: http://lkml.kernel.org/r/20180731044831.26036-1-jane.chu@oracle.com
Link: http://lkml.kernel.org/r/20180727211727.5020-1-jane.chu@oracle.com
Fixes: 05ea8860 ("mm, hugetlbfs: introduce ->pagesize() to vm_operations_struct")
Signed-off-by: default avatarJane Chu <jane.chu@oracle.com>
Suggested-by: default avatarMike Kravetz <mike.kravetz@oracle.com>
Reviewed-by: default avatarMike Kravetz <mike.kravetz@oracle.com>
Acked-by: default avatarDavidlohr Bueso <dave@stgolabs.net>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jérôme Glisse <jglisse@redhat.com>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7e97de0b
...@@ -427,6 +427,17 @@ static int shm_split(struct vm_area_struct *vma, unsigned long addr) ...@@ -427,6 +427,17 @@ static int shm_split(struct vm_area_struct *vma, unsigned long addr)
return 0; return 0;
} }
static unsigned long shm_pagesize(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct shm_file_data *sfd = shm_file_data(file);
if (sfd->vm_ops->pagesize)
return sfd->vm_ops->pagesize(vma);
return PAGE_SIZE;
}
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
static int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new) static int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
{ {
...@@ -554,6 +565,7 @@ static const struct vm_operations_struct shm_vm_ops = { ...@@ -554,6 +565,7 @@ static const struct vm_operations_struct shm_vm_ops = {
.close = shm_close, /* callback for when the vm-area is released */ .close = shm_close, /* callback for when the vm-area is released */
.fault = shm_fault, .fault = shm_fault,
.split = shm_split, .split = shm_split,
.pagesize = shm_pagesize,
#if defined(CONFIG_NUMA) #if defined(CONFIG_NUMA)
.set_policy = shm_set_policy, .set_policy = shm_set_policy,
.get_policy = shm_get_policy, .get_policy = shm_get_policy,
......
...@@ -3167,6 +3167,13 @@ static vm_fault_t hugetlb_vm_op_fault(struct vm_fault *vmf) ...@@ -3167,6 +3167,13 @@ static vm_fault_t hugetlb_vm_op_fault(struct vm_fault *vmf)
return 0; return 0;
} }
/*
* When a new function is introduced to vm_operations_struct and added
* to hugetlb_vm_ops, please consider adding the function to shm_vm_ops.
* This is because under System V memory model, mappings created via
* shmget/shmat with "huge page" specified are backed by hugetlbfs files,
* their original vm_ops are overwritten with shm_vm_ops.
*/
const struct vm_operations_struct hugetlb_vm_ops = { const struct vm_operations_struct hugetlb_vm_ops = {
.fault = hugetlb_vm_op_fault, .fault = hugetlb_vm_op_fault,
.open = hugetlb_vm_op_open, .open = hugetlb_vm_op_open,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment