home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / nfs / mmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  3.7 KB  |  157 lines

  1. /*
  2.  *    fs/nfs/mmap.c    by Jon Tombs 15 Aug 1993
  3.  *
  4.  * This code is from
  5.  *    linux/mm/mmap.c which was written by obz, Linus and Eric
  6.  * and
  7.  *    linux/mm/memory.c  by Linus Torvalds and others
  8.  *
  9.  *    Copyright (C) 1993
  10.  *
  11.  */
  12. #include <linux/stat.h>
  13. #include <linux/sched.h>
  14. #include <linux/kernel.h>
  15. #include <linux/mm.h>
  16. #include <linux/shm.h>
  17. #include <linux/errno.h>
  18. #include <linux/mman.h>
  19. #include <linux/string.h>
  20. #include <linux/malloc.h>
  21. #include <linux/nfs_fs.h>
  22.  
  23. #include <asm/segment.h>
  24. #include <asm/system.h>
  25.  
  26. extern int share_page(struct vm_area_struct * area, struct task_struct * tsk,
  27.     struct inode * inode, unsigned long address, unsigned long error_code,
  28.     unsigned long newpage);
  29.  
  30. extern unsigned long put_page(struct task_struct * tsk,unsigned long page,
  31.     unsigned long address,int prot);
  32.  
  33. static void nfs_file_mmap_nopage(int error_code, struct vm_area_struct * area,
  34.                 unsigned long address);
  35.  
  36. extern void file_mmap_free(struct vm_area_struct * area);
  37. extern int file_mmap_share(struct vm_area_struct * from, struct vm_area_struct * to,
  38.                 unsigned long address);
  39.  
  40. struct vm_operations_struct nfs_file_mmap = {
  41.     NULL,            /* open */
  42.     file_mmap_free,        /* close */
  43.     nfs_file_mmap_nopage,    /* nopage */
  44.     NULL,            /* wppage */
  45.     file_mmap_share,    /* share */
  46.     NULL,            /* unmap */
  47. };
  48.  
  49.  
  50. /* This is used for a general mmap of a nfs file */
  51. int nfs_mmap(struct inode * inode, struct file * file,
  52.     unsigned long addr, size_t len, int prot, unsigned long off)
  53. {
  54.     struct vm_area_struct * mpnt;
  55.  
  56.     if (prot & PAGE_RW)    /* only PAGE_COW or read-only supported now */
  57.         return -EINVAL;
  58.     if (off & (inode->i_sb->s_blocksize - 1))
  59.         return -EINVAL;
  60.     if (!inode->i_sb || !S_ISREG(inode->i_mode))
  61.         return -EACCES;
  62.     if (!IS_RDONLY(inode)) {
  63.         inode->i_atime = CURRENT_TIME;
  64.         inode->i_dirt = 1;
  65.     }
  66.  
  67.     mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
  68.     if (!mpnt)
  69.         return -ENOMEM;
  70.  
  71.     unmap_page_range(addr, len);
  72.     mpnt->vm_task = current;
  73.     mpnt->vm_start = addr;
  74.     mpnt->vm_end = addr + len;
  75.     mpnt->vm_page_prot = prot;
  76.     mpnt->vm_share = NULL;
  77.     mpnt->vm_inode = inode;
  78.     inode->i_count++;
  79.     mpnt->vm_offset = off;
  80.     mpnt->vm_ops = &nfs_file_mmap;
  81.     insert_vm_struct(current, mpnt);
  82.     merge_segments(current->mmap, NULL, NULL);
  83.     return 0;
  84. }
  85.  
  86.  
  87. static void nfs_file_mmap_nopage(int error_code, struct vm_area_struct * area,
  88.                 unsigned long address)
  89. {
  90.     struct inode * inode = area->vm_inode;
  91.     unsigned int clear;
  92.     unsigned long page;
  93.     unsigned long tmp;
  94.     int n;
  95.     int i;
  96.     int pos;
  97.     struct nfs_fattr fattr;
  98.  
  99.     address &= PAGE_MASK;
  100.     pos = address - area->vm_start + area->vm_offset;
  101.  
  102.     page = get_free_page(GFP_KERNEL);
  103.     if (share_page(area, area->vm_task, inode, address, error_code, page)) {
  104.         ++area->vm_task->min_flt;
  105.         return;
  106.     }
  107.  
  108.     ++area->vm_task->maj_flt;
  109.     if (!page) {
  110.         oom(current);
  111.         put_page(area->vm_task, BAD_PAGE, address, PAGE_PRIVATE);
  112.         return;
  113.     }
  114.  
  115.     clear = 0;
  116.     if (address + PAGE_SIZE > area->vm_end) {
  117.         clear = address + PAGE_SIZE - area->vm_end;
  118.     }
  119.  
  120.     n = NFS_SERVER(inode)->rsize; /* what we can read in one go */
  121.  
  122.     for (i = 0; i < (PAGE_SIZE - clear); i += n) {
  123.         int hunk, result;
  124.  
  125.         hunk = PAGE_SIZE - i;
  126.         if (hunk > n)
  127.             hunk = n;
  128.         result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
  129.             pos, hunk, (char *) (page + i), &fattr);
  130.         if (result < 0)
  131.             break;
  132.         pos += result;
  133.         if (result < n) {
  134.             i += result;
  135.             break;
  136.         }
  137.     }
  138.  
  139. #ifdef doweneedthishere
  140.     nfs_refresh_inode(inode, &fattr);
  141. #endif
  142.  
  143.     if (!(error_code & PAGE_RW)) {
  144.         if (share_page(area, area->vm_task, inode, address, error_code, page))
  145.             return;
  146.     }
  147.  
  148.     tmp = page + PAGE_SIZE;
  149.     while (clear--) {
  150.         *(char *)--tmp = 0;
  151.     }
  152.     if (put_page(area->vm_task,page,address,area->vm_page_prot))
  153.         return;
  154.     free_page(page);
  155.     oom(current);
  156. }
  157.