*参照元 [#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]