/[lkdp]/lkdp/mm/process.tex
ViewVC logotype

Diff of /lkdp/mm/process.tex

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.8 by nayaniabhishek, Sat Jun 15 10:24:52 2002 UTC revision 1.9 by nayaniabhishek, Tue Jun 18 07:18:34 2002 UTC
# Line 616  fail_nomem: Line 616  fail_nomem:
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    
# Line 636  out: Line 643  out:
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;
# Line 648  out: Line 655  out:
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;
# Line 662  out: Line 677  out:
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.
# Line 670  out: Line 689  out:
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
# Line 678  out: Line 701  out:
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;
# Line 686  out: Line 713  out:
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:
# Line 705  out: Line 736  out:
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))
# Line 714  out: Line 755  out:
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) {
# Line 726  out: Line 772  out:
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:
# Line 736  munmap_back: Line 786  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.
# Line 760  munmap_back: Line 826  munmap_back:
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;
# Line 771  munmap_back: Line 841  munmap_back:
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
# Line 805  munmap_back: Line 899  munmap_back:
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.
# Line 835  out: Line 930  out:
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);
# Line 843  unmap_and_free_vma: Line 942  unmap_and_free_vma:
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;

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26