- 追加された行はこの色です。
- 削除された行はこの色です。
*参照元 [#u26fa5e1]
#backlinks
*説明 [#s33392ff]
-パス: [[linux-4.4.1/mm/mmap.c]]
-FIXME: これは何?
--説明
**引数 [#md56d548]
-struct file *file
--
--[[linux-4.4.1/file]]
-unsigned long addr
--
-unsigned long len
--
-unsigned long prot
--
-unsigned long flags
--
-vm_flags_t vm_flags
-
--[[linux-4.4.1/vm_flags_t]]
-unsigned long pgoff
--
-unsigned long *populate
--
**返り値 [#a7f2941d]
-unsigned long
--
**参考 [#dd70ae03]
*実装 [#b3e8556d]
/*
* The caller must hold down_write(¤t->mm->mmap_sem).
*/
unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, vm_flags_t vm_flags,
unsigned long pgoff, unsigned long *populate)
{
struct mm_struct *mm = current->mm;
-
--[[linux-4.4.1/mm_struct]]
--[[linux-4.4.1/current(global)]]
*populate = 0;
if (!len)
return -EINVAL;
/*
* Does the application expect PROT_READ to imply PROT_EXEC?
*
* (the exception is when the underlying filesystem is noexec
* mounted, in which case we dont add PROT_EXEC.)
*/
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
if (!(file && path_noexec(&file->f_path)))
prot |= PROT_EXEC;
-
--[[linux-4.4.1/PROT_READ]]
--[[linux-4.4.1/path_noexec()]]
--[[linux-4.4.1/PROT_EXEC]]
if (!(flags & MAP_FIXED))
addr = round_hint_to_min(addr);
-
--[[linux-4.4.1/MAP_FIXED]]
--[[linux-4.4.1/round_hint_to_min()]]
/* Careful about overflows.. */
len = PAGE_ALIGN(len);
if (!len)
return -ENOMEM;
-
--[[linux-4.4.1/PAGE_ALIGN()]]
/* offset overflow? */
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
return -EOVERFLOW;
/* Too many mappings? */
if (mm->map_count > sysctl_max_map_count)
return -ENOMEM;
/* Obtain the address to map to. we verify (or select) it and ensure
* that it represents a valid section of the address space.
*/
addr = get_unmapped_area(file, addr, len, pgoff, flags);
if (offset_in_page(addr))
return addr;
-
--[[linux-4.4.1/get_unmmapped_area()]]
--[[linux-4.4.1/offset_in_page()]]
/* Do simple checking here so the lower-level routines won't have
* to. we assume access permissions have been handled by the open
* of the memory object, so we don't do any here.
*/
vm_flags |= calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
-
--[[linux-4.4.1/calc_vm_prot_bits()]]
--[[linux-4.4.1/calc_vm_flag_bis()]]
--[[linux-4.4.1/VM_MAYREAD]]
--[[linux-4.4.1/VM_MAYWRITE]]
--[[linux-4.4.1/VM_MAY_EXEC]]
if (flags & MAP_LOCKED)
if (!can_do_mlock())
return -EPERM;
-
--[[linux-4.4.1/MAP_LOCKED]]
--[[linux-4.4.1/can_do_mlock()]]
if (mlock_future_check(mm, vm_flags, len))
return -EAGAIN;
-
--[[linux-4.4.1/mlock_future_check()]]
if (file) {
struct inode *inode = file_inode(file);
-
--[[linux-4.4.1/inode]]
--[[linux-4.4.1/file_inode()]]
switch (flags & MAP_TYPE) {
case MAP_SHARED:
if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE))
return -EACCES;
/*
* Make sure we don't allow writing to an append-only
* file..
*/
if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE))
return -EACCES;
-
--[[linux-4.4.1/IS_APPEND()]]
/*
* Make sure there are no mandatory locks on the file.
*/
if (locks_verify_locked(file))
return -EAGAIN;
-
--[[linux-4.4.1/locks_verify_locked()]]
vm_flags |= VM_SHARED | VM_MAYSHARE;
if (!(file->f_mode & FMODE_WRITE))
vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
/* fall through */
case MAP_PRIVATE:
if (!(file->f_mode & FMODE_READ))
return -EACCES;
if (path_noexec(&file->f_path)) {
if (vm_flags & VM_EXEC)
return -EPERM;
vm_flags &= ~VM_MAYEXEC;
}
if (!file->f_op->mmap)
return -ENODEV;
if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
return -EINVAL;
break;
default:
return -EINVAL;
}
} else {
switch (flags & MAP_TYPE) {
case MAP_SHARED:
if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
return -EINVAL;
/*
* Ignore pgoff.
*/
pgoff = 0;
vm_flags |= VM_SHARED | VM_MAYSHARE;
break;
case MAP_PRIVATE:
/*
* Set pgoff according to addr for anon_vma.
*/
pgoff = addr >> PAGE_SHIFT;
break;
default:
return -EINVAL;
}
}
/*
* Set 'VM_NORESERVE' if we should not account for the
* memory use of this mapping.
*/
if (flags & MAP_NORESERVE) {
/* We honor MAP_NORESERVE if allowed to overcommit */
if (sysctl_overcommit_memory != OVERCOMMIT_NEVER)
vm_flags |= VM_NORESERVE;
-
--[[linux-4.4.1/sysctl_overcommit_memory(global)]]
--[[linux-4.4.1/OVERCOMMIT_NEVER]]
--[[linux-4.4.1/VM_NORESERVE]]
/* hugetlb applies strict overcommit unless MAP_NORESERVE */
if (file && is_file_hugepages(file))
vm_flags |= VM_NORESERVE;
}
addr = mmap_region(file, addr, len, vm_flags, pgoff);
-
--[[linux-4.4.1/mmap_region()]]
if (!IS_ERR_VALUE(addr) &&
((vm_flags & VM_LOCKED) ||
(flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE))
*populate = len;
return addr;
}
*コメント [#m8ce7d4f]