*参照元 [#cc520445]
#backlinks

*説明 [#b741f145]
-パス: [[linux-2.6.33/mm/mmap.c]]

-FIXME: これは何?
--説明


**引数 [#ue41253b]
-struct file *file
--
--[[linux-2.6.33/file]]
-unsigned long addr
--
-unsigned long len
--
-unsigned long flags
--
-unsigned int vm_flags
--
-unsigned long pgoff
--


**返り値 [#w4132174]
-long
-unsigned long
--


**参考 [#a1dae6d1]


*実装 [#t5cc2978]
 unsigned long mmap_region(struct file *file, unsigned long addr,
 			  unsigned long len, unsigned long flags,
 			  unsigned int vm_flags, unsigned long pgoff)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma, *prev;
 	int correct_wcount = 0;
 	int error;
 	struct rb_node **rb_link, *rb_parent;
 	unsigned long charged = 0;
 	struct inode *inode =  file ? file->f_path.dentry->d_inode : NULL;
 
-
--[[linux-2.6.33/current(global)]]
--[[linux-2.6.33/mm_struct]]
--[[linux-2.6.33/vm_area_struct]]
--[[linux-2.6.33/rb_node]]
--[[linux-2.6.33/inode]]

 	/* Clear old maps */
 	error = -ENOMEM;
-
--[[linux-2.6.33/ENOMEM]]

 munmap_back:
 	vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
 	if (vma && vma->vm_start < addr + len) {
 		if (do_munmap(mm, addr, len))
 			return -ENOMEM;
 		goto munmap_back;
 	}
 
-
--[[linux-2.6.33/find_vma_prepare()]]
--[[linux-2.6.33/do_munmap()]]

 	/* Check against address space limit. */
 	if (!may_expand_vm(mm, len >> PAGE_SHIFT))
 		return -ENOMEM;
 
-
--[[linux-2.6.33/may_expand_vm()]]
--[[linux-2.6.33/PAGE_SHIFT]]

 	/*
 	 * 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;
 
 		/* hugetlb applies strict overcommit unless MAP_NORESERVE */
 		if (file && is_file_hugepages(file))
 			vm_flags |= VM_NORESERVE;
 	}
 
-
--[[linux-2.6.33/MAP_NORESERVE]]
--[[linux-2.6.33/sysctl_overcommit_memory(global)]]
--[[linux-2.6.33/OVERCOMMIT_NEVER]]
--[[linux-2.6.33/VM_NORESERVE]]
--[[linux-2.6.33/is_file_hugepages()]]

 	/*
 	 * Private writable mapping: check memory availability
 	 */
 	if (accountable_mapping(file, vm_flags)) {
 		charged = len >> PAGE_SHIFT;
 		if (security_vm_enough_memory(charged))
 			return -ENOMEM;
 		vm_flags |= VM_ACCOUNT;
 	}
 
-
--[[linux-2.6.33/accountable_mapping()]]
--[[linux-2.6.33/security_vm_enough_memory()]]
--[[linux-2.6.33/VM_ACCOUNT]]

 	/*
 	 * Can we just expand an old mapping?
 	 */
 	vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, NULL);
 	if (vma)
 		goto out;
 
-
--[[linux-2.6.33/vma_merge()]]

 	/*
 	 * Determine the object being mapped and call the appropriate
 	 * specific mapper. the address has already been validated, but
 	 * not unmapped, but the maps are removed from the list.
 	 */
 	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (!vma) {
 		error = -ENOMEM;
 		goto unacct_error;
 	}
 
-
--[[linux-2.6.33/kmem_cache_zalloc()]]
--[[linux-2.6.33/vm_area_cachep(global)]]
--[[linux-2.6.33/GFP_KERNEL]]

 	vma->vm_mm = mm;
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
 	vma->vm_flags = vm_flags;
 	vma->vm_page_prot = vm_get_page_prot(vm_flags);
 	vma->vm_pgoff = pgoff;
 
-
--[[linux-2.6.33/vm_get_page_prot()]]

 	if (file) {
 		error = -EINVAL;
 		if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
 			goto free_vma;
 		if (vm_flags & VM_DENYWRITE) {
 			error = deny_write_access(file);
 			if (error)
 				goto free_vma;
 			correct_wcount = 1;
 		}
-
--[[linux-2.6.33/VM_GROWSDOWN]]
--[[linux-2.6.33/VM_GROWSUP]]
--[[linux-2.6.33/VM_DENYWRITE]]
--[[linux-2.6.33/deny_write_access()]]

 		vma->vm_file = file;
 		get_file(file);
 		error = file->f_op->mmap(file, vma);
 		if (error)
 			goto unmap_and_free_vma;
 		if (vm_flags & VM_EXECUTABLE)
 			added_exe_file_vma(mm);
 
-
--[[linux-2.6.33/get_file()]]
--[[linux-2.6.33/VM_EXECUTABLE]]
--[[linux-2.6.33/added_exe_file_vma()]]

 		/* Can addr have changed??
 		 *
 		 * Answer: Yes, several device drivers can do it in their
 		 *         f_op->mmap method. -DaveM
 		 */
 		addr = vma->vm_start;
 		pgoff = vma->vm_pgoff;
 		vm_flags = vma->vm_flags;
 	} else if (vm_flags & VM_SHARED) {
 		error = shmem_zero_setup(vma);
 		if (error)
 			goto free_vma;
-
--[[linux-2.6.33/VM_SHARED]]
--[[linux-2.6.33/shmem_zero_setup()]]

 	}
 
 	if (vma_wants_writenotify(vma)) {
 		pgprot_t pprot = vma->vm_page_prot;
 
 		/* Can vma->vm_page_prot have changed??
 		 *
 		 * Answer: Yes, drivers may have changed it in their
 		 *         f_op->mmap method.
 		 *
 		 * Ensures that vmas marked as uncached stay that way.
 		 */
 		vma->vm_page_prot = vm_get_page_prot(vm_flags & ~VM_SHARED);
 		if (pgprot_val(pprot) == pgprot_val(pgprot_noncached(pprot)))
 			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
--[[linux-2.6.33/pgprot_t]]
--[[linux-2.6.33/vm_get_page_prot()]]
--[[linux-2.6.33/pgprot_val()]]
--[[linux-2.6.33/pgprot_noncached()]]

 	}
 
 	vma_link(mm, vma, prev, rb_link, rb_parent);
 	file = vma->vm_file;
 
-
--[[linux-2.6.33/vma_link()]]

 	/* Once vma denies write, undo our temporary denial count */
 	if (correct_wcount)
 		atomic_inc(&inode->i_writecount);
-
--[[linux-2.6.33/atomic_inc()]]

 out:
 	perf_event_mmap(vma);
 
-
--[[linux-2.6.33/perf_event_mmap()]]

 	mm->total_vm += len >> PAGE_SHIFT;
 	vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
-
--[[linux-2.6.33/vm_stat_account()]]

 	if (vm_flags & VM_LOCKED) {
 		/*
 		 * makes pages present; downgrades, drops, reacquires mmap_sem
 		 */
 		long nr_pages = mlock_vma_pages_range(vma, addr, addr + len);
 		if (nr_pages < 0)
 			return nr_pages;	/* vma gone! */
 		mm->locked_vm += (len >> PAGE_SHIFT) - nr_pages;
 	} else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
 		make_pages_present(addr, addr + len);
 	return addr;
 
-
--[[linux-2.6.33/VM_LOCKED]]
--[[linux-2.6.33/mlock_vma_pages_range()]]
--[[linux-2.6.33/MAP_POPULATE]]
--[[linux-2.6.33/MAP_NONBLOCK]]
--[[linux-2.6.33/make_pages_present()]]

 unmap_and_free_vma:
 	if (correct_wcount)
 		atomic_inc(&inode->i_writecount);
 	vma->vm_file = NULL;
 	fput(file);
 
-
--[[linux-2.6.33/fput()]]

 	/* Undo any partial mapping done by a device driver. */
 	unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
 	charged = 0;
-
--[[linux-2.6.33/unmap_region()]]

 free_vma:
 	kmem_cache_free(vm_area_cachep, vma);
-
--[[linux-2.6.33/kmem_cache_free()]]

 unacct_error:
 	if (charged)
 		vm_unacct_memory(charged);
 	return error;
-
--[[linux-2.6.33/vm_unacct_memory()]]

 }


*コメント [#te4ca810]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS