This source file includes following definitions.
- nfs_mmap
- nfs_file_mmap_nopage
1
2
3
4
5
6
7
8
9
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,
42 file_mmap_free,
43 nfs_file_mmap_nopage,
44 NULL,
45 file_mmap_share,
46 NULL,
47 };
48
49
50
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)
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_flags = 0;
77 mpnt->vm_share = NULL;
78 mpnt->vm_inode = inode;
79 inode->i_count++;
80 mpnt->vm_offset = off;
81 mpnt->vm_ops = &nfs_file_mmap;
82 insert_vm_struct(current, mpnt);
83 merge_segments(current->mm->mmap, NULL, NULL);
84 return 0;
85 }
86
87
88 static void nfs_file_mmap_nopage(int error_code, struct vm_area_struct * area,
89 unsigned long address)
90 {
91 struct inode * inode = area->vm_inode;
92 unsigned int clear;
93 unsigned long page;
94 unsigned long tmp;
95 int n;
96 int i;
97 int pos;
98 struct nfs_fattr fattr;
99
100 address &= PAGE_MASK;
101 pos = address - area->vm_start + area->vm_offset;
102
103 page = get_free_page(GFP_KERNEL);
104 if (share_page(area, area->vm_task, inode, address, error_code, page)) {
105 ++area->vm_task->mm->min_flt;
106 return;
107 }
108
109 ++area->vm_task->mm->maj_flt;
110 if (!page) {
111 oom(current);
112 put_page(area->vm_task, BAD_PAGE, address, PAGE_PRIVATE);
113 return;
114 }
115
116 clear = 0;
117 if (address + PAGE_SIZE > area->vm_end) {
118 clear = address + PAGE_SIZE - area->vm_end;
119 }
120
121 n = NFS_SERVER(inode)->rsize;
122
123 for (i = 0; i < (PAGE_SIZE - clear); i += n) {
124 int hunk, result;
125
126 hunk = PAGE_SIZE - i;
127 if (hunk > n)
128 hunk = n;
129 result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
130 pos, hunk, (char *) (page + i), &fattr);
131 if (result < 0)
132 break;
133 pos += result;
134 if (result < n) {
135 i += result;
136 break;
137 }
138 }
139
140 #ifdef doweneedthishere
141 nfs_refresh_inode(inode, &fattr);
142 #endif
143
144 if (!(error_code & PAGE_RW)) {
145 if (share_page(area, area->vm_task, inode, address, error_code, page))
146 return;
147 }
148
149 tmp = page + PAGE_SIZE;
150 while (clear--) {
151 *(char *)--tmp = 0;
152 }
153 if (put_page(area->vm_task,page,address,area->vm_page_prot))
154 return;
155 free_page(page);
156 oom(current);
157 }