616 |
|
|
617 |
if ((offset + PAGE_ALIGN(len)) < offset) |
if ((offset + PAGE_ALIGN(len)) < offset) |
618 |
goto out; |
goto out; |
619 |
|
|
620 |
|
\end{verbatim} |
621 |
|
We check for an overflow. |
622 |
|
\begin{verbatim} |
623 |
|
|
624 |
if (!(offset & ~PAGE_MASK)) |
if (!(offset & ~PAGE_MASK)) |
625 |
ret = do_mmap_pgoff(file, addr, len, prot, |
ret = do_mmap_pgoff(file, addr, len, prot, |
626 |
flag, offset >> PAGE_SHIFT); |
flag, offset >> PAGE_SHIFT); |
627 |
out: |
out: |
628 |
return ret; |
return ret; |
629 |
\end{verbatim} |
\end{verbatim} |
630 |
|
After checking that the offset is page aligned, we call \texttt{do\_mmap\_pgoff()} to do the real work of allocating the VMA. |
631 |
|
|
632 |
|
|
633 |
|
|
634 |
|
|
643 |
unsigned long flags, |
unsigned long flags, |
644 |
unsigned long pgoff) |
unsigned long pgoff) |
645 |
\end{verbatim} |
\end{verbatim} |
646 |
|
This function does the actual work of creating a VMA. |
647 |
\begin{verbatim} |
\begin{verbatim} |
648 |
struct mm_struct * mm = current->mm; |
struct mm_struct * mm = current->mm; |
649 |
struct vm_area_struct * vma, * prev; |
struct vm_area_struct * vma, * prev; |
655 |
if (file && (!file->f_op || !file->f_op->mmap)) |
if (file && (!file->f_op || !file->f_op->mmap)) |
656 |
return -ENODEV; |
return -ENODEV; |
657 |
|
|
658 |
|
\end{verbatim} |
659 |
|
If we are trying to map a file, \textit{file}, $file\rightarrow{f\_op}$ and $file\rightarrow{f\_op}\rightarrow{mmap}$ should not be NULL. |
660 |
|
\begin{verbatim} |
661 |
|
|
662 |
if ((len = PAGE_ALIGN(len)) == 0) |
if ((len = PAGE_ALIGN(len)) == 0) |
663 |
return addr; |
return addr; |
664 |
|
|
665 |
if (len > TASK_SIZE) |
if (len > TASK_SIZE) |
666 |
return -EINVAL; |
return -EINVAL; |
667 |
|
|
668 |
|
\end{verbatim} |
669 |
|
If the size of the request is 0 or if it exceeds the maximum limit of the process which is 3GB, it just returns with the appropriate error value. |
670 |
|
\begin{verbatim} |
671 |
|
|
672 |
/* offset overflow? */ |
/* offset overflow? */ |
673 |
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff) |
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff) |
674 |
return -EINVAL; |
return -EINVAL; |
677 |
if (mm->map_count > max_map_count) |
if (mm->map_count > max_map_count) |
678 |
return -ENOMEM; |
return -ENOMEM; |
679 |
|
|
680 |
|
\end{verbatim} |
681 |
|
We check for an overflow and also see if we have not reached the limit of number of VMAs a process can have. The limit is currently 65536. |
682 |
|
\begin{verbatim} |
683 |
|
|
684 |
/* Obtain the address to map to. we verify |
/* Obtain the address to map to. we verify |
685 |
* (or select) it and ensure that it represents |
* (or select) it and ensure that it represents |
686 |
* a valid section of the address space. |
* a valid section of the address space. |
689 |
if (addr & ~PAGE_MASK) |
if (addr & ~PAGE_MASK) |
690 |
return addr; |
return addr; |
691 |
|
|
692 |
|
\end{verbatim} |
693 |
|
The function \texttt{get\_unmapped\_area()} returns the starting address of an unused address space big enough to hold the new memory region. |
694 |
|
\begin{verbatim} |
695 |
|
|
696 |
/* Do simple checking here so the lower-level |
/* Do simple checking here so the lower-level |
697 |
* routines won't have to. we assume access |
* routines won't have to. we assume access |
698 |
* permissions have been handled by the open |
* permissions have been handled by the open |
701 |
vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | |
vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | |
702 |
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; |
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; |
703 |
|
|
704 |
|
\end{verbatim} |
705 |
|
Then we get the new flags for the memory region by combining the \textit{prot} and \textit{flags} fields. |
706 |
|
\begin{verbatim} |
707 |
|
|
708 |
/* mlock MCL_FUTURE? */ |
/* mlock MCL_FUTURE? */ |
709 |
if (vm_flags & VM_LOCKED) { |
if (vm_flags & VM_LOCKED) { |
710 |
unsigned long locked = mm->locked_vm << PAGE_SHIFT; |
unsigned long locked = mm->locked_vm << PAGE_SHIFT; |
713 |
return -EAGAIN; |
return -EAGAIN; |
714 |
} |
} |
715 |
|
|
716 |
|
\end{verbatim} |
717 |
|
If one of the flags happens to be VM\_LOCKED, then we check whether we are within the limit on the number of locked pages. As previously mentioned, $mm\rightarrow{locked\_vm}$ gives the number of pages already locked. So the above expression first converts it into the number of bytes and then adds it to \textit{len}, thereby giving the total number of pages that are going to be locked. By default, the limit is infinity. |
718 |
|
\begin{verbatim} |
719 |
|
|
720 |
if (file) { |
if (file) { |
721 |
switch (flags & MAP_TYPE) { |
switch (flags & MAP_TYPE) { |
722 |
case MAP_SHARED: |
case MAP_SHARED: |
736 |
if (!(file->f_mode & FMODE_WRITE)) |
if (!(file->f_mode & FMODE_WRITE)) |
737 |
vm_flags &= ~(VM_MAYWRITE | VM_SHARED); |
vm_flags &= ~(VM_MAYWRITE | VM_SHARED); |
738 |
|
|
739 |
|
\end{verbatim} |
740 |
|
If we are mapping a file and its a shared mapping, then we check for the following conditions: |
741 |
|
\begin{enumerate} |
742 |
|
\item If the pages in the mapping can be written to, but the file was opened in read-only mode, return with an access error. |
743 |
|
\item The comment says it all. We cannot write to a file that is opened in O\_APPEND mode. |
744 |
|
\item If there is a lock on the file, then return and let the user try again later. |
745 |
|
\item Set the flags VM\_SHARED and VM\_MAYSHARE. Then if the file is read-only, the flags VM\_MAYWRITE and VM\_SHARED are reset. |
746 |
|
\end{enumerate} |
747 |
|
\begin{verbatim} |
748 |
|
|
749 |
/* fall through */ |
/* fall through */ |
750 |
case MAP_PRIVATE: |
case MAP_PRIVATE: |
751 |
if (!(file->f_mode & FMODE_READ)) |
if (!(file->f_mode & FMODE_READ)) |
755 |
default: |
default: |
756 |
return -EINVAL; |
return -EINVAL; |
757 |
} |
} |
758 |
|
|
759 |
|
\end{verbatim} |
760 |
|
We cannot map a file privately which is not opened in read-only mode. So we just return an "Access Denied". The default action is to return the error "Invalid Value". |
761 |
|
\begin{verbatim} |
762 |
|
|
763 |
} else { |
} else { |
764 |
vm_flags |= VM_SHARED | VM_MAYSHARE; |
vm_flags |= VM_SHARED | VM_MAYSHARE; |
765 |
switch (flags & MAP_TYPE) { |
switch (flags & MAP_TYPE) { |
772 |
break; |
break; |
773 |
} |
} |
774 |
} |
} |
775 |
|
|
776 |
|
\end{verbatim} |
777 |
|
If we are not mapping a file, set the flags VM\_SHARED and VM\_MAYSHARE. Then if its a private mapping, we reset the flags which were set above else if it is a shared mapping, we do nothing as the correct flags were already set. |
778 |
|
\begin{verbatim} |
779 |
|
|
780 |
/* Clear old maps */ |
/* Clear old maps */ |
781 |
munmap_back: |
munmap_back: |
786 |
goto munmap_back; |
goto munmap_back; |
787 |
} |
} |
788 |
|
|
789 |
|
\end{verbatim} |
790 |
|
xxx |
791 |
|
\begin{verbatim} |
792 |
|
|
793 |
/* Check against address space limit. */ |
/* Check against address space limit. */ |
794 |
if ((mm->total_vm << PAGE_SHIFT) + len |
if ((mm->total_vm << PAGE_SHIFT) + len |
795 |
> current->rlim[RLIMIT_AS].rlim_cur) |
> current->rlim[RLIMIT_AS].rlim_cur) |
796 |
return -ENOMEM; |
return -ENOMEM; |
797 |
|
|
798 |
|
\end{verbatim} |
799 |
|
xxx |
800 |
|
\begin{verbatim} |
801 |
|
|
802 |
/* Private writable mapping? Check memory availability.. */ |
/* Private writable mapping? Check memory availability.. */ |
803 |
if ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE && |
if ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE && |
804 |
!(flags & MAP_NORESERVE) && |
!(flags & MAP_NORESERVE) && |
805 |
!vm_enough_memory(len >> PAGE_SHIFT)) |
!vm_enough_memory(len >> PAGE_SHIFT)) |
806 |
return -ENOMEM; |
return -ENOMEM; |
807 |
|
|
808 |
|
\end{verbatim} |
809 |
|
xxx |
810 |
|
\begin{verbatim} |
811 |
|
|
812 |
/* Can we just expand an old anonymous mapping? */ |
/* Can we just expand an old anonymous mapping? */ |
813 |
if (!file && !(vm_flags & VM_SHARED) && rb_parent) |
if (!file && !(vm_flags & VM_SHARED) && rb_parent) |
814 |
if (vma_merge(mm, prev, rb_parent, addr, addr + len, vm_flags)) |
if (vma_merge(mm, prev, rb_parent, addr, addr + len, vm_flags)) |
815 |
goto out; |
goto out; |
816 |
|
|
817 |
|
\end{verbatim} |
818 |
|
xxx |
819 |
|
\begin{verbatim} |
820 |
|
|
821 |
/* Determine the object being mapped and call the appropriate |
/* Determine the object being mapped and call the appropriate |
822 |
* specific mapper. the address has already been validated, but |
* specific mapper. the address has already been validated, but |
823 |
* not unmapped, but the maps are removed from the list. |
* not unmapped, but the maps are removed from the list. |
826 |
if (!vma) |
if (!vma) |
827 |
return -ENOMEM; |
return -ENOMEM; |
828 |
|
|
829 |
|
\end{verbatim} |
830 |
|
xxx |
831 |
|
\begin{verbatim} |
832 |
|
|
833 |
vma->vm_mm = mm; |
vma->vm_mm = mm; |
834 |
vma->vm_start = addr; |
vma->vm_start = addr; |
835 |
vma->vm_end = addr + len; |
vma->vm_end = addr + len; |
841 |
vma->vm_private_data = NULL; |
vma->vm_private_data = NULL; |
842 |
vma->vm_raend = 0; |
vma->vm_raend = 0; |
843 |
|
|
844 |
|
\end{verbatim} |
845 |
|
xxx |
846 |
|
\begin{verbatim} |
847 |
|
|
848 |
if (file) { |
if (file) { |
849 |
error = -EINVAL; |
error = -EINVAL; |
850 |
if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) |
if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) |
851 |
goto free_vma; |
goto free_vma; |
852 |
|
|
853 |
|
\end{verbatim} |
854 |
|
xxx |
855 |
|
\begin{verbatim} |
856 |
|
|
857 |
if (vm_flags & VM_DENYWRITE) { |
if (vm_flags & VM_DENYWRITE) { |
858 |
error = deny_write_access(file); |
error = deny_write_access(file); |
859 |
if (error) |
if (error) |
860 |
goto free_vma; |
goto free_vma; |
861 |
correct_wcount = 1; |
correct_wcount = 1; |
862 |
} |
} |
863 |
|
|
864 |
|
\end{verbatim} |
865 |
|
xxx |
866 |
|
\begin{verbatim} |
867 |
|
|
868 |
vma->vm_file = file; |
vma->vm_file = file; |
869 |
get_file(file); |
get_file(file); |
870 |
error = file->f_op->mmap(file, vma); |
error = file->f_op->mmap(file, vma); |
871 |
if (error) |
if (error) |
872 |
goto unmap_and_free_vma; |
goto unmap_and_free_vma; |
873 |
|
|
874 |
|
\end{verbatim} |
875 |
|
xxx |
876 |
|
\begin{verbatim} |
877 |
|
|
878 |
} else if (flags & MAP_SHARED) { |
} else if (flags & MAP_SHARED) { |
879 |
error = shmem_zero_setup(vma); |
error = shmem_zero_setup(vma); |
880 |
if (error) |
if (error) |
881 |
goto free_vma; |
goto free_vma; |
882 |
} |
} |
883 |
|
|
884 |
|
\end{verbatim} |
885 |
|
xxx |
886 |
|
\begin{verbatim} |
887 |
|
|
888 |
/* Can addr have changed?? |
/* Can addr have changed?? |
889 |
* |
* |
890 |
* Answer: Yes, several device drivers can do it in their |
* Answer: Yes, several device drivers can do it in their |
891 |
* f_op->mmap method. -DaveM |
* f_op->mmap method. -DaveM |
892 |
*/ |
*/ |
893 |
if (addr != vma->vm_start) { |
if (addr != vma->vm_start) { |
894 |
|
|
895 |
/* |
/* |
896 |
* It is a bit too late to pretend changing the virtual |
* It is a bit too late to pretend changing the virtual |
897 |
* area of the mapping, we just corrupted userspace |
* area of the mapping, we just corrupted userspace |
899 |
* the driver API). |
* the driver API). |
900 |
*/ |
*/ |
901 |
struct vm_area_struct * stale_vma; |
struct vm_area_struct * stale_vma; |
902 |
|
|
903 |
/* Since addr changed, we rely on the mmap op to prevent |
/* Since addr changed, we rely on the mmap op to prevent |
904 |
* collisions with existing vmas and just use find_vma_prepare |
* collisions with existing vmas and just use find_vma_prepare |
905 |
* to update the tree pointers. |
* to update the tree pointers. |
930 |
} |
} |
931 |
return addr; |
return addr; |
932 |
|
|
933 |
|
\end{verbatim} |
934 |
|
xxx |
935 |
|
\begin{verbatim} |
936 |
|
|
937 |
unmap_and_free_vma: |
unmap_and_free_vma: |
938 |
if (correct_wcount) |
if (correct_wcount) |
939 |
atomic_inc(&file->f_dentry->d_inode->i_writecount); |
atomic_inc(&file->f_dentry->d_inode->i_writecount); |
942 |
|
|
943 |
/* Undo any partial mapping done by a device driver. */ |
/* Undo any partial mapping done by a device driver. */ |
944 |
zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start); |
zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start); |
945 |
|
|
946 |
|
\end{verbatim} |
947 |
|
xxx |
948 |
|
\begin{verbatim} |
949 |
|
|
950 |
free_vma: |
free_vma: |
951 |
kmem_cache_free(vm_area_cachep, vma); |
kmem_cache_free(vm_area_cachep, vma); |
952 |
return error; |
return error; |